diff --git a/src/makernote_int.cpp b/src/makernote_int.cpp index 092cf90e..20cd7629 100644 --- a/src/makernote_int.cpp +++ b/src/makernote_int.cpp @@ -1185,6 +1185,15 @@ namespace Exiv2 { return aix == 0 ? -1 : aix->idx_; } + int nikonAf2Selector(uint16_t tag, const byte* /*pData*/, uint32_t size, TiffComponent* const /*pRoot*/) + { + int result = tag == 0x00b7 ? 0 : -1 ; + if (result > -1 && size == 84 ) { + result = 1; + } + return result; + } + DataBuf nikonCrypt(uint16_t tag, const byte* pData, uint32_t size, TiffComponent* const pRoot) { DataBuf buf; diff --git a/src/makernote_int.hpp b/src/makernote_int.hpp index a348260e..4acd055f 100644 --- a/src/makernote_int.hpp +++ b/src/makernote_int.hpp @@ -741,6 +741,17 @@ namespace Exiv2 { */ int nikonSelector(uint16_t tag, const byte* pData, uint32_t size, TiffComponent* const pRoot); + /*! + @brief Function to select cfg + def of a Nikon complex binary array. + + @param tag Tag number of the binary array + @param pData Pointer to the raw array data. + @param size Size of the array data. + @param pRoot Pointer to the root component of the TIFF tree. + @return An index into the array set, -1 if no match was found. + */ + int nikonAf2Selector(uint16_t tag, const byte* pData, uint32_t size, TiffComponent* const pRoot); + /*! @brief Encrypt and decrypt Nikon data. diff --git a/src/nikonmn_int.cpp b/src/nikonmn_int.cpp index 4def0e56..6554e4f4 100644 --- a/src/nikonmn_int.cpp +++ b/src/nikonmn_int.cpp @@ -889,29 +889,54 @@ namespace Exiv2 { }; // Nikon3 Auto Focus Tag Info - const TagInfo Nikon3MakerNote::tagInfoAf2_[] = { - TagInfo( 0, "Version", N_("Version"), N_("Version"), nikonAf2Id, makerTags, undefined, 4, printExifVersion), - TagInfo( 4, "ContrastDetectAF", N_("Contrast Detect AF"), N_("Contrast detect AF"), nikonAf2Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonOffOn)), - TagInfo( 5, "AFAreaMode", N_("AF Area Mode"), N_("AF area mode"), nikonAf2Id, makerTags, unsignedByte, 1, printValue), - TagInfo( 6, "PhaseDetectAF", N_("Phase Detect AF"), N_("Phase detect AF"), nikonAf2Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonPhaseDetectAF)), - TagInfo( 7, "PrimaryAFPoint", N_("Primary AF Point"), N_("Primary AF point"), nikonAf2Id, makerTags, unsignedByte, 1, printValue), - TagInfo( 8, "AFPointsUsed", N_("AF Points Used"), N_("AF points used"), nikonAf2Id, makerTags, unsignedByte, 7, printValue), - TagInfo( 16, "AFImageWidth", N_("AF Image Width"), N_("AF image width"), nikonAf2Id, makerTags, unsignedShort, 1, printValue), - TagInfo( 18, "AFImageHeight", N_("AF Image Height"), N_("AF image height"), nikonAf2Id, makerTags, unsignedShort, 1, printValue), - TagInfo( 20, "AFAreaXPosition", N_("AF Area X Position"), N_("AF area x position"), nikonAf2Id, makerTags, unsignedShort, 1, printValue), - TagInfo( 22, "AFAreaYPosition", N_("AF Area Y Position"), N_("AF area y position"), nikonAf2Id, makerTags, unsignedShort, 1, printValue), - TagInfo( 24, "AFAreaWidth", N_("AF Area Width"), N_("AF area width"), nikonAf2Id, makerTags, unsignedShort, 1, printValue), - TagInfo( 26, "AFAreaHeight", N_("AF Area Height"), N_("AF area height"), nikonAf2Id, makerTags, unsignedShort, 1, printValue), - TagInfo( 28, "ContrastDetectAFInFocus", N_("Contrast Detect AF In Focus"), N_("Contrast detect AF in focus"), nikonAf2Id, makerTags, unsignedShort, 1, printValue), + const TagInfo Nikon3MakerNote::tagInfoAf21_[] = { + TagInfo( 0, "Version", N_("Version"), N_("Version"), nikonAf21Id, makerTags, undefined, 4, printExifVersion), + TagInfo( 4, "ContrastDetectAF", N_("Contrast Detect AF"), N_("Contrast detect AF"), nikonAf21Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonOffOn)), + TagInfo( 5, "AFAreaMode", N_("AF Area Mode"), N_("AF area mode"), nikonAf21Id, makerTags, unsignedByte, 1, printValue), + TagInfo( 6, "PhaseDetectAF", N_("Phase Detect AF"), N_("Phase detect AF"), nikonAf21Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonPhaseDetectAF)), + TagInfo( 7, "PrimaryAFPoint", N_("Primary AF Point"), N_("Primary AF point"), nikonAf21Id, makerTags, unsignedByte, 1, printValue), + TagInfo( 8, "AFPointsUsed", N_("AF Points Used"), N_("AF points used"), nikonAf21Id, makerTags, unsignedByte, 7, printValue), + TagInfo( 16, "AFImageWidth", N_("AF Image Width"), N_("AF image width"), nikonAf21Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 18, "AFImageHeight", N_("AF Image Height"), N_("AF image height"), nikonAf21Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 20, "AFAreaXPosition", N_("AF Area X Position"), N_("AF area x position"), nikonAf21Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 22, "AFAreaYPosition", N_("AF Area Y Position"), N_("AF area y position"), nikonAf21Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 24, "AFAreaWidth", N_("AF Area Width"), N_("AF area width"), nikonAf21Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 26, "AFAreaHeight", N_("AF Area Height"), N_("AF area height"), nikonAf21Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 28, "ContrastDetectAFInFocus", N_("Contrast Detect AF In Focus"), N_("Contrast detect AF in focus"), nikonAf21Id, makerTags, unsignedShort, 1, printValue), // End of list marker - TagInfo(0xffff, "(UnknownNikonAf2Tag)", "(UnknownNikonAf2Tag)", N_("Unknown Nikon Auto Focus 2 Tag"), nikonAf2Id, makerTags, unsignedByte, 1, printValue) + TagInfo(0xffff, "(UnknownNikonAf2Tag)", "(UnknownNikonAf2Tag)", N_("Unknown Nikon Auto Focus 2 Tag"), nikonAf21Id, makerTags, unsignedByte, 1, printValue) }; - const TagInfo* Nikon3MakerNote::tagListAf2() + const TagInfo* Nikon3MakerNote::tagListAf21() { - return tagInfoAf2_; + return tagInfoAf21_; } + // Nikon3 Auto Focus Tag Info Version 1.01 https://github.com/Exiv2/exiv2/pull/900 + const TagInfo Nikon3MakerNote::tagInfoAf22_[] = { + TagInfo( 0, "Version", N_("Version"), N_("Version"), nikonAf22Id, makerTags, undefined, 4, printExifVersion), + TagInfo( 4, "ContrastDetectAF", N_("Contrast Detect AF"), N_("Contrast detect AF"), nikonAf22Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonOffOn)), + TagInfo( 5, "AFAreaMode", N_("AF Area Mode"), N_("AF area mode"), nikonAf22Id, makerTags, unsignedByte, 1, printValue), + TagInfo( 6, "PhaseDetectAF", N_("Phase Detect AF"), N_("Phase detect AF"), nikonAf22Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonPhaseDetectAF)), + TagInfo( 7, "PrimaryAFPoint", N_("Primary AF Point"), N_("Primary AF point"), nikonAf22Id, makerTags, unsignedByte, 1, printValue), + TagInfo( 8, "AFPointsUsed", N_("AF Points Used"), N_("AF points used"), nikonAf22Id, makerTags, unsignedByte, 7, printValue), + TagInfo( 70, "AFImageWidth", N_("AF Image Width"), N_("AF image width"), nikonAf22Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 72, "AFImageHeight", N_("AF Image Height"), N_("AF image height"), nikonAf22Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 74, "AFAreaXPosition", N_("AF Area X Position"), N_("AF area x position"), nikonAf22Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 76, "AFAreaYPosition", N_("AF Area Y Position"), N_("AF area y position"), nikonAf22Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 78, "AFAreaWidth", N_("AF Area Width"), N_("AF area width"), nikonAf22Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 80, "AFAreaHeight", N_("AF Area Height"), N_("AF area height"), nikonAf22Id, makerTags, unsignedShort, 1, printValue), + TagInfo( 82, "ContrastDetectAFInFocus", N_("Contrast Detect AF In Focus"), N_("Contrast detect AF in focus"), nikonAf22Id, makerTags, unsignedShort, 1, printValue), + // End of list marker + TagInfo(0xffff, "(UnknownNikonAf2Tag)", "(UnknownNikonAf2Tag)", N_("Unknown Nikon Auto Focus 2 Tag"), nikonAf22Id, makerTags, unsignedByte, 1, printValue) + }; + + const TagInfo* Nikon3MakerNote::tagListAf22() + { + return tagInfoAf22_; + } + + // Nikon3 File Info Tag Info const TagInfo Nikon3MakerNote::tagInfoFi_[] = { TagInfo( 0, "Version", N_("Version"), N_("Version"), nikonFiId, makerTags, undefined, 4, printExifVersion), diff --git a/src/nikonmn_int.hpp b/src/nikonmn_int.hpp index 45a3cdbd..cdac89c0 100644 --- a/src/nikonmn_int.hpp +++ b/src/nikonmn_int.hpp @@ -124,7 +124,9 @@ namespace Exiv2 { //! Return read-only list of built-in Auto Focus tags static const TagInfo* tagListAf(); //! Return read-only list of built-in Auto Focus 2 tags - static const TagInfo* tagListAf2(); + static const TagInfo* tagListAf21(); + //! Return read-only list of built-in Auto Focus 2 tags + static const TagInfo* tagListAf22(); //! Return read-only list of built-in AF Fine Tune tags static const TagInfo* tagListAFT(); //! Return read-only list of built-in File Info tags @@ -235,7 +237,9 @@ namespace Exiv2 { //! Auto Focus tag information static const TagInfo tagInfoAf_[]; //! Auto Focus tag 2 information - static const TagInfo tagInfoAf2_[]; + static const TagInfo tagInfoAf21_[]; + //! Auto Focus tag 2 information + static const TagInfo tagInfoAf22_[]; //! AF Fine Tune tag information static const TagInfo tagInfoAFT_[]; //! File Info tag information diff --git a/src/tags_int.cpp b/src/tags_int.cpp index 902c7f52..c07aa364 100644 --- a/src/tags_int.cpp +++ b/src/tags_int.cpp @@ -106,7 +106,8 @@ namespace Exiv2 { { nikonWtId, "Makernote", "NikonWt", Nikon3MakerNote::tagListWt }, { nikonIiId, "Makernote", "NikonIi", Nikon3MakerNote::tagListIi }, { nikonAfId, "Makernote", "NikonAf", Nikon3MakerNote::tagListAf }, - { nikonAf2Id, "Makernote", "NikonAf2", Nikon3MakerNote::tagListAf2 }, + { nikonAf21Id, "Makernote", "NikonAf2", Nikon3MakerNote::tagListAf21 }, + { nikonAf22Id, "Makernote", "NikonAf22", Nikon3MakerNote::tagListAf22 }, { nikonAFTId, "Makernote", "NikonAFT", Nikon3MakerNote::tagListAFT }, { nikonFiId, "Makernote", "NikonFi", Nikon3MakerNote::tagListFi }, { nikonMeId, "Makernote", "NikonMe", Nikon3MakerNote::tagListMe }, diff --git a/src/tags_int.hpp b/src/tags_int.hpp index 91337e5b..eaa8baf9 100644 --- a/src/tags_int.hpp +++ b/src/tags_int.hpp @@ -99,7 +99,8 @@ namespace Exiv2 { nikonWtId, nikonIiId, nikonAfId, - nikonAf2Id, + nikonAf21Id, + nikonAf22Id, nikonAFTId, nikonFiId, nikonMeId, diff --git a/src/tiffimage_int.cpp b/src/tiffimage_int.cpp index c5aa3565..383c8ee4 100644 --- a/src/tiffimage_int.cpp +++ b/src/tiffimage_int.cpp @@ -221,9 +221,9 @@ namespace Exiv2 { { 2, ttUnsignedShort, 1 } // The array contains 4 bytes }; - //! Nikon Auto Focus 2 binary array - configuration - extern const ArrayCfg nikonAf2Cfg = { - nikonAf2Id, // Group for the elements + //! Nikon Auto Focus 21 binary array - configuration + extern const ArrayCfg nikonAf21Cfg = { + nikonAf21Id, // Group for the elements invalidByteOrder, // Use byte order from parent ttUndefined, // Type for array entry notEncrypted, // Not encrypted @@ -232,8 +232,8 @@ namespace Exiv2 { true, // Concatenate gaps { 0, ttUnsignedByte, 1 } }; - //! Nikon Auto Focus 2 binary array - definition - extern const ArrayDef nikonAf2Def[] = { + //! Nikon Auto Focus 21 binary array - definition + extern const ArrayDef nikonAf21Def[] = { { 0, ttUndefined, 4 }, // Version { 4, ttUnsignedByte, 1 }, // ContrastDetectAF { 5, ttUnsignedByte, 1 }, // AFAreaMode @@ -248,6 +248,39 @@ namespace Exiv2 { { 26, ttUnsignedShort, 1 }, // AFAreaHeight { 28, ttUnsignedShort, 1 }, // ContrastDetectAFInFocus }; + //! Nikon Auto Focus 22 binary array - configuration + extern const ArrayCfg nikonAf22Cfg = { + nikonAf22Id, // Group for the elements + invalidByteOrder, // Byte order + ttUndefined, // Type for array entry + notEncrypted, // Not encrypted + false, // No size element + true, // Write all tags + true, // Concatenate gaps + { 0, ttUnsignedByte, 1 } + }; + //! Nikon Auto Focus 22 binary array - definition + extern const ArrayDef nikonAf22Def[] = { + { 0, ttUndefined, 4 }, // Version + { 4, ttUnsignedByte, 1 }, // ContrastDetectAF + { 5, ttUnsignedByte, 1 }, // AFAreaMode + { 6, ttUnsignedByte, 1 }, // PhaseDetectAF + { 7, ttUnsignedByte, 1 }, // PrimaryAFPoint + { 8, ttUnsignedByte, 7 }, // AFPointsUsed + { 70, ttUnsignedShort, 1 }, // AFImageWidth + { 72, ttUnsignedShort, 1 }, // AFImageHeight + { 74, ttUnsignedShort, 1 }, // AFAreaXPosition + { 76, ttUnsignedShort, 1 }, // AFAreaYPosition + { 78, ttUnsignedShort, 1 }, // AFAreaWidth + { 80, ttUnsignedShort, 1 }, // AFAreaHeight + }; + + //! Nikon AF2 configuration and definitions + // https://github.com/Exiv2/exiv2/issues/646 + extern const ArraySet nikonAf2Set[] = { + { nikonAf21Cfg, nikonAf21Def, EXV_COUNTOF(nikonAf21Def) }, + { nikonAf22Cfg, nikonAf22Def, EXV_COUNTOF(nikonAf22Def) }, + }; //! Nikon AF Fine Tune binary array - configuration extern const ArrayCfg nikonAFTCfg = { @@ -932,7 +965,8 @@ namespace Exiv2 { { Tag::root, nikonLd2Id, nikon3Id, 0x0098 }, { Tag::root, nikonLd3Id, nikon3Id, 0x0098 }, { Tag::root, nikonMeId, nikon3Id, 0x00b0 }, - { Tag::root, nikonAf2Id, nikon3Id, 0x00b7 }, + { Tag::root, nikonAf21Id, nikon3Id, 0x00b7 }, + { Tag::root, nikonAf22Id, nikon3Id, 0x00b7 }, { Tag::root, nikonFiId, nikon3Id, 0x00b8 }, { Tag::root, nikonAFTId, nikon3Id, 0x00b9 }, { Tag::root, nikonFl1Id, nikon3Id, 0x00a8 }, @@ -1274,7 +1308,7 @@ namespace Exiv2 { { 0x0098, nikon3Id, EXV_COMPLEX_BINARY_ARRAY(nikonLdSet, nikonSelector) }, { 0x00a8, nikon3Id, EXV_COMPLEX_BINARY_ARRAY(nikonFlSet, nikonSelector) }, { 0x00b0, nikon3Id, EXV_BINARY_ARRAY(nikonMeCfg, nikonMeDef) }, - { 0x00b7, nikon3Id, EXV_BINARY_ARRAY(nikonAf2Cfg, nikonAf2Def)}, + { 0x00b7, nikon3Id, EXV_COMPLEX_BINARY_ARRAY(nikonAf2Set, nikonAf2Selector) }, { 0x00b8, nikon3Id, EXV_BINARY_ARRAY(nikonFiCfg, nikonFiDef) }, { 0x00b9, nikon3Id, EXV_BINARY_ARRAY(nikonAFTCfg, nikonAFTDef) }, { Tag::all, nikon3Id, newTiffEntry }, @@ -1301,7 +1335,8 @@ namespace Exiv2 { { Tag::all, nikonAfId, newTiffBinaryElement }, // Nikon3 auto focus 2 - { Tag::all, nikonAf2Id, newTiffBinaryElement }, + { Tag::all, nikonAf21Id, newTiffBinaryElement }, + { Tag::all, nikonAf22Id, newTiffBinaryElement }, // Nikon3 AF Fine Tune { Tag::all, nikonAFTId, newTiffBinaryElement }, diff --git a/src/tiffvisitor_int.cpp b/src/tiffvisitor_int.cpp index b633a96a..c98a1c31 100644 --- a/src/tiffvisitor_int.cpp +++ b/src/tiffvisitor_int.cpp @@ -1582,7 +1582,6 @@ namespace Exiv2 { postList_.push_back(object); return; } - // Check duplicates TiffFinder finder(object->tag(), object->group()); pRoot_->accept(finder); diff --git a/test/data/_DSC8437.exv b/test/data/_DSC8437.exv new file mode 100644 index 00000000..d55a6869 Binary files /dev/null and b/test/data/_DSC8437.exv differ diff --git a/tests/bugfixes/github/test_issue_646.py b/tests/bugfixes/github/test_issue_646.py new file mode 100644 index 00000000..854fb5d0 --- /dev/null +++ b/tests/bugfixes/github/test_issue_646.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, path + +class Fix646_NikonAF22(metaclass=CaseMeta): + + url = "http://dev.exiv2.org/issues/646" + filename = "$data_path/_DSC8437.exv" + commands = [ + "$exiv2 -pa --grep NikonAf $filename" +] + stdout = [ + """Exif.NikonAf22.Version Undefined 4 1.01 +Exif.NikonAf22.ContrastDetectAF Byte 1 On +Exif.NikonAf22.AFAreaMode Byte 1 1 +Exif.NikonAf22.PhaseDetectAF Byte 1 Off +Exif.NikonAf22.PrimaryAFPoint Byte 1 0 +Exif.NikonAf22.AFPointsUsed Byte 7 0 0 0 0 0 0 0 +Exif.NikonAf22.AFImageWidth Short 1 8256 +Exif.NikonAf22.AFImageHeight Short 1 5504 +Exif.NikonAf22.AFAreaXPosition Short 1 3950 +Exif.NikonAf22.AFAreaYPosition Short 1 2871 +Exif.NikonAf22.AFAreaWidth Short 1 435 +Exif.NikonAf22.AFAreaHeight Short 1 360 +Exif.NikonAf22.ContrastDetectAFInFocus Byte 2 1 0 +""" + ] + stderr = [ "" ] * len(commands) + retval = [ 0 ] * len(commands)