diff --git a/doc/templates/Makefile b/doc/templates/Makefile
index 04dea6a2..4b2b2422 100644
--- a/doc/templates/Makefile
+++ b/doc/templates/Makefile
@@ -76,6 +76,7 @@ TABLES = Exif \
NikonFl1 \
NikonFl2 \
NikonFl3 \
+ NikonFl7 \
NikonSiD80 \
NikonSiD40 \
NikonSiD300a \
diff --git a/doc/templates/tags-nikon.html.in b/doc/templates/tags-nikon.html.in
index 9110c249..4f2ec5fd 100644
--- a/doc/templates/tags-nikon.html.in
+++ b/doc/templates/tags-nikon.html.in
@@ -91,6 +91,11 @@ __NikonFl2__
__NikonFl3__
+
Nikon Flash Info 7 Tags (for version 0107 and 0108)
+Click on a column header to sort the table.
+__NikonFl7__
+
+
Nikon Shot Info D80 Tags
Click on a column header to sort the table.
__NikonSiD80__
diff --git a/exiv2.md b/exiv2.md
index e46610d2..7243df44 100644
--- a/exiv2.md
+++ b/exiv2.md
@@ -793,19 +793,19 @@ Image CanonCf Nikon2 NikonPc OlympusFe9 SonyMisc3c
Image2 CanonCs Nikon3 NikonPreview OlympusFi SonyMinolta
Image3 CanonFi NikonAFT NikonSi01xx OlympusIp SonySInfo1
Iop CanonPa NikonAf NikonSi02xx OlympusRd
-MakerNote CanonPi NikonAf NikonSiD300a OlympusRd2 Samsung2
-MpfInfo CanonPr NikonAf2 NikonSiD300b OlympusRi SamsungPictureWizard
-Photo CanonSi NikonAf22 NikonSiD40 SamsungPreview
-SubImage1 CanonTi NikonCb1 NikonSiD80 Sigma
-SubImage2 NikonCb2 NikonVr
-SubImage3 Casio NikonCb2a NikonWt Sony1
-SubImage4 Casio2 NikonCb2b Sony1Cs
-SubImage5 NikonCb3 Olympus Sony1Cs2
-SubImage6 Minolta NikonCb4 Olympus2 Sony1MltCs7D
-SubImage7 MinoltaCs5D NikonFi OlympusCs Sony1MltCsA100
-SubImage8 MinoltaCs7D NikonFl1 OlympusEq Sony1MltCsNew
-SubImage9 MinoltaCsNew NikonFl2 OlympusFe1 Sony1MltCsOld
-SubThumb1 MinoltaCsOld NikonFl3 OlympusFe2 Sony2
+MakerNote CanonPi NikonAf2 NikonSiD300a OlympusRd2 Samsung2
+MpfInfo CanonPr NikonAf22 NikonSiD300b OlympusRi SamsungPictureWizard
+Photo CanonSi NikonCb1 NikonSiD40 SamsungPreview
+SubImage1 CanonTi NikonCb2 NikonSiD80 Sigma
+SubImage2 NikonCb2a NikonVr
+SubImage3 Casio NikonCb2b NikonWt Sony1
+SubImage4 Casio2 NikonCb3 Sony1Cs
+SubImage5 NikonCb4 Olympus Sony1Cs2
+SubImage6 Minolta NikonFi Olympus2 Sony1MltCs7D
+SubImage7 MinoltaCs5D NikonFl1 OlympusCs Sony1MltCsA100
+SubImage8 MinoltaCs7D NikonFl2 OlympusEq Sony1MltCsNew
+SubImage9 MinoltaCsNew NikonFl3 OlympusFe1 Sony1MltCsOld
+SubThumb1 MinoltaCsOld NikonFl7 OlympusFe2 Sony2
Thumbnail NikonIi OlympusFe3 Sony2Cs
Panasonic NikonLd1 OlympusFe4 Sony2Cs2
Pentax PanasonicRaw NikonLd2 OlympusFe5 Sony2010e
diff --git a/src/makernote_int.cpp b/src/makernote_int.cpp
index 6d66cccc..939d0d4b 100644
--- a/src/makernote_int.cpp
+++ b/src/makernote_int.cpp
@@ -1139,6 +1139,8 @@ namespace Exiv2 {
{ 0x00a8, "0101", 0, 0, NA },
{ 0x00a8, "0102", 0, 1, NA },
{ 0x00a8, "0103", 0, 2, NA },
+ { 0x00a8, "0107", 0, 3, NA },
+ { 0x00a8, "0108", 0, 3, NA },
};
int nikonSelector(uint16_t tag, const byte* pData, uint32_t size, TiffComponent* const /*pRoot*/)
diff --git a/src/nikonmn_int.cpp b/src/nikonmn_int.cpp
index fd913bed..631b0139 100644
--- a/src/nikonmn_int.cpp
+++ b/src/nikonmn_int.cpp
@@ -38,6 +38,8 @@
#include
#include
#include //for log, pow, abs
+#include
+#include
// *****************************************************************************
// class member definitions
@@ -1050,7 +1052,6 @@ namespace Exiv2 {
{ 5, N_("GN (distance priority)") },
{ 6, N_("Manual") },
{ 7, N_("Repeating Flash") },
- { 7, N_("Repeating Flash") } // To silence compiler warning
};
//! ExternalFlashFlags
@@ -1135,6 +1136,32 @@ namespace Exiv2 {
return tagInfoFl3_;
}
+ // Nikon3 Flash Info 7 (0107 and 0108) Tag Info
+ constexpr TagInfo Nikon3MakerNote::tagInfoFl7_[] = {
+ { 0, "Version", N_("Version"), N_("Flash info version"), nikonFl7Id, makerTags, undefined, 4, printExifVersion},
+ { 4, "FlashSource", N_("Flash source"), N_("The type of flash used (if any)"), nikonFl7Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonFlashSource)},
+ { 6, "ExternalFlashFirmware", N_("External Flash Firmware"), N_("External flash firmware version"), nikonFl7Id, makerTags, unsignedShort, 1, EXV_PRINT_TAG(nikonFlashFirmware)},
+ { 8, "ExternalFlashData1", N_("External flash data"), N_("External flash data"), nikonFl7Id, makerTags, unsignedByte, 1, printExternalFlashData1},
+ { 9, "ExternalFlashData2", N_("External flash ready state"), N_("External flash ready state"), nikonFl7Id, makerTags, unsignedByte, 1, printExternalFlashData2},
+ { 10, "FlashCompensation", N_("Flash compensation"), N_("Flash compensation"), nikonFl7Id, makerTags, signedByte, 1, printFlashCompensation},
+ { 12, "FlashFocalLength", N_("Flash focal length"), N_("Flash focal length"), nikonFl7Id, makerTags, unsignedByte, 1, printFlashFocalLength},
+ { 13, "RepeatingFlashRate", N_("Repeating flash rate"), N_("Repeating flash rate"), nikonFl7Id, makerTags, unsignedByte, 1, printRepeatingFlashRate},
+ { 14, "RepeatingFlashCount", N_("Repeating flash count"), N_("Repeating flash count"), nikonFl7Id, makerTags, unsignedByte, 1, printRepeatingFlashCount},
+ { 15, "FlashGNDistance", N_("Flash GN Distance"), N_("Flash GN distance"), nikonFl7Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonFlashGNDistance)},
+ { 17, "FlashGroupAControlData", N_("Flash group A control data"), N_("Flash group A control data"), nikonFl7Id, makerTags, unsignedByte, 1, EXV_PRINT_TAG(nikonFlashControlMode)},
+ { 18, "FlashGroupBCControlData", N_("Flash group B/C control data"), N_("Flash group B/C control data"), nikonFl7Id, makerTags, unsignedByte, 1, printFlashGroupBCControlData},
+ { 40, "FlashGroupAData", N_("Flash group A data"), N_("Depending upon FlashGroupAControlData, either the FlashGroupACompensation value or the FlashGroupAOutput value"), nikonFl7Id, makerTags, unsignedByte, 1, printFlashGroupAData},
+ { 41, "FlashGroupBData", N_("Flash group B data"), N_("Depending upon FlashGroupBCControlData, either the FlashGroupBCompensation value or the FlashGroupBOutput value"), nikonFl7Id, makerTags, unsignedByte, 1, printFlashGroupBData},
+ { 42, "FlashGroupCData", N_("Flash group C data"), N_("Depending upon FlashGroupBCControlData, either the FlashGroupCCompensation value or the FlashGroupCOutput value"), nikonFl7Id, makerTags, unsignedByte, 1, printFlashGroupCData},
+ // End of list marker
+ {0xffff, "(UnknownNikonFl7Tag)", "(UnknownNikonFl7Tag)", N_("Unknown Nikon Flash Info 7 Tag"), nikonFl7Id, makerTags, unsignedByte, 1, printValue},
+ };
+
+ const TagInfo* Nikon3MakerNote::tagListFl7()
+ {
+ return tagInfoFl7_;
+ }
+
// Nikon3 Shot Info D80 Tag Info
constexpr TagInfo Nikon3MakerNote::tagInfoSi1_[] = {
{ 0, "Version", N_("Version"), N_("Version"), nikonSi1Id, makerTags, unsignedByte, 4, printExifVersion},
@@ -2772,14 +2799,18 @@ fmountlens[] = {
const ExifData*)
{
std::ios::fmtflags f( os.flags() );
- if (value.count() != 1 || value.typeId() != unsignedByte || value.toLong() == 0 || value.toLong() == 255) {
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
os << "(" << value << ")";
os.flags(f);
return os;
}
+ auto temp = value.toLong();
+ if (temp == 0 || temp == 255)
+ return os << _("n/a");
+
std::ostringstream oss;
oss.copyfmt(os);
- os << std::fixed << std::setprecision(1) << value.toLong() << " mm";
+ os << std::fixed << std::setprecision(1) << temp << " mm";
os.copyfmt(oss);
os.flags(f);
return os;
@@ -2790,12 +2821,16 @@ fmountlens[] = {
const ExifData*)
{
std::ios::fmtflags f( os.flags() );
- if (value.count() != 1 || value.typeId() != unsignedByte || value.toLong() == 0 || value.toLong() == 255) {
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
return os << "(" << value << ")";
}
+ auto temp = value.toLong();
+ if (temp == 0 || temp == 255)
+ return os << _("n/a");
+
std::ostringstream oss;
oss.copyfmt(os);
- os << std::fixed << std::setprecision(2) << value.toLong() << " Hz";
+ os << std::fixed << std::setprecision(2) << temp << " Hz";
os.copyfmt(oss);
os.flags(f);
return os;
@@ -2806,12 +2841,250 @@ fmountlens[] = {
const ExifData*)
{
std::ios::fmtflags f( os.flags() );
- if (value.count() != 1 || value.typeId() != unsignedByte || value.toLong() == 0 || value.toLong() == 255) {
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
return os << "(" << value << ")";
}
+ auto temp = value.toLong();
+ if (temp == 0 || temp == 255)
+ return os << _("n/a");
+
+ std::ostringstream oss;
+ oss.copyfmt(os);
+ os << std::fixed << std::setprecision(2) << temp;
+ os.copyfmt(oss);
+ os.flags(f);
+ return os;
+ }
+
+ std::ostream& Nikon3MakerNote::printExternalFlashData1(std::ostream& os,
+ const Value& value,
+ const ExifData*)
+ {
+ std::ios::fmtflags f( os.flags() );
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ os.flags(f);
+ return os;
+ }
+ std::ostringstream oss;
+ oss.copyfmt(os);
+ os << (value.toLong() & 0x80 ? _("External flash zoom override") : _("No external flash zoom override"));
+ os << ", ";
+ os << (value.toLong() & 0x01 ? _("external flash attached") : _("external flash not attached"));
+
+ os.copyfmt(oss);
+ os.flags(f);
+ return os;
+ }
+
+ std::ostream& Nikon3MakerNote::printExternalFlashData2(std::ostream& os,
+ const Value& value,
+ const ExifData*)
+ {
+ std::ios::fmtflags f( os.flags() );
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ os.flags(f);
+ return os;
+ }
+
std::ostringstream oss;
oss.copyfmt(os);
- os << std::fixed << std::setprecision(2) << value.toLong();
+ long temp = value.toLong();
+
+ switch (temp & 0x07) {
+ case 0:
+ os << _("n/a");
+ break;
+ case 1:
+ os << _("Ready");
+ break;
+ case 6:
+ os << _("Not ready");
+ break;
+ default:
+ os << "(" << temp << ")";
+ break;
+ }
+
+ os.copyfmt(oss);
+ os.flags(f);
+ return os;
+ }
+
+ std::ostream& Nikon3MakerNote::printFlashCompensation(std::ostream& os,
+ const Value& value,
+ const ExifData*)
+ {
+ std::ios::fmtflags f( os.flags() );
+ if (value.count() != 1 || value.typeId() != signedByte) {
+ os << "(" << value << ")";
+ os.flags(f);
+ return os;
+ }
+ std::ostringstream oss;
+ oss.copyfmt(os);
+ float temp = ( value.toFloat()/float(-6.0) );
+
+ if (temp == 0)
+ os << 0;
+ else if (!std::isfinite(temp))
+ os << "(" << value << ")";
+ else if (std::abs(std::remainderf(temp, 1)) < 0.001)
+ os << std::round(temp);
+ else if (std::abs(std::remainderf(temp*2, 1)) < 0.001)
+ os << std::round(temp*2) << "/2";
+ else if (std::abs(std::remainderf(temp*3, 1)) < 0.001)
+ os << std::round(temp*3) << "/3";
+ else
+ os << std::setprecision(3) << temp;
+
+ os.copyfmt(oss);
+ os.flags(f);
+ return os;
+ }
+
+ std::ostream& Nikon3MakerNote::printFlashGroupBCControlData(std::ostream& os,
+ const Value& value,
+ const ExifData* data)
+ {
+ std::ios::fmtflags f( os.flags() );
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ os.flags(f);
+ return os;
+ }
+ std::ostringstream oss;
+ oss.copyfmt(os);
+ long temp = value.toLong();
+
+ printTag(os, (temp >> 4), data);
+ os << ", ";
+ printTag(os, (temp & 0x0f), data);
+
+ os.copyfmt(oss);
+ os.flags(f);
+ return os;
+ }
+
+ std::ostream& Nikon3MakerNote::printFlashGroupAData(std::ostream& os,
+ const Value& value,
+ const ExifData* metadata)
+ {
+ std::ios::fmtflags f( os.flags() );
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ os.flags(f);
+ return os;
+ }
+
+ std::ostringstream oss;
+ oss.copyfmt(os);
+ double temp = value.toFloat()/double(-6.0);
+
+ auto pos = metadata->findKey(ExifKey("Exif.NikonFl7.FlashGroupAControlData"));
+ if (pos == metadata->end() || pos-> count() != 1 || pos->typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ }
+ else {
+ if (pos->toLong() < 0x06) {
+ // FlashGroupACompensation value
+ if (temp == 0)
+ os << 0;
+ else
+ os << std::fixed << std::setprecision(1) << temp;
+ }
+ else {
+ // FlashGroupAOutput value
+ double flashGroupAOutput = std::exp2(temp);
+ if (flashGroupAOutput > 0.99)
+ os << _("Full");
+ else
+ os << std::setprecision(2) << std::round(flashGroupAOutput*100) << "%";
+ }
+ }
+ os.copyfmt(oss);
+ os.flags(f);
+ return os;
+ }
+
+ std::ostream& Nikon3MakerNote::printFlashGroupBData(std::ostream& os,
+ const Value& value,
+ const ExifData* metadata)
+ {
+ std::ios::fmtflags f( os.flags() );
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ os.flags(f);
+ return os;
+ }
+
+ std::ostringstream oss;
+ oss.copyfmt(os);
+ double temp = value.toFloat()/double(-6.0);
+
+ auto pos = metadata->findKey(ExifKey("Exif.NikonFl7.FlashGroupBCControlData"));
+ if (pos == metadata->end() || pos-> count() != 1 || pos->typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ }
+ else {
+ if (pos->toLong() < 0x06) {
+ // FlashGroupBCompensation value
+ if (temp == 0)
+ os << 0;
+ else
+ os << std::fixed << std::setprecision(1) << temp;
+ }
+ else {
+ // FlashGroupBOutput value
+ double flashGroupAOutput = std::exp2(temp);
+ if (flashGroupAOutput > 0.99)
+ os << _("Full");
+ else
+ os << std::setprecision(2) << std::round(flashGroupAOutput*100) << "%";
+ }
+ }
+ os.copyfmt(oss);
+ os.flags(f);
+ return os;
+ }
+
+ std::ostream& Nikon3MakerNote::printFlashGroupCData(std::ostream& os,
+ const Value& value,
+ const ExifData* metadata)
+ {
+ std::ios::fmtflags f( os.flags() );
+ if (value.count() != 1 || value.typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ os.flags(f);
+ return os;
+ }
+
+ std::ostringstream oss;
+ oss.copyfmt(os);
+ double temp = value.toFloat()/double(-6.0);
+
+ auto pos = metadata->findKey(ExifKey("Exif.NikonFl7.FlashGroupBCControlData"));
+ if (pos == metadata->end() || pos-> count() != 1 || pos->typeId() != unsignedByte) {
+ os << "(" << value << ")";
+ }
+ else {
+ if (pos->toLong() < 0x06) {
+ // FlashGroupCCompensation value
+ if (temp == 0)
+ os << 0;
+ else
+ os << std::fixed << std::setprecision(1) << temp;
+ }
+ else {
+ // FlashGroupCOutput value
+ double flashGroupAOutput = std::exp2(temp);
+ if (flashGroupAOutput > 0.99)
+ os << _("Full");
+ else
+ os << std::setprecision(2) << std::round(flashGroupAOutput*100) << "%";
+ }
+ }
os.copyfmt(oss);
os.flags(f);
return os;
diff --git a/src/nikonmn_int.hpp b/src/nikonmn_int.hpp
index 070d2cdb..37fba84c 100644
--- a/src/nikonmn_int.hpp
+++ b/src/nikonmn_int.hpp
@@ -130,6 +130,8 @@ namespace Exiv2 {
static const TagInfo* tagListFl2();
//! Return read-only list of built-in Flash Info 3 tags
static const TagInfo* tagListFl3();
+ //! Return read-only list of built-in Flash Info 7 (0107 and 0108) tags
+ static const TagInfo* tagListFl7();
//! Return read-only list of built-in Shot Info D80 tags
static const TagInfo* tagListSi1();
//! Return read-only list of built-in Shot Info D40 tags
@@ -217,6 +219,20 @@ namespace Exiv2 {
static std::ostream& printRepeatingFlashRate(std::ostream& os, const Value& value, const ExifData*);
//! Print repeating flash count
static std::ostream& printRepeatingFlashCount(std::ostream& os, const Value& value, const ExifData*);
+ //! Print external flash data 1 value
+ static std::ostream& printExternalFlashData1(std::ostream& os, const Value& value, const ExifData*);
+ //! Print external flash data 2 value
+ static std::ostream& printExternalFlashData2(std::ostream& os, const Value& value, const ExifData*);
+ //! Print flash compensation value
+ static std::ostream& printFlashCompensation(std::ostream& os, const Value& value, const ExifData*);
+ //! Print flash group B/C control data value
+ static std::ostream& printFlashGroupBCControlData(std::ostream& os, const Value& value, const ExifData* data);
+ //! Print flash group A data value
+ static std::ostream& printFlashGroupAData(std::ostream& os, const Value& value, const ExifData*);
+ //! Print flash group B data value
+ static std::ostream& printFlashGroupBData(std::ostream& os, const Value& value, const ExifData*);
+ //! Print flash group C data value
+ static std::ostream& printFlashGroupCData(std::ostream& os, const Value& value, const ExifData*);
//! Print time zone
static std::ostream& printTimeZone(std::ostream& os, const Value& value, const ExifData*);
//! Print picture control value
@@ -252,6 +268,8 @@ namespace Exiv2 {
static const TagInfo tagInfoFl2_[];
//! Flash Info 3 tag information
static const TagInfo tagInfoFl3_[];
+ //! Flash Info 7 (0107 and 0108) tag information
+ static const TagInfo tagInfoFl7_[];
//! Shot Info D80 tag information
static const TagInfo tagInfoSi1_[];
//! Shot Info D40 tag information
diff --git a/src/tags_int.cpp b/src/tags_int.cpp
index 6466ca19..7bf2fc13 100644
--- a/src/tags_int.cpp
+++ b/src/tags_int.cpp
@@ -115,6 +115,7 @@ namespace Exiv2 {
{ nikonFl1Id, "Makernote", "NikonFl1", Nikon3MakerNote::tagListFl1 },
{ nikonFl2Id, "Makernote", "NikonFl2", Nikon3MakerNote::tagListFl2 },
{ nikonFl3Id, "Makernote", "NikonFl3", Nikon3MakerNote::tagListFl3 },
+ { nikonFl7Id, "Makernote", "NikonFl7", Nikon3MakerNote::tagListFl7 },
{ nikonSi1Id, "Makernote", "NikonSiD80", Nikon3MakerNote::tagListSi1 },
{ nikonSi2Id, "Makernote", "NikonSiD40", Nikon3MakerNote::tagListSi2 },
{ nikonSi3Id, "Makernote", "NikonSiD300a", Nikon3MakerNote::tagListSi3 },
diff --git a/src/tags_int.hpp b/src/tags_int.hpp
index da48f744..649c4c1c 100644
--- a/src/tags_int.hpp
+++ b/src/tags_int.hpp
@@ -125,6 +125,7 @@ namespace Exiv2 {
nikonFl1Id,
nikonFl2Id,
nikonFl3Id,
+ nikonFl7Id,
nikonSi1Id,
nikonSi2Id,
nikonSi3Id,
@@ -266,9 +267,9 @@ namespace Exiv2 {
by looking up a reference table.
*/
template
- std::ostream& printTag(std::ostream& os, const Value& value, const ExifData*)
+ std::ostream& printTag(std::ostream& os, const long& value, const ExifData*)
{
- const TagDetails* td = find(array, value.toLong());
+ const TagDetails* td = find(array, value);
if (td) {
os << exvGettext(td->label_);
}
@@ -278,7 +279,17 @@ namespace Exiv2 {
return os;
}
-//! Shortcut for the printTag template which requires typing the array name only once.
+ /*!
+ @brief Generic pretty-print function to translate the first long value in Value, to a description
+ by looking up a reference table.
+ */
+ template
+ std::ostream& printTag(std::ostream& os, const Value& value, const ExifData* data)
+ {
+ return printTag(os, value.toLong(), data);
+ }
+
+ //! Shortcut for the printTag template which requires typing the array name only once.
#define EXV_PRINT_TAG(array) printTag
/*!
diff --git a/src/tiffimage_int.cpp b/src/tiffimage_int.cpp
index da740bc2..90100377 100644
--- a/src/tiffimage_int.cpp
+++ b/src/tiffimage_int.cpp
@@ -427,11 +427,42 @@ namespace Exiv2 {
{ 15, ttUnsignedByte, 1 }, // FlashGNDistance
{ 16, ttUnsignedByte, 1 }, // FlashColorFilter
};
- //! Nikon Lens Data configurations and definitions
+ //! Nikon Flash Info 7 (0107 and 0108) binary array - configuration
+ constexpr ArrayCfg nikonFl7Cfg = {
+ nikonFl7Id, // Group for the elements
+ bigEndian, // Use byte order from parent
+ ttUndefined, // Type for array entry
+ notEncrypted, // Not encrypted
+ false, // No size element
+ true, // Write all tags
+ true, // Concatenate gaps
+ { 0, ttUnsignedByte, 1 }
+ };
+ //! Nikon Flash Info 7 (0107 and 0108) binary array - definition
+ constexpr ArrayDef nikonFl7Def[] = {
+ { 0, ttUndefined, 4 }, // Version
+ { 4, ttUnsignedByte, 1 }, // FlashSource
+ { 6, ttUnsignedShort, 1 }, // ExternalFlashFirmware
+ { 8, ttUnsignedByte, 1 }, // ExternalFlashData1
+ { 9, ttUnsignedByte, 1 }, // ExternalFlashData2
+ { 10, ttSignedByte, 1 }, // FlashCompensation
+ { 12, ttUnsignedByte, 1 }, // FlashFocalLength
+ { 13, ttUnsignedByte, 1 }, // RepeatingFlashRate
+ { 14, ttUnsignedByte, 1 }, // RepeatingFlashCount
+ { 15, ttUnsignedByte, 1 }, // FlashGNDistance
+ { 17, ttUnsignedByte, 1 }, // FlashGroupAControlData
+ { 18, ttUnsignedByte, 1 }, // FlashGroupBCControlData
+ { 40, ttUnsignedByte, 1 }, // FlashGroupAData
+ { 41, ttUnsignedByte, 1 }, // FlashGroupBData
+ { 42, ttUnsignedByte, 1 } // FlashGroupCData
+ };
+
+ //! Nikon Flash Info Data configurations and definitions
constexpr ArraySet nikonFlSet[] = {
{ nikonFl1Cfg, nikonFl1Def, EXV_COUNTOF(nikonFl1Def) },
{ nikonFl2Cfg, nikonFl2Def, EXV_COUNTOF(nikonFl2Def) },
- { nikonFl3Cfg, nikonFl3Def, EXV_COUNTOF(nikonFl3Def) }
+ { nikonFl3Cfg, nikonFl3Def, EXV_COUNTOF(nikonFl3Def) },
+ { nikonFl7Cfg, nikonFl7Def, EXV_COUNTOF(nikonFl7Def) }
};
//! Nikon Shot Info binary array - configuration 1 (D80)
@@ -1177,6 +1208,7 @@ namespace Exiv2 {
{ Tag::root, nikonFl1Id, nikon3Id, 0x00a8 },
{ Tag::root, nikonFl2Id, nikon3Id, 0x00a8 },
{ Tag::root, nikonFl3Id, nikon3Id, 0x00a8 },
+ { Tag::root, nikonFl7Id, nikon3Id, 0x00a8 },
{ Tag::root, panasonicId, exifId, 0x927c },
{ Tag::root, pentaxId, exifId, 0x927c },
{ Tag::root, pentaxDngId, ifd0Id, 0xc634 },
@@ -1577,6 +1609,7 @@ namespace Exiv2 {
{ Tag::all, nikonFl1Id, newTiffBinaryElement },
{ Tag::all, nikonFl2Id, newTiffBinaryElement },
{ Tag::all, nikonFl3Id, newTiffBinaryElement },
+ { Tag::all, nikonFl7Id, newTiffBinaryElement },
// Nikon3 shot info
{ Tag::all, nikonSi1Id, newTiffBinaryElement },
diff --git a/test/data/exiv2-issue1941-1.exv b/test/data/exiv2-issue1941-1.exv
new file mode 100644
index 00000000..2416315f
Binary files /dev/null and b/test/data/exiv2-issue1941-1.exv differ
diff --git a/test/data/exiv2-test.out b/test/data/exiv2-test.out
index 87513594..f7d02dfa 100644
--- a/test/data/exiv2-test.out
+++ b/test/data/exiv2-test.out
@@ -971,9 +971,9 @@ File 4/16: 20040329_224245.jpg
20040329_224245.jpg Exif.NikonFl1.ExternalFlashFirmware Short 1 n/a
20040329_224245.jpg Exif.NikonFl1.ExternalFlashFlags Byte 1 Fired
20040329_224245.jpg Exif.NikonFl1.0x0009 Byte 2 0 0
-20040329_224245.jpg Exif.NikonFl1.FlashFocalLength Byte 1 (0)
-20040329_224245.jpg Exif.NikonFl1.RepeatingFlashRate Byte 1 (0)
-20040329_224245.jpg Exif.NikonFl1.RepeatingFlashCount Byte 1 (0)
+20040329_224245.jpg Exif.NikonFl1.FlashFocalLength Byte 1 n/a
+20040329_224245.jpg Exif.NikonFl1.RepeatingFlashRate Byte 1 n/a
+20040329_224245.jpg Exif.NikonFl1.RepeatingFlashCount Byte 1 n/a
20040329_224245.jpg Exif.NikonFl1.FlashGNDistance Byte 1 None
20040329_224245.jpg Exif.NikonFl1.FlashGroupAControlMode Byte 1 Off
20040329_224245.jpg Exif.NikonFl1.FlashGroupBControlMode Byte 1 Off
@@ -2612,9 +2612,9 @@ Compare image data and extracted data ------------------------------------
< 20040329_224245.jpg Exif.NikonFl1.ExternalFlashFirmware Short 1 n/a
< 20040329_224245.jpg Exif.NikonFl1.ExternalFlashFlags Byte 1 Fired
< 20040329_224245.jpg Exif.NikonFl1.0x0009 Byte 2 0 0
-< 20040329_224245.jpg Exif.NikonFl1.FlashFocalLength Byte 1 (0)
-< 20040329_224245.jpg Exif.NikonFl1.RepeatingFlashRate Byte 1 (0)
-< 20040329_224245.jpg Exif.NikonFl1.RepeatingFlashCount Byte 1 (0)
+< 20040329_224245.jpg Exif.NikonFl1.FlashFocalLength Byte 1 n/a
+< 20040329_224245.jpg Exif.NikonFl1.RepeatingFlashRate Byte 1 n/a
+< 20040329_224245.jpg Exif.NikonFl1.RepeatingFlashCount Byte 1 n/a
< 20040329_224245.jpg Exif.NikonFl1.FlashGNDistance Byte 1 None
< 20040329_224245.jpg Exif.NikonFl1.FlashGroupAControlMode Byte 1 Off
< 20040329_224245.jpg Exif.NikonFl1.FlashGroupBControlMode Byte 1 Off
@@ -4175,9 +4175,9 @@ Compare image data and extracted data ------------------------------------
> 20040329_224245.exv Exif.NikonFl1.ExternalFlashFirmware Short 1 n/a
> 20040329_224245.exv Exif.NikonFl1.ExternalFlashFlags Byte 1 Fired
> 20040329_224245.exv Exif.NikonFl1.0x0009 Byte 2 0 0
-> 20040329_224245.exv Exif.NikonFl1.FlashFocalLength Byte 1 (0)
-> 20040329_224245.exv Exif.NikonFl1.RepeatingFlashRate Byte 1 (0)
-> 20040329_224245.exv Exif.NikonFl1.RepeatingFlashCount Byte 1 (0)
+> 20040329_224245.exv Exif.NikonFl1.FlashFocalLength Byte 1 n/a
+> 20040329_224245.exv Exif.NikonFl1.RepeatingFlashRate Byte 1 n/a
+> 20040329_224245.exv Exif.NikonFl1.RepeatingFlashCount Byte 1 n/a
> 20040329_224245.exv Exif.NikonFl1.FlashGNDistance Byte 1 None
> 20040329_224245.exv Exif.NikonFl1.FlashGroupAControlMode Byte 1 Off
> 20040329_224245.exv Exif.NikonFl1.FlashGroupBControlMode Byte 1 Off
@@ -5976,9 +5976,9 @@ Compare original and inserted image data ---------------------------------
< 20040329_224245.jpg Exif.NikonFl1.ExternalFlashFirmware Short 1 n/a
< 20040329_224245.jpg Exif.NikonFl1.ExternalFlashFlags Byte 1 Fired
< 20040329_224245.jpg Exif.NikonFl1.0x0009 Byte 2 0 0
-< 20040329_224245.jpg Exif.NikonFl1.FlashFocalLength Byte 1 (0)
-< 20040329_224245.jpg Exif.NikonFl1.RepeatingFlashRate Byte 1 (0)
-< 20040329_224245.jpg Exif.NikonFl1.RepeatingFlashCount Byte 1 (0)
+< 20040329_224245.jpg Exif.NikonFl1.FlashFocalLength Byte 1 n/a
+< 20040329_224245.jpg Exif.NikonFl1.RepeatingFlashRate Byte 1 n/a
+< 20040329_224245.jpg Exif.NikonFl1.RepeatingFlashCount Byte 1 n/a
< 20040329_224245.jpg Exif.NikonFl1.FlashGNDistance Byte 1 None
< 20040329_224245.jpg Exif.NikonFl1.FlashGroupAControlMode Byte 1 Off
< 20040329_224245.jpg Exif.NikonFl1.FlashGroupBControlMode Byte 1 Off
@@ -7539,9 +7539,9 @@ Compare original and inserted image data ---------------------------------
> 20040329_224245.exv Exif.NikonFl1.ExternalFlashFirmware Short 1 n/a
> 20040329_224245.exv Exif.NikonFl1.ExternalFlashFlags Byte 1 Fired
> 20040329_224245.exv Exif.NikonFl1.0x0009 Byte 2 0 0
-> 20040329_224245.exv Exif.NikonFl1.FlashFocalLength Byte 1 (0)
-> 20040329_224245.exv Exif.NikonFl1.RepeatingFlashRate Byte 1 (0)
-> 20040329_224245.exv Exif.NikonFl1.RepeatingFlashCount Byte 1 (0)
+> 20040329_224245.exv Exif.NikonFl1.FlashFocalLength Byte 1 n/a
+> 20040329_224245.exv Exif.NikonFl1.RepeatingFlashRate Byte 1 n/a
+> 20040329_224245.exv Exif.NikonFl1.RepeatingFlashCount Byte 1 n/a
> 20040329_224245.exv Exif.NikonFl1.FlashGNDistance Byte 1 None
> 20040329_224245.exv Exif.NikonFl1.FlashGroupAControlMode Byte 1 Off
> 20040329_224245.exv Exif.NikonFl1.FlashGroupBControlMode Byte 1 Off
diff --git a/tests/bugfixes/github/test_issue_1941.py b/tests/bugfixes/github/test_issue_1941.py
new file mode 100644
index 00000000..d951bdf0
--- /dev/null
+++ b/tests/bugfixes/github/test_issue_1941.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+
+import system_tests
+from system_tests import CaseMeta, CopyTmpFiles, path
+
+class TestNikonFl7GroupWithFlash(metaclass=CaseMeta):
+
+ url = "https://github.com/Exiv2/exiv2/issues/1941"
+
+ filename = system_tests.path("$data_path/exiv2-issue1941-1.exv")
+ commands = ["""$exiv2 --grep NikonFl7 $filename"""]
+
+ stderr = [""]
+ retval = [0]
+
+ stdout = ["""Exif.NikonFl7.Version Undefined 4 1.08
+Exif.NikonFl7.FlashSource Byte 1 External
+Exif.NikonFl7.ExternalFlashFirmware Short 1 5.01 (SB-900)
+Exif.NikonFl7.ExternalFlashData1 Byte 1 No external flash zoom override, external flash attached
+Exif.NikonFl7.ExternalFlashData2 Byte 1 n/a
+Exif.NikonFl7.FlashCompensation SByte 1 0
+Exif.NikonFl7.FlashFocalLength Byte 1 n/a
+Exif.NikonFl7.RepeatingFlashRate Byte 1 n/a
+Exif.NikonFl7.RepeatingFlashCount Byte 1 n/a
+Exif.NikonFl7.FlashGNDistance Byte 1 None
+Exif.NikonFl7.FlashGroupAControlData Byte 1 Manual
+Exif.NikonFl7.FlashGroupBCControlData Byte 1 Off, Off
+Exif.NikonFl7.FlashGroupAData Byte 1 4%
+Exif.NikonFl7.FlashGroupBData Byte 1 0
+Exif.NikonFl7.FlashGroupCData Byte 1 0
+"""]
+
+class TestNikonFl7GroupWithoutFlash(metaclass=CaseMeta):
+
+ url = "https://github.com/Exiv2/exiv2/issues/1941"
+
+ filename = system_tests.path("$data_path/exiv2-bug1014_2.exv")
+ commands = ["""$exiv2 --grep NikonFl7 $filename"""]
+
+ stderr = [""]
+ retval = [0]
+
+ stdout = ["""Exif.NikonFl7.Version Undefined 4 1.07
+Exif.NikonFl7.FlashSource Byte 1 None
+Exif.NikonFl7.ExternalFlashFirmware Short 1 n/a
+Exif.NikonFl7.ExternalFlashData1 Byte 1 No external flash zoom override, external flash not attached
+Exif.NikonFl7.ExternalFlashData2 Byte 1 n/a
+Exif.NikonFl7.FlashCompensation SByte 1 0
+Exif.NikonFl7.FlashFocalLength Byte 1 n/a
+Exif.NikonFl7.RepeatingFlashRate Byte 1 n/a
+Exif.NikonFl7.RepeatingFlashCount Byte 1 n/a
+Exif.NikonFl7.FlashGNDistance Byte 1 None
+Exif.NikonFl7.FlashGroupAControlData Byte 1 Off
+Exif.NikonFl7.FlashGroupBCControlData Byte 1 Off, Off
+Exif.NikonFl7.FlashGroupAData Byte 1 0
+Exif.NikonFl7.FlashGroupBData Byte 1 0
+Exif.NikonFl7.FlashGroupCData Byte 1 0
+"""]