diff --git a/src/makernote_int.cpp b/src/makernote_int.cpp index f99a8353..246a2afc 100644 --- a/src/makernote_int.cpp +++ b/src/makernote_int.cpp @@ -1190,6 +1190,18 @@ namespace Exiv2 { }; return std::find(std::begin(models), std::end(models), getExifModel(pRoot)) != std::end(models) ? 0 : -1; } + int sony2FpSelector(uint16_t /*tag*/, const byte* /*pData*/, uint32_t /*size*/, TiffComponent* const pRoot) + { + // Not valid for models beginning + const char* models[] = { "SLT-", "HV", "ILCA-" }; + + std::string model = getExifModel(pRoot); + for (auto&& m : models) { + if (model.find(m) == 0) + return -1; + } + return 0; + } } // namespace Internal } // namespace Exiv2 diff --git a/src/makernote_int.hpp b/src/makernote_int.hpp index 3c7fa7ee..abc1aa09 100644 --- a/src/makernote_int.hpp +++ b/src/makernote_int.hpp @@ -707,6 +707,17 @@ namespace Exiv2 { */ int sony2010eSelector(uint16_t tag, const byte* pData, uint32_t size, TiffComponent* const pRoot); + /*! + @brief Function to select cfg + def of the Sony2Fp (tag 9402) 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 sony2FpSelector(uint16_t tag, const byte* pData, uint32_t size, TiffComponent* const pRoot); + /*! @brief Function to select cfg + def of a Nikon complex binary array. diff --git a/src/sonymn_int.cpp b/src/sonymn_int.cpp index 4f4f3ad7..a682ab68 100644 --- a/src/sonymn_int.cpp +++ b/src/sonymn_int.cpp @@ -25,6 +25,7 @@ #include "tags_int.hpp" #include "tiffcomposite_int.hpp" #include "value.hpp" +#include "exif.hpp" #include "i18n.h" // NLS support. // + standard includes @@ -791,14 +792,29 @@ namespace Exiv2 { return tagInfoCs2_; } + //! Lookup table to translate Sony2Fp AF Area Mode values to readable labels + constexpr TagDetails sony2FpAFAreaMode[] = { + { 0, N_("Multi") }, + { 1, N_("Center") }, + { 2, N_("Spot") }, + { 3, N_("Flexible Spot") }, + { 10, N_("Selective (for Miniature effect)") }, + { 11, N_("Zone") }, + { 12, N_("Expanded Flexible Spot") }, + { 14, N_("Tracking") }, + { 15, N_("Face Tracking") }, + { 20, N_("Animal Eye Tracking") }, + { 255, N_("Manual") } + }; + //! Sony Tag 9402 Sony2Fp (FocusPosition) constexpr TagInfo SonyMakerNote::tagInfoFp_[] = { - { 0x04, "AmbientTemperature", N_("Ambient Temperature"), N_("Ambient Temperature"), sony2FpId, makerTags, signedByte, 1, printValue}, - { 0x16, "FocusMode" , N_("Focus Mode") , N_("Focus Mode") , sony2FpId, makerTags, unsignedByte, 1, printValue}, - { 0x17, "AFAreaMode" , N_("AF Area Mode") , N_("AF Area Mode") , sony2FpId, makerTags, unsignedByte, 1, printValue}, - { 0x2d, "FocusPosition2" , N_("Focus Position 2") , N_("Focus Position 2") , sony2FpId, makerTags, unsignedByte, 1, printValue}, + { 0x04, "AmbientTemperature", N_("Ambient temperature"), N_("Temperature of the surroundings (in degrees Celsius)"), sony2FpId, makerTags, signedByte, 1, printTemperatureInDegC}, + { 0x16, "FocusMode" , N_("Focus mode") , N_("Focus mode") , sony2FpId, makerTags, unsignedByte, 1, printSony2FpFocusMode}, + { 0x17, "AFAreaMode" , N_("AF area mode") , N_("Auto focus area mode"), sony2FpId, makerTags, unsignedByte, 1, EXV_PRINT_TAG(sony2FpAFAreaMode)}, + { 0x2d, "FocusPosition2" , N_("Focus position 2") , N_("Focus position 2") , sony2FpId, makerTags, unsignedByte, 1, printSony2FpFocusPosition2}, // End of list marker - {0xffff, "(Unknownsony2FpTag)", "(Unknownsony2FpTag)" , "(Unknownsony2FpTag)" , sony2FpId, makerTags, unsignedByte, 1, printValue}, + {0xffff, "(UnknownSony2FpTag)", "(UnknownSony2FpTag)" , "(UnknownSony2FpTag)" , sony2FpId, makerTags, unsignedByte, 1, printValue}, }; const TagInfo* SonyMakerNote::tagListFp() @@ -806,6 +822,57 @@ namespace Exiv2 { return tagInfoFp_; } + std::ostream& SonyMakerNote::printSony2FpFocusMode(std::ostream& os, const Value& value, const ExifData*) + { + if (value.count() != 1) + os << value; + else { + long val = (value.toLong() & 0x7F); + if (val == 0) + os << N_("Manual"); + else if (val == 2) + os << N_("AF-S"); + else if (val == 3) + os << N_("AF-C"); + else if (val == 4) + os << N_("AF-A"); + else if (val == 6) + os << N_("DMF"); + else + os << "(" << val << ")"; + } + + return os; + } + + std::ostream& SonyMakerNote::printSony2FpFocusPosition2(std::ostream& os, const Value& value, const ExifData* metadata) + { + if (value.count() != 1) + os << "(" << value << ")"; + else { + auto pos = metadata->findKey(ExifKey("Exif.Image.Model")); + if (pos == metadata->end()) + return os << "(" << value << ")"; + + // Ranges of models that do not support this tag + const char* models[] = { "DSC-", "Stellar" }; + + std::string model = pos->toString(); + for (auto&& m : models) { + if (model.find(m) == 0) { + os << N_("n/a"); + return os; + } + } + long val = value.toLong(); + if (val == 255) + os << N_("Infinity"); + else + os << val; + } + return os; + } + //! Sony Tag 9403 SonyMisc1 constexpr TagInfo SonyMakerNote::tagInfoSonyMisc1_[] = { {0x05, "CameraTemperature", N_("Camera temperature"), diff --git a/src/sonymn_int.hpp b/src/sonymn_int.hpp index 84121a86..71764bd2 100644 --- a/src/sonymn_int.hpp +++ b/src/sonymn_int.hpp @@ -56,7 +56,11 @@ namespace Exiv2 { //! @name Print functions for Sony %MakerNote tags //@{ - //! Print Sony temperature values (in Degrees Celsius) + //! Print Sony2Fp Focus Mode value + static std::ostream& printSony2FpFocusMode(std::ostream&, const Value&, const ExifData*); + //! Print Sony2Fp Focus Position 2 value + static std::ostream& printSony2FpFocusPosition2(std::ostream&, const Value&, const ExifData* metadata); + //! Print Sony temperature values (in degrees Celsius) static std::ostream& printTemperatureInDegC(std::ostream&, const Value&, const ExifData*); //! Print Sony Camera Model static std::ostream& print0xb000(std::ostream&, const Value&, const ExifData*); diff --git a/src/tiffimage_int.cpp b/src/tiffimage_int.cpp index 089bd4e2..7ffedf67 100644 --- a/src/tiffimage_int.cpp +++ b/src/tiffimage_int.cpp @@ -826,6 +826,11 @@ namespace Exiv2 { { 0x2d, ttUnsignedByte, 1 } // Exif.Sony2Fp.FocusPosition2 }; + //! Sony2Fp configurations and definitions + constexpr ArraySet sony2FpSet[] = { + { sony2FpCfg, sony2FpDef, EXV_COUNTOF(sony2FpDef) } + }; + constexpr ArrayCfg sonyMisc1Cfg = { sonyMisc1Id, // Group for the elements bigEndian, // Big endian @@ -1559,7 +1564,7 @@ namespace Exiv2 { // Tag 0x9402 Sony2Fp Focus Position { Tag::all, sony2FpId, newTiffBinaryElement }, - { 0x9402, sony1Id, EXV_BINARY_ARRAY(sony2FpCfg, sony2FpDef) }, + { 0x9402, sony1Id, EXV_COMPLEX_BINARY_ARRAY(sony2FpSet, sony2FpSelector) }, // Tag 0x9403 SonyMisc1 { Tag::all, sonyMisc1Id, newTiffBinaryElement }, @@ -1580,7 +1585,7 @@ namespace Exiv2 { // Tag 0x9402 Sony2Fp Focus Position { Tag::all, sony2FpId, newTiffBinaryElement }, - { 0x9402, sony2Id, EXV_BINARY_ARRAY(sony2FpCfg, sony2FpDef) }, + { 0x9402, sony2Id, EXV_COMPLEX_BINARY_ARRAY(sony2FpSet, sony2FpSelector) }, // Tag 0x9403 SonyMisc1 { Tag::all, sonyMisc1Id, newTiffBinaryElement }, diff --git a/tests/bugfixes/github/test_pr_906.py b/tests/bugfixes/github/test_pr_906.py index d87bc474..00fcda4d 100644 --- a/tests/bugfixes/github/test_pr_906.py +++ b/tests/bugfixes/github/test_pr_906.py @@ -7,9 +7,9 @@ class Sony2FpTest(metaclass=CaseMeta): filename = path("$data_path/exiv2-pr906.exv") commands = ["$exiv2 -pa --grep Sony2Fp $filename"] - stdout = ["""Exif.Sony2Fp.AmbientTemperature SByte 1 19 -Exif.Sony2Fp.FocusMode Byte 1 6 -Exif.Sony2Fp.AFAreaMode Byte 1 12 + stdout = ["""Exif.Sony2Fp.AmbientTemperature SByte 1 19 °C +Exif.Sony2Fp.FocusMode Byte 1 DMF +Exif.Sony2Fp.AFAreaMode Byte 1 Expanded Flexible Spot Exif.Sony2Fp.FocusPosition2 Byte 1 140 """ ]