From 2909e9cacc7423f0df2a00045a883ef0d6a08e52 Mon Sep 17 00:00:00 2001 From: Christoph Hasse Date: Sun, 20 Dec 2020 13:48:42 +0100 Subject: [PATCH] Implement handling of new Nikon LensData version 8.0 and 8.01 --- src/makernote_int.cpp | 2 + src/nikonmn_int.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++ src/nikonmn_int.hpp | 11 +++++ src/tags_int.cpp | 1 + src/tags_int.hpp | 1 + src/tiffimage_int.cpp | 24 +++++++++- 6 files changed, 143 insertions(+), 1 deletion(-) diff --git a/src/makernote_int.cpp b/src/makernote_int.cpp index 25bb3d3f..a61d76ae 100644 --- a/src/makernote_int.cpp +++ b/src/makernote_int.cpp @@ -1171,6 +1171,8 @@ namespace Exiv2 { { 0x0098, "0202", 0, 1, 4 }, { 0x0098, "0203", 0, 1, 4 }, { 0x0098, "0204", 0, 2, 4 }, + { 0x0098, "0800", 0, 3, 4 }, // for e.g. Z6/7 + { 0x0098, "0801", 0, 3, 4 }, // for e.g. Z6/7 // NikonFl { 0x00a8, "0100", 0, 0, NA }, { 0x00a8, "0101", 0, 0, NA }, diff --git a/src/nikonmn_int.cpp b/src/nikonmn_int.cpp index 969d748c..82c7656f 100644 --- a/src/nikonmn_int.cpp +++ b/src/nikonmn_int.cpp @@ -1465,6 +1465,37 @@ namespace Exiv2 { return tagInfoLd3_; } + // Nikon3 Lens Data 4 Tag Info + // based on https://exiftool.org/TagNames/Nikon.html#LensData0800 + const TagInfo Nikon3MakerNote::tagInfoLd4_[] = { + TagInfo( 0, "Version", N_("Version"), N_("Version"), nikonLd4Id, makerTags, undefined, 4, printExifVersion), + TagInfo( 4, "ExitPupilPosition", N_("Exit Pupil Position"), N_("Exit pupil position"), nikonLd4Id, makerTags, unsignedByte, 1, printExitPupilPosition), + TagInfo( 5, "AFAperture", N_("AF Aperture"), N_("AF aperture"), nikonLd4Id, makerTags, unsignedByte, 1, printAperture), + TagInfo( 9, "FocusPosition", N_("Focus Position"), N_("Focus position"), nikonLd4Id, makerTags, unsignedByte, 1, printValue), + TagInfo(11, "FocusDistance", N_("Focus Distance"), N_("Focus distance"), nikonLd4Id, makerTags, unsignedByte, 1, printFocusDistance), + TagInfo(12, "FocalLength", N_("Focal Length"), N_("Focal length"), nikonLd4Id, makerTags, unsignedByte, 1, printFocal), + TagInfo(13, "LensIDNumber", N_("Lens ID Number"), N_("Lens ID number"), nikonLd4Id, makerTags, unsignedByte, 1, printLensId4), + TagInfo(14, "LensFStops", N_("Lens F-Stops"), N_("Lens F-stops"), nikonLd4Id, makerTags, unsignedByte, 1, printFStops), + TagInfo(15, "MinFocalLength", N_("Min Focal Length"), N_("Min focal length"), nikonLd4Id, makerTags, unsignedByte, 1, printFocal), + TagInfo(16, "MaxFocalLength", N_("Max Focal Length"), N_("Max focal length"), nikonLd4Id, makerTags, unsignedByte, 1, printFocal), + TagInfo(17, "MaxApertureAtMinFocal", N_("Max Aperture At Min Focal"), N_("Max aperture at min focal length"), nikonLd4Id, makerTags, unsignedByte, 1, printAperture), + TagInfo(18, "MaxApertureAtMaxFocal", N_("Max Aperture At Max Focal"), N_("Max aperture at max focal length"), nikonLd4Id, makerTags, unsignedByte, 1, printAperture), + TagInfo(19, "MCUVersion", N_("MCU Version"), N_("MCU version"), nikonLd4Id, makerTags, unsignedByte, 1, printValue), + TagInfo(20, "EffectiveMaxAperture", N_("Effective Max Aperture"), N_("Effective max aperture"), nikonLd4Id, makerTags, unsignedByte, 1, printAperture), + TagInfo(48, "LensID", N_("LensID"), N_("Lens ID"), nikonLd4Id, makerTags, unsignedShort, 1, printLensId4ZMount), + TagInfo(54, "MaxAperture", N_("Max Aperture"), N_("Max aperture"), nikonLd4Id, makerTags, unsignedShort, 1, printApertureLd4), + TagInfo(56, "FNumber", N_("F-Number"), N_("F-Number"), nikonLd4Id, makerTags, unsignedShort, 1, printApertureLd4), + TagInfo(60, "FocalLength", N_("Focal Length"), N_("Focal length"), nikonLd4Id, makerTags, unsignedShort, 1, printFocalLd4), + TagInfo(79, "FocusDistance", N_("Focus Distance"), N_("Focus distance"), nikonLd4Id, makerTags, unsignedByte, 1, printFocusDistance), + // End of list marker + TagInfo(0xffff, "(UnknownNikonLd4Tag)", "(UnknownNikonLd4Tag)", N_("Unknown Nikon Lens Data 3 Tag"), nikonLd4Id, makerTags, unsignedByte, 1, printValue) + }; + + const TagInfo* Nikon3MakerNote::tagListLd4() + { + return tagInfoLd4_; + } + std::ostream& Nikon3MakerNote::printIiIso(std::ostream& os, const Value& value, const ExifData*) @@ -1790,6 +1821,13 @@ namespace Exiv2 { return testConfigFile(os,value) ? os : printLensId(os, value, metadata, "NikonLd3"); } + std::ostream& Nikon3MakerNote::printLensId4(std::ostream& os, + const Value& value, + const ExifData* metadata) + { + return testConfigFile(os,value) ? os : printLensId(os, value, metadata, "NikonLd4"); + } + std::ostream& Nikon3MakerNote::printLensId(std::ostream& os, const Value& value, const ExifData* metadata, @@ -2876,4 +2914,71 @@ fmountlens[] = { return os << s; } + std::ostream& Nikon3MakerNote::printLensId4ZMount(std::ostream& os, + const Value& value, + const ExifData*) + { + if (value.count() != 1 || value.typeId() != unsignedShort) { + return os << "(" << value << ")"; + } + +// from https://github.com/exiftool/exiftool/blob/12.12/lib/Image/ExifTool/Nikon.pm#L4646 +static const struct ZMntLens {uint16_t lid; const char *manuf, *lensname;} +zmountlens[] = { + {1 , "Nikon", "Nikkor Z 24-70mm f/4 S"}, + {2 , "Nikon", "Nikkor Z 14-30mm f/4 S"}, + {4 , "Nikon", "Nikkor Z 35mm f/1.8 S"}, + {8 , "Nikon", "Nikkor Z 58mm f/0.95 S Noct"}, //IB + {9 , "Nikon", "Nikkor Z 50mm f/1.8 S"}, + {11 , "Nikon", "Nikkor Z DX 16-50mm f/3.5-6.3 VR"}, + {12 , "Nikon", "Nikkor Z DX 50-250mm f/4.5-6.3 VR"}, + {13 , "Nikon", "Nikkor Z 24-70mm f/2.8 S"}, + {14 , "Nikon", "Nikkor Z 85mm f/1.8 S"}, + {15 , "Nikon", "Nikkor Z 24mm f/1.8 S"}, //IB + {16 , "Nikon", "Nikkor Z 70-200mm f/2.8 VR S"}, //IB + {17 , "Nikon", "Nikkor Z 20mm f/1.8 S"}, //IB + {18 , "Nikon", "Nikkor Z 24-200mm f/4-6.3 VR"}, //IB + {21 , "Nikon", "Nikkor Z 50mm f/1.2 S"}, //IB + {22 , "Nikon", "Nikkor Z 24-50mm f/4-6.3"}, //IB + {23 , "Nikon", "Nikkor Z 14-24mm f/2.8 S"}, //IB + {0 , "", ""} //end of array +}; + + uint16_t lid = value.toLong(); + for(int i{0}; zmountlens[i].lid != 0; ++i){ + if ( zmountlens[i].lid == lid ) return os << zmountlens[i].manuf << " " << zmountlens[i].lensname; + } + return os << lid; + } + + std::ostream& Nikon3MakerNote::printApertureLd4(std::ostream& os, + const Value& value, + const ExifData*) + { + if (value.count() != 1 || value.typeId() != unsignedShort) { + return os << "(" << value << ")"; + } + + double aperture = pow(2.0, value.toLong()/384.0 - 1.0); + std::ostringstream oss; + oss.copyfmt(os); + os << std::fixed << std::setprecision(1) << "F" << aperture; + os.copyfmt(oss); + return os; + } + std::ostream& Nikon3MakerNote::printFocalLd4(std::ostream& os, + const Value& value, + const ExifData*) + { + if (value.count() != 1 || value.typeId() != unsignedShort) { + return os << "(" << value << ")"; + } + std::ostringstream oss; + oss.copyfmt(os); + os << std::fixed << std::setprecision(1) << value.toLong() << " mm"; + os.copyfmt(oss); + return os; + } + + }} // namespace Internal, Exiv2 diff --git a/src/nikonmn_int.hpp b/src/nikonmn_int.hpp index cdac89c0..e777e4ad 100644 --- a/src/nikonmn_int.hpp +++ b/src/nikonmn_int.hpp @@ -167,6 +167,8 @@ namespace Exiv2 { static const TagInfo* tagListLd2(); //! Return read-only list of built-in Lens Data 3 tags static const TagInfo* tagListLd3(); + //! Return read-only list of built-in Lens Data 4 tags + static const TagInfo* tagListLd4(); //! @name Print functions for Nikon3 %MakerNote tags //@{ @@ -195,12 +197,19 @@ namespace Exiv2 { static std::ostream& printLensId1(std::ostream& os, const Value& value, const ExifData* metadata); static std::ostream& printLensId2(std::ostream& os, const Value& value, const ExifData* metadata); static std::ostream& printLensId3(std::ostream& os, const Value& value, const ExifData* metadata); + static std::ostream& printLensId4(std::ostream& os, const Value& value, const ExifData* metadata); + //! Print lensname for ZMount Lens in new LensData as used for e.g. Nikon Z 6/7 + static std::ostream& printLensId4ZMount(std::ostream& os, const Value& value, const ExifData*); //! Print focus distance static std::ostream& printFocusDistance(std::ostream& os, const Value& value, const ExifData*); //! Print lens aperture value static std::ostream& printAperture(std::ostream& os, const Value& value, const ExifData*); + //! Print lens aperture value for new LensData as used for e.g. Nikon Z 6/7 + static std::ostream& printApertureLd4(std::ostream& os, const Value& value, const ExifData*); //! Print lens focal length static std::ostream& printFocal(std::ostream& os, const Value& value, const ExifData*); + //! Print Focal length value for new LensData as used for e.g. Nikon Z 6/7 + static std::ostream& printFocalLd4(std::ostream& os, const Value& value, const ExifData*); //! Print lens f-stops static std::ostream& printFStops(std::ostream& os, const Value& value, const ExifData*); //! Print exit pupil position @@ -280,6 +289,8 @@ namespace Exiv2 { static const TagInfo tagInfoLd2_[]; //! Lens Data 3 tag information static const TagInfo tagInfoLd3_[]; + //! Lens Data 4 tag information + static const TagInfo tagInfoLd4_[]; }; // class Nikon3MakerNote diff --git a/src/tags_int.cpp b/src/tags_int.cpp index 1f9499fa..d6910fb1 100644 --- a/src/tags_int.cpp +++ b/src/tags_int.cpp @@ -129,6 +129,7 @@ namespace Exiv2 { { nikonLd1Id, "Makernote", "NikonLd1", Nikon3MakerNote::tagListLd1 }, { nikonLd2Id, "Makernote", "NikonLd2", Nikon3MakerNote::tagListLd2 }, { nikonLd3Id, "Makernote", "NikonLd3", Nikon3MakerNote::tagListLd3 }, + { nikonLd4Id, "Makernote", "NikonLd4", Nikon3MakerNote::tagListLd4 }, { olympusId, "Makernote", "Olympus", OlympusMakerNote::tagList }, { olympus2Id, "Makernote", "Olympus2", OlympusMakerNote::tagList }, { olympusCsId, "Makernote", "OlympusCs", OlympusMakerNote::tagListCs }, diff --git a/src/tags_int.hpp b/src/tags_int.hpp index 694624cc..f0578e05 100644 --- a/src/tags_int.hpp +++ b/src/tags_int.hpp @@ -116,6 +116,7 @@ namespace Exiv2 { nikonLd1Id, nikonLd2Id, nikonLd3Id, + nikonLd4Id, nikonCb1Id, nikonCb2Id, nikonCb2aId, diff --git a/src/tiffimage_int.cpp b/src/tiffimage_int.cpp index d27d75df..8007a3b3 100644 --- a/src/tiffimage_int.cpp +++ b/src/tiffimage_int.cpp @@ -563,15 +563,35 @@ namespace Exiv2 { false, // Don't concatenate gaps { 0, ttUnsignedByte, 1 } }; + //! Nikon Lens Data binary array - configuration 3 + extern const ArrayCfg nikonLd4Cfg = { + nikonLd4Id, // Group for the elements + invalidByteOrder, // Use byte order from parent + ttUndefined, // Type for array entry + nikonCrypt, // Encryption function + false, // No size element + true, // Write all tags + false, // Don't concatenate gaps + { 0, ttUnsignedByte, 1 } + }; //! Nikon Lens Data binary array - definition extern const ArrayDef nikonLdDef[] = { { 0, ttUndefined, 4 } // Version }; + //! Nikon Lens Data binary array - definition + extern const ArrayDef nikonLd4Def[] = { + { 0, ttUndefined, 4 }, // Version + { 48, ttUnsignedShort, 1 }, // LensID + { 54, ttUnsignedShort, 1 }, // MacAperture + { 56, ttUnsignedShort, 1 }, // FNumber + { 60, ttUnsignedShort, 1 } // FocalLength + }; //! Nikon Lens Data configurations and definitions extern const ArraySet nikonLdSet[] = { { nikonLd1Cfg, nikonLdDef, EXV_COUNTOF(nikonLdDef) }, { nikonLd2Cfg, nikonLdDef, EXV_COUNTOF(nikonLdDef) }, - { nikonLd3Cfg, nikonLdDef, EXV_COUNTOF(nikonLdDef) } + { nikonLd3Cfg, nikonLdDef, EXV_COUNTOF(nikonLdDef) }, + { nikonLd4Cfg, nikonLd4Def, EXV_COUNTOF(nikonLd4Def) } }; //! Nikon Color Balance binary array - configuration 1 @@ -1037,6 +1057,7 @@ namespace Exiv2 { { Tag::root, nikonLd1Id, nikon3Id, 0x0098 }, { Tag::root, nikonLd2Id, nikon3Id, 0x0098 }, { Tag::root, nikonLd3Id, nikon3Id, 0x0098 }, + { Tag::root, nikonLd4Id, nikon3Id, 0x0098 }, { Tag::root, nikonMeId, nikon3Id, 0x00b0 }, { Tag::root, nikonAf21Id, nikon3Id, 0x00b7 }, { Tag::root, nikonAf22Id, nikon3Id, 0x00b7 }, @@ -1453,6 +1474,7 @@ namespace Exiv2 { { Tag::all, nikonLd1Id, newTiffBinaryElement }, { Tag::all, nikonLd2Id, newTiffBinaryElement }, { Tag::all, nikonLd3Id, newTiffBinaryElement }, + { Tag::all, nikonLd4Id, newTiffBinaryElement }, // Panasonic makernote { Tag::next, panasonicId, ignoreTiffComponent },