diff --git a/conanfile.py b/conanfile.py index 23de4359..6946e3df 100644 --- a/conanfile.py +++ b/conanfile.py @@ -22,7 +22,9 @@ class Exiv2Conan(ConanFile): def requirements(self): self.requires('zlib/1.2.11') - self.requires('libcurl/7.75.0') + + if self.options.webready: + self.requires('libcurl/7.79.0') if os_info.is_windows and self.options.iconv: self.requires('libiconv/1.16') @@ -35,7 +37,7 @@ class Exiv2Conan(ConanFile): if self.options.xmp: self.requires('XmpSdk/2016.7@piponazo/stable') # from conan-piponazo else: - self.requires('expat/2.3.0') + self.requires('expat/2.4.1') def imports(self): self.copy('*.dll', dst='bin', src='bin') 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/include/exiv2/basicio.hpp b/include/exiv2/basicio.hpp index ead0d73c..b654891d 100644 --- a/include/exiv2/basicio.hpp +++ b/include/exiv2/basicio.hpp @@ -27,6 +27,7 @@ #include "exiv2lib_export.h" // included header files +#include "error.hpp" #include "types.hpp" // + standard includes @@ -142,6 +143,17 @@ namespace Exiv2 { 0 if failure; */ virtual long read(byte* buf, long rcount) = 0; + /*! + @brief Safe version of `read()` that checks for errors and throws + an exception if the read was unsuccessful. + @param buf Pointer to a block of memory into which the read data + is stored. The memory block must be at least \em rcount bytes + long. + @param rcount Maximum number of bytes to read. Fewer bytes may be + read if \em rcount bytes are not available. + @param err Error code to use if an exception is thrown. + */ + void readOrThrow(byte* buf, long rcount, ErrorCode err); /*! @brief Read one byte from the IO source. Current IO position is advanced by one byte. @@ -176,6 +188,19 @@ namespace Exiv2 { #else virtual int seek(long offset, Position pos) = 0; #endif + /*! + @brief Safe version of `seek()` that checks for errors and throws + an exception if the seek was unsuccessful. + @param offset Number of bytes to move the position relative + to the starting position specified by \em pos + @param pos Position from which the seek should start + @param err Error code to use if an exception is thrown. + */ +#if defined(_MSC_VER) + void seekOrThrow(int64_t offset, Position pos, ErrorCode err); +#else + void seekOrThrow(long offset, Position pos, ErrorCode err); +#endif /*! @brief Direct access to the IO data. For files, this is done by diff --git a/src/basicio.cpp b/src/basicio.cpp index f0a6e667..f7e699c6 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -28,6 +28,7 @@ #include "futils.hpp" #include "types.hpp" #include "error.hpp" +#include "enforce.hpp" #include "http.hpp" #include "properties.hpp" #include "image_int.hpp" @@ -77,6 +78,21 @@ using nlink_t = short; // ***************************************************************************** // class member definitions namespace Exiv2 { + void BasicIo::readOrThrow(byte* buf, long rcount, ErrorCode err) { + const long nread = read(buf, rcount); + enforce(nread == rcount, err); + enforce(!error(), err); + } + +#if defined(_MSC_VER) + void BasicIo::seekOrThrow(int64_t offset, Position pos, ErrorCode err) { +#else + void BasicIo::seekOrThrow(long offset, Position pos, ErrorCode err) { +#endif + const int r = seek(offset, pos); + enforce(r == 0, err); + } + //! Internal Pimpl structure of class FileIo. class FileIo::Impl { public: diff --git a/src/image.cpp b/src/image.cpp index 0ba1c25c..8dfa7bb1 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -138,19 +138,6 @@ namespace { // ***************************************************************************** // class member definitions namespace Exiv2 { - // BasicIo::read() with error checking - static void readOrThrow(BasicIo& iIo, byte* buf, long rcount, ErrorCode err) { - const long nread = iIo.read(buf, rcount); - enforce(nread == rcount, err); - enforce(!iIo.error(), err); - } - - // BasicIo::seek() with error checking - static void seekOrThrow(BasicIo& iIo, long offset, BasicIo::Position pos, ErrorCode err) { - const int r = iIo.seek(offset, pos); - enforce(r == 0, err); - } - Image::Image(int imageType, uint16_t supportedMetadata, BasicIo::UniquePtr io) : io_(std::move(io)), pixelWidth_(0), @@ -342,8 +329,8 @@ namespace Exiv2 { do { // Read top of directory - seekOrThrow(io, start, BasicIo::beg, kerCorruptedMetadata); - readOrThrow(io, dir.data(), 2, kerCorruptedMetadata); + io.seekOrThrow(start, BasicIo::beg, kerCorruptedMetadata); + io.readOrThrow(dir.data(), 2, kerCorruptedMetadata); uint16_t dirLength = byteSwap2(dir,0,bSwap); // Prevent infinite loops. (GHSA-m479-7frc-gqqg) enforce(dirLength > 0, kerCorruptedMetadata); @@ -369,7 +356,7 @@ namespace Exiv2 { } bFirst = false; - readOrThrow(io, dir.data(), 12, kerCorruptedMetadata); + io.readOrThrow(dir.data(), 12, kerCorruptedMetadata); uint16_t tag = byteSwap2(dir,0,bSwap); uint16_t type = byteSwap2(dir,2,bSwap); uint32_t count = byteSwap4(dir,4,bSwap); @@ -420,9 +407,9 @@ namespace Exiv2 { if ( bOffsetIsPointer ) { // read into buffer const long restore = io.tell(); // save - seekOrThrow(io, offset, BasicIo::beg, kerCorruptedMetadata); // position - readOrThrow(io, buf.data(), static_cast(count_x_size), kerCorruptedMetadata); // read - seekOrThrow(io, restore, BasicIo::beg, kerCorruptedMetadata); // restore + io.seekOrThrow(offset, BasicIo::beg, kerCorruptedMetadata); // position + io.readOrThrow(buf.data(), static_cast(count_x_size), kerCorruptedMetadata); // read + io.seekOrThrow(restore, BasicIo::beg, kerCorruptedMetadata); // restore } if ( bPrint ) { @@ -464,7 +451,7 @@ namespace Exiv2 { const long restore = io.tell(); offset = byteSwap4(buf,k*size,bSwap); printIFDStructure(io,out,option,offset,bSwap,c,depth); - seekOrThrow(io, restore, BasicIo::beg, kerCorruptedMetadata); + io.seekOrThrow(restore, BasicIo::beg, kerCorruptedMetadata); } } else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { if (count > 0) { @@ -473,11 +460,11 @@ namespace Exiv2 { } const long restore = io.tell(); - seekOrThrow(io, offset, BasicIo::beg, kerCorruptedMetadata); // position + io.seekOrThrow(offset, BasicIo::beg, kerCorruptedMetadata); // position std::vector bytes(count) ; // allocate memory // TODO: once we have C++11 use bytes.data() - readOrThrow(io, &bytes[0], count, kerCorruptedMetadata); - seekOrThrow(io, restore, BasicIo::beg, kerCorruptedMetadata); + io.readOrThrow(&bytes[0], count, kerCorruptedMetadata); + io.seekOrThrow(restore, BasicIo::beg, kerCorruptedMetadata); // TODO: once we have C++11 use bytes.data() IptcData::printStructure(out, makeSliceUntil(&bytes[0], count), depth); } @@ -487,8 +474,8 @@ namespace Exiv2 { uint32_t jump= 10 ; byte bytes[20] ; const auto chars = reinterpret_cast(&bytes[0]); - seekOrThrow(io, offset, BasicIo::beg, kerCorruptedMetadata); // position - readOrThrow(io, bytes, jump, kerCorruptedMetadata) ; // read + io.seekOrThrow(offset, BasicIo::beg, kerCorruptedMetadata); // position + io.readOrThrow(bytes, jump, kerCorruptedMetadata) ; // read bytes[jump]=0 ; bool bNikon = ::strcmp("Nikon" ,chars) == 0; @@ -498,17 +485,17 @@ namespace Exiv2 { // tag is an embedded tiff const long byteslen = count-jump; DataBuf bytes(byteslen); // allocate a buffer - readOrThrow(io, bytes.data(), byteslen, kerCorruptedMetadata); // read + io.readOrThrow(bytes.data(), byteslen, kerCorruptedMetadata); // read MemIo memIo(bytes.c_data(), byteslen) ; // create a file printTiffStructure(memIo,out,option,depth); } else { // tag is an IFD uint32_t punt = bSony ? 12 : 0 ; - seekOrThrow(io, 0, BasicIo::beg, kerCorruptedMetadata); // position + io.seekOrThrow(0, BasicIo::beg, kerCorruptedMetadata); // position printIFDStructure(io,out,option,offset+punt,bSwap,c,depth); } - seekOrThrow(io, restore, BasicIo::beg, kerCorruptedMetadata); // restore + io.seekOrThrow(restore, BasicIo::beg, kerCorruptedMetadata); // restore } } @@ -521,7 +508,7 @@ namespace Exiv2 { } } if ( start ) { - readOrThrow(io, dir.data(), 4, kerCorruptedMetadata); + io.readOrThrow(dir.data(), 4, kerCorruptedMetadata); start = byteSwap4(dir,0,bSwap); } } while (start) ; @@ -541,7 +528,7 @@ namespace Exiv2 { DataBuf dir(dirSize); // read header (we already know for certain that we have a Tiff file) - readOrThrow(io, dir.data(), 8, kerCorruptedMetadata); + io.readOrThrow(dir.data(), 8, kerCorruptedMetadata); char c = static_cast(dir.read_uint8(0)); bool bSwap = ( c == 'M' && isLittleEndianPlatform() ) || ( c == 'I' && isBigEndianPlatform() ) diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index f07b48fb..5865d25c 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -94,19 +94,6 @@ namespace Exiv2 { constexpr uint16_t Photoshop::iptc_ = 0x0404; constexpr uint16_t Photoshop::preview_ = 0x040c; - // BasicIo::read() with error checking - static void readOrThrow(BasicIo& iIo, byte* buf, long rcount, ErrorCode err) { - const long nread = iIo.read(buf, rcount); - enforce(nread == rcount, err); - enforce(!iIo.error(), err); - } - - // BasicIo::seek() with error checking - static void seekOrThrow(BasicIo& iIo, long offset, BasicIo::Position pos, ErrorCode err) { - const int r = iIo.seek(offset, pos); - enforce(r == 0, err); - } - static inline bool inRange(int lo,int value, int hi) { return lo<=value && value <= hi; @@ -389,7 +376,7 @@ namespace Exiv2 { byte sizebuf[2]; uint16_t size = 0; if (markerHasLength(marker)) { - readOrThrow(*io_, sizebuf, 2, kerFailedToReadImageData); + io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData); size = getUShort(sizebuf, bigEndian); // `size` is the size of the segment, including the 2-byte size field // that we just read. @@ -399,7 +386,7 @@ namespace Exiv2 { // Read the rest of the segment. DataBuf buf(size); if (size > 0) { - readOrThrow(*io_, buf.data(2), size - 2, kerFailedToReadImageData); + io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData); buf.copyBytes(0, sizebuf, 2); } @@ -616,7 +603,7 @@ namespace Exiv2 { byte sizebuf[2]; uint16_t size = 0; if (markerHasLength(marker)) { - readOrThrow(*io_, sizebuf, 2, kerFailedToReadImageData); + io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData); size = getUShort(sizebuf, bigEndian); // `size` is the size of the segment, including the 2-byte size field // that we just read. @@ -627,7 +614,7 @@ namespace Exiv2 { DataBuf buf(size); if (size > 0) { assert(size >= 2); // enforced above - readOrThrow(*io_, buf.data(2), size - 2, kerFailedToReadImageData); + io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData); buf.copyBytes(0, sizebuf, 2); } @@ -847,16 +834,16 @@ namespace Exiv2 { #ifdef EXIV2_DEBUG_MESSAGES std::cout << start << ":" << length << std::endl; #endif - seekOrThrow(*io_, start, BasicIo::beg, kerFailedToReadImageData); + io_->seekOrThrow(start, BasicIo::beg, kerFailedToReadImageData); DataBuf buf(length); - readOrThrow(*io_, buf.data(), buf.size(), kerFailedToReadImageData); + io_->readOrThrow(buf.data(), buf.size(), kerFailedToReadImageData); tempIo->write(buf.c_data(), buf.size()); } } - seekOrThrow(*io_, 0, BasicIo::beg, kerFailedToReadImageData); + io_->seekOrThrow(0, BasicIo::beg, kerFailedToReadImageData); io_->transfer(*tempIo); // may throw - seekOrThrow(*io_, 0, BasicIo::beg, kerFailedToReadImageData); + io_->seekOrThrow(0, BasicIo::beg, kerFailedToReadImageData); readMetadata(); } } // JpegBase::printStructure @@ -923,7 +910,7 @@ namespace Exiv2 { byte sizebuf[2]; uint16_t size = 0; if (markerHasLength(marker)) { - readOrThrow(*io_, sizebuf, 2, kerFailedToReadImageData); + io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData); size = getUShort(sizebuf, bigEndian); // `size` is the size of the segment, including the 2-byte size field // that we just read. @@ -934,7 +921,7 @@ namespace Exiv2 { DataBuf buf(size); if (size > 0) { assert(size >= 2); // enforced above - readOrThrow(*io_, buf.data(2), size - 2, kerFailedToReadImageData); + io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData); buf.copyBytes(0, sizebuf, 2); } @@ -1024,7 +1011,7 @@ namespace Exiv2 { if (!comment_.empty()) ++search; - seekOrThrow(*io_, seek, BasicIo::beg, kerNoImageInInputData); + io_->seekOrThrow(seek, BasicIo::beg, kerNoImageInInputData); count = 0; marker = advanceToMarker(kerNoImageInInputData); @@ -1037,7 +1024,7 @@ namespace Exiv2 { byte sizebuf[2]; uint16_t size = 0; if (markerHasLength(marker)) { - readOrThrow(*io_, sizebuf, 2, kerFailedToReadImageData); + io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData); size = getUShort(sizebuf, bigEndian); // `size` is the size of the segment, including the 2-byte size field // that we just read. @@ -1048,7 +1035,7 @@ namespace Exiv2 { DataBuf buf(size); if (size > 0) { assert(size >= 2); // enforced above - readOrThrow(*io_, buf.data(2), size - 2, kerFailedToReadImageData); + io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData); buf.copyBytes(0, sizebuf, 2); } diff --git a/src/makernote_int.cpp b/src/makernote_int.cpp index 6d66cccc..04c375eb 100644 --- a/src/makernote_int.cpp +++ b/src/makernote_int.cpp @@ -1139,6 +1139,10 @@ namespace Exiv2 { { 0x00a8, "0101", 0, 0, NA }, { 0x00a8, "0102", 0, 1, NA }, { 0x00a8, "0103", 0, 2, NA }, + { 0x00a8, "0104", 0, 2, NA }, + { 0x00a8, "0105", 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 << std::fixed << std::setprecision(2) << value.toLong(); + 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); + 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/src/webpimage.cpp b/src/webpimage.cpp index f8a1887b..e99b21ce 100644 --- a/src/webpimage.cpp +++ b/src/webpimage.cpp @@ -55,14 +55,6 @@ namespace Exiv2 { using namespace Exiv2::Internal; - // This static function is a temporary fix in v0.27. In the next version, - // it will be added as a method of BasicIo. - static void readOrThrow(BasicIo& iIo, byte* buf, long rcount, ErrorCode err) { - const long nread = iIo.read(buf, rcount); - enforce(nread == rcount, err); - enforce(!iIo.error(), err); - } - WebPImage::WebPImage(BasicIo::UniquePtr io) : Image(ImageType::webp, mdNone, std::move(io)) { @@ -140,7 +132,7 @@ namespace Exiv2 { DataBuf chunkId(WEBP_TAG_SIZE+1); chunkId.write_uint8(WEBP_TAG_SIZE, '\0'); - readOrThrow(*io_, data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata); uint64_t filesize = Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian); /* Set up header */ @@ -180,8 +172,8 @@ namespace Exiv2 { case we have any exif or xmp data, also check for any chunks with alpha frame/layer set */ while (!io_->eof() && static_cast(io_->tell()) < filesize) { - readOrThrow(*io_, chunkId.data(), WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); - readOrThrow(*io_, size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(chunkId.data(), WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian); // Check that `size_u32` is safe to cast to `long`. @@ -189,10 +181,10 @@ namespace Exiv2 { Exiv2::kerCorruptedMetadata); const long size = static_cast(size_u32); DataBuf payload(size); - readOrThrow(*io_, payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); if ( payload.size() % 2 ) { byte c = 0; - readOrThrow(*io_, &c, 1, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(&c, 1, Exiv2::kerCorruptedMetadata); } /* Chunk with information about features @@ -317,8 +309,8 @@ namespace Exiv2 { io_->seek(12, BasicIo::beg); while (!io_->eof() && static_cast(io_->tell()) < filesize) { - readOrThrow(*io_, chunkId.data(), 4, Exiv2::kerCorruptedMetadata); - readOrThrow(*io_, size_buff, 4, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(chunkId.data(), 4, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(size_buff, 4, Exiv2::kerCorruptedMetadata); const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian); @@ -328,7 +320,7 @@ namespace Exiv2 { const long size = static_cast(size_u32); DataBuf payload(size); - readOrThrow(*io_, payload.data(), size, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), size, Exiv2::kerCorruptedMetadata); if ( io_->tell() % 2 ) io_->seek(+1,BasicIo::cur); // skip pad if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X)) { @@ -520,7 +512,7 @@ namespace Exiv2 { DataBuf chunkId(5); chunkId.write_uint8(4, '\0'); - readOrThrow(*io_, data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata); const uint32_t filesize_u32 = Safe::add(Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian), 8U); @@ -546,8 +538,8 @@ namespace Exiv2 { chunkId.write_uint8(4, '\0'); while (!io_->eof() && io_->tell() < filesize) { - readOrThrow(*io_, chunkId.data(), WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); - readOrThrow(*io_, size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(chunkId.data(), WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); + io_->readOrThrow(size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata); const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian); @@ -568,7 +560,7 @@ namespace Exiv2 { has_canvas_data = true; byte size_buf[WEBP_TAG_SIZE]; - readOrThrow(*io_, payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); // Fetch width memcpy(&size_buf, payload.c_data(4), 3); @@ -583,7 +575,7 @@ namespace Exiv2 { enforce(size >= 10, Exiv2::kerCorruptedMetadata); has_canvas_data = true; - readOrThrow(*io_, payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); byte size_buf[WEBP_TAG_SIZE]; // Fetch width"" @@ -604,7 +596,7 @@ namespace Exiv2 { byte size_buf_w[2]; byte size_buf_h[3]; - readOrThrow(*io_, payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); // Fetch width memcpy(&size_buf_w, payload.c_data(1), 2); @@ -622,7 +614,7 @@ namespace Exiv2 { has_canvas_data = true; byte size_buf[WEBP_TAG_SIZE]; - readOrThrow(*io_, payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); // Fetch width memcpy(&size_buf, payload.c_data(6), 3); @@ -634,10 +626,10 @@ namespace Exiv2 { size_buf[3] = 0; pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1; } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ICCP)) { - readOrThrow(*io_, payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); this->setIccProfile(std::move(payload)); } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_EXIF)) { - readOrThrow(*io_, payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); byte size_buff2[2]; // 4 meaningful bytes + 2 padding bytes @@ -715,7 +707,7 @@ namespace Exiv2 { exifData_.clear(); } } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_XMP)) { - readOrThrow(*io_, payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); + io_->readOrThrow(payload.data(), payload.size(), Exiv2::kerCorruptedMetadata); xmpPacket_.assign(payload.c_str(), payload.size()); if (!xmpPacket_.empty() && XmpParser::decode(xmpData_, xmpPacket_)) { #ifndef SUPPRESS_WARNINGS @@ -758,9 +750,9 @@ namespace Exiv2 { byte webp[len]; byte data[len]; byte riff[len]; - readOrThrow(iIo, riff, len, Exiv2::kerCorruptedMetadata); - readOrThrow(iIo, data, len, Exiv2::kerCorruptedMetadata); - readOrThrow(iIo, webp, len, Exiv2::kerCorruptedMetadata); + iIo.readOrThrow(riff, len, Exiv2::kerCorruptedMetadata); + iIo.readOrThrow(data, len, Exiv2::kerCorruptedMetadata); + iIo.readOrThrow(webp, len, Exiv2::kerCorruptedMetadata); bool matched_riff = (memcmp(riff, RiffImageId, len) == 0); bool matched_webp = (memcmp(webp, WebPImageId, len) == 0); iIo.seek(-12, BasicIo::cur); 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/test/data/pr_1994_poc1.jpg b/test/data/pr_1994_poc1.jpg new file mode 100644 index 00000000..13bbc3d4 Binary files /dev/null and b/test/data/pr_1994_poc1.jpg differ diff --git a/test/data/pr_1994_poc2.jpg b/test/data/pr_1994_poc2.jpg new file mode 100644 index 00000000..7f0f7cdb Binary files /dev/null and b/test/data/pr_1994_poc2.jpg differ 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 +"""] diff --git a/tests/bugfixes/github/test_pr_1994.py b/tests/bugfixes/github/test_pr_1994.py new file mode 100644 index 00000000..b24df704 --- /dev/null +++ b/tests/bugfixes/github/test_pr_1994.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +import system_tests +from system_tests import CaseMeta, path + +class TestAddModelsForNikonFl3(metaclass=CaseMeta): + """ + Enables NikonFl3 group to be used by more camera models + """ + + filename1 = path("$data_path/pr_1994_poc1.jpg") + filename2 = path("$data_path/pr_1994_poc2.jpg") + commands = ["$exiv2 --grep NikonFl3 $filename1", + "$exiv2 --grep NikonFl3 $filename2" + ] + stdout = ["""Exif.NikonFl3.Version Undefined 4 1.04 +Exif.NikonFl3.FlashSource Byte 1 None +Exif.NikonFl3.ExternalFlashFirmware Short 1 n/a +Exif.NikonFl3.ExternalFlashFlags Byte 1 Fired +Exif.NikonFl3.FlashFocalLength Byte 1 n/a +Exif.NikonFl3.RepeatingFlashRate Byte 1 n/a +Exif.NikonFl3.RepeatingFlashCount Byte 1 n/a +Exif.NikonFl3.FlashGNDistance Byte 1 None +Exif.NikonFl3.FlashColorFilter Byte 1 None +""", +"""Exif.NikonFl3.Version Undefined 4 1.05 +Exif.NikonFl3.FlashSource Byte 1 None +Exif.NikonFl3.ExternalFlashFirmware Short 1 n/a +Exif.NikonFl3.ExternalFlashFlags Byte 1 Fired +Exif.NikonFl3.FlashFocalLength Byte 1 n/a +Exif.NikonFl3.RepeatingFlashRate Byte 1 n/a +Exif.NikonFl3.RepeatingFlashCount Byte 1 n/a +Exif.NikonFl3.FlashGNDistance Byte 1 None +Exif.NikonFl3.FlashColorFilter Byte 1 None +"""] + stderr = [""]*2 + retval = [0]*2 +