diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp index 937b4ccc..37b441f3 100644 --- a/include/exiv2/image.hpp +++ b/include/exiv2/image.hpp @@ -368,9 +368,8 @@ namespace Exiv2 { encoded. Initially, it is not set (\em invalidByteOrder). */ ByteOrder byteOrder() const; - /*! - @brief Check if the Image instance is valid. Use after object - construction. + + /*! @brief Check if the Image instance is valid. Use after object construction. @return true if the Image is in a valid state. */ bool good() const; diff --git a/src/bmpimage.cpp b/src/bmpimage.cpp index 1aff6991..d18979a7 100644 --- a/src/bmpimage.cpp +++ b/src/bmpimage.cpp @@ -105,7 +105,7 @@ namespace Exiv2 46 4 bytes color count 50 4 bytes important colors number of "important" colors */ - byte buf[54]; + byte buf[26]; if (io_->read(buf, sizeof(buf)) == sizeof(buf)) { pixelWidth_ = getLong(buf + 18, littleEndian); pixelHeight_ = getLong(buf + 22, littleEndian); diff --git a/src/image.cpp b/src/image.cpp index 8dfa7bb1..7002a99c 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -741,7 +741,8 @@ namespace Exiv2 { bool Image::good() const { - if (io_->open() != 0) return false; + if (io_->open() != 0) + return false; IoCloser closer(*io_); return ImageFactory::checkType(imageType_, *io_, false); } @@ -809,7 +810,7 @@ namespace Exiv2 { return r->isThisType_(io, advance); } return false; - } // ImageFactory::checkType + } int ImageFactory::getType(const std::string& path) { diff --git a/unitTests/test_bmpimage.cpp b/unitTests/test_bmpimage.cpp index 92865de6..86764fd8 100644 --- a/unitTests/test_bmpimage.cpp +++ b/unitTests/test_bmpimage.cpp @@ -1,8 +1,7 @@ -#include - #include #include +#include using namespace Exiv2; @@ -19,3 +18,179 @@ TEST(BmpImage, mimeTypeIsBmp) ASSERT_EQ("image/x-ms-bmp", bmp.mimeType()); } + +TEST(BmpImage, writeMetadataIsNotImplemented) +{ + auto memIo = std::make_unique(); + BmpImage bmp(std::move(memIo)); + + try { + bmp.writeMetadata(); + FAIL(); + } catch (const Exiv2::Error& e) { + ASSERT_EQ(kerWritingImageFormatUnsupported, e.code()); + ASSERT_STREQ("Writing to BMP images is not supported", e.what()); + } +} + +TEST(BmpImage, setExitDataIsNotImplemented) +{ + auto memIo = std::make_unique(); + BmpImage bmp(std::move(memIo)); + + try { + ExifData data; + bmp.setExifData(data); + FAIL(); + } catch (const Exiv2::Error& e) { + ASSERT_EQ(kerInvalidSettingForImage, e.code()); + ASSERT_STREQ("Setting Exif metadata in BMP images is not supported", e.what()); + } +} + +TEST(BmpImage, setIptcDataIsNotImplemented) +{ + auto memIo = std::make_unique(); + BmpImage bmp(std::move(memIo)); + + try { + IptcData data; + bmp.setIptcData(data); + FAIL(); + } catch (const Exiv2::Error& e) { + ASSERT_EQ(kerInvalidSettingForImage, e.code()); + ASSERT_STREQ("Setting IPTC metadata in BMP images is not supported", e.what()); + } +} + +TEST(BmpImage, setCommentIsNotImplemented) +{ + auto memIo = std::make_unique(); + BmpImage bmp(std::move(memIo)); + + try { + bmp.setComment("random comment"); + FAIL(); + } catch (const Exiv2::Error& e) { + ASSERT_EQ(kerInvalidSettingForImage, e.code()); + ASSERT_STREQ("Setting Image comment in BMP images is not supported", e.what()); + } +} + +TEST(BmpImage, readMetadataReadsImageDimensionsWhenDataIsAvailable) +{ + const std::array header{ + 'B', 'M', // Signature off:0 size:2 + 0x4E, 0x47, 0x0D, 0x0A, // Size of the BMP file in bytes off:2, size:4 + 0x1A, 0x0A, // Reserved off:6, size:2 + 0x00, 0x00, // Reserved off:8, size:2 + 0x00, 0x00, 0x00, 0x00, // Offset of the byte where the bitmap image data can be found off:10, size:4 + 0x00, 0x00, 0x00, 0x00, // Size of this header off:14, size:4 + 0x00, 0x05, 0x00, 0x00, // The bitmap width in pixels (unsigned 16 bit) off:18, size:4 + 0x20, 0x03, 0x00, 0x00, // The bitmap height in pixels (unsigned 16 bit) off:22, size:4 + }; + + auto memIo = std::make_unique(header.data(), header.size()); + BmpImage bmp(std::move(memIo)); + ASSERT_NO_THROW(bmp.readMetadata()); + ASSERT_EQ(1280, bmp.pixelWidth()); + ASSERT_EQ(800, bmp.pixelHeight()); +} + +TEST(BmpImage, readMetadataThrowsWhenImageIsNotBMP) +{ + const std::array header{ + 'B', 'A', // Signature off:0 size:2 + 0x4E, 0x47, 0x0D, 0x0A, // Size of the BMP file in bytes off:2, size:4 + 0x1A, 0x0A, // Reserved off:6, size:2 + 0x00, 0x00, // Reserved off:8, size:2 + 0x00, 0x00, 0x00, 0x00, // Offset of the byte where the bitmap image data can be found off:10, size:4 + 0x00, 0x00, 0x00, 0x00, // Size of this header off:14, size:4 + 0x00, 0x05, 0x00, 0x00, // The bitmap width in pixels (unsigned 16 bit) off:18, size:4 + 0x20, 0x03, 0x00, 0x00, // The bitmap height in pixels (unsigned 16 bit) off:22, size:4 + }; + + auto memIo = std::make_unique(header.data(), header.size()); + BmpImage bmp(std::move(memIo)); + try { + bmp.readMetadata(); + FAIL(); + } catch (const Exiv2::Error& e) { + ASSERT_EQ(kerNotAnImage, e.code()); + ASSERT_STREQ("This does not look like a BMP image", e.what()); + } +} + +TEST(BmpImage, readMetadataThrowsWhenThereIsNotEnoughInfoToRead) +{ + const std::array header{'B'}; + auto memIo = std::make_unique(header.data(), header.size()); + BmpImage bmp(std::move(memIo)); + try { + bmp.readMetadata(); + FAIL(); + } catch (const Exiv2::Error& e) { + ASSERT_EQ(kerFailedToReadImageData, e.code()); + ASSERT_STREQ("Failed to read image data", e.what()); + } +} + + +TEST(BmpImage, readMetadataThrowsWhenIoCannotBeOpened) +{ + auto fileIo = std::make_unique("NonExistingPath.png"); + BmpImage bmp(std::move(fileIo)); + try { + bmp.readMetadata(); + FAIL(); + } catch (const Exiv2::Error& e) { + ASSERT_EQ(kerDataSourceOpenFailed, e.code()); + } +} + +TEST(newBmpInstance, createsValidInstace) +{ + const std::array bitmapHeader{ + 'B', 'M', // Signature + 0x4E, 0x47, 0x0D, 0x0A, // Size of the BMP file in bytes + 0x1A, 0x0A, // Reserved + 0x00, 0x00, // Reserved + 0x00, 0x00, 0x00, 0x00 // Offset of the byte where the bitmap image data can be found + }; + auto memIo = std::make_unique(bitmapHeader.data(), bitmapHeader.size()); + auto img = newBmpInstance(std::move(memIo), false); + ASSERT_TRUE(img->good()); +} + +TEST(newBmpInstance, createsInvalidInstaceWithNonExistingFilePath) +{ + auto fileIo = std::make_unique("NonExistingPath.png"); + auto img = newBmpInstance(std::move(fileIo), false); + ASSERT_FALSE(img); +} + +TEST(isBmpType, withValidSignatureReturnsTrue) +{ + const std::array bitmapHeader{ + 'B', 'M', // Signature + 0x4E, 0x47, 0x0D, 0x0A, // Size of the BMP file in bytes + 0x1A, 0x0A, // Reserved + 0x00, 0x00, // Reserved + 0x00, 0x00, 0x00, 0x00 // Offset of the byte where the bitmap image data can be found + }; + MemIo memIo(bitmapHeader.data(), bitmapHeader.size()); + ASSERT_TRUE(isBmpType(memIo, false)); +} + +TEST(isBmpType, withInvalidSignatureReturnsFalse) +{ + const std::array bitmapHeader{ + 'B', 'A', // Signature + 0x4E, 0x47, 0x0D, 0x0A, // Size of the BMP file in bytes + 0x1A, 0x0A, // Reserved + 0x00, 0x00, // Reserved + 0x00, 0x00, 0x00, 0x00 // Offset of the byte where the bitmap image data can be found + }; + MemIo memIo(bitmapHeader.data(), bitmapHeader.size()); + ASSERT_FALSE(isBmpType(memIo, false)); +}