#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_PIXELS_SOURCE 1 #include "../../../Source/Storage/Tiff/TiffBitmapCodec.h" #if defined(NUCLEX_PIXELS_HAVE_LIBTIFF) #include #include "Nuclex/Pixels/Storage/VirtualFile.h" #include "Nuclex/Pixels/Errors/FileFormatError.h" #include "ExampleTiffs.h" #include // for std::copy_n() namespace { // ------------------------------------------------------------------------------------------- // /// Simple virtual file implementation that accesses an in-memory buffer class InMemoryFile : public Nuclex::Pixels::Storage::VirtualFile { /// Initializes a new memory buffer based file /// Memory buffer the virtual file will access /// Size of the memory buffer in bytes public: InMemoryFile(const std::uint8_t *data, std::uint64_t length) : data(data), length(length) {} /// Frees all memory used by the instance public: ~InMemoryFile() override = default; /// Determines the current size of the file in bytes /// The size of the file in bytes public: std::uint64_t GetSize() const override { return this->length; } /// Reads data from the file /// Offset in the file at which to begin reading /// Number of bytes that will be read /// Buffer into which the data will be read public: void ReadAt( std::uint64_t start, std::size_t byteCount, std::uint8_t *buffer ) const override { std::copy_n(this->data + start, byteCount, buffer); } /// Writes data into the file /// Offset at which writing will begin in the file /// Number of bytes that should be written /// Buffer holding the data that should be written public: void WriteAt( std::uint64_t start, std::size_t byteCount, const std::uint8_t *buffer ) override { (void)start; (void)byteCount; (void)buffer; assert(!u8"Write method of unit test dummy file is never called"); } /// Memory buffer the virtual file implementation is serving data from private: const std::uint8_t *data; /// Length of the memory buffer in bytes private: std::uint64_t length; }; // ------------------------------------------------------------------------------------------- // } // anonymous namespace namespace Nuclex { namespace Pixels { namespace Storage { namespace Tiff { // ------------------------------------------------------------------------------------------- // TEST(TiffBitmapCodecTest, HasDefaultConstructor) { EXPECT_NO_THROW( TiffBitmapCodec codec; ); } // ------------------------------------------------------------------------------------------- // TEST(TiffBitmapCodecTest, ProvidesName) { TiffBitmapCodec codec; std::string codecName = codec.GetName(); EXPECT_GT(codecName.length(), 0U); } // ------------------------------------------------------------------------------------------- // TEST(TiffBitmapCodecTest, FileExtensionsIncludeTifAndTiff) { TiffBitmapCodec codec; const std::vector &extensions = codec.GetFileExtensions(); bool tifFound = false; bool tiffFound = false; for(std::size_t index = 0; index < extensions.size(); ++index) { if((extensions[index] == "tif") || (extensions[index] == ".tif")) { tifFound = true; } if((extensions[index] == "tiff") || (extensions[index] == ".tiff")) { tiffFound = true; } } EXPECT_TRUE(tifFound); EXPECT_TRUE(tiffFound); } // ------------------------------------------------------------------------------------------- // TEST(TiffBitmapCodecTest, CanLoadMethodRecognizesTiffs) { TiffBitmapCodec codec; { std::uint8_t dummyData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; const InMemoryFile dummyFile(dummyData, sizeof(dummyData)); EXPECT_FALSE(codec.CanLoad(dummyFile)); } { const InMemoryFile tiffFile(Tiff::testTiff, sizeof(Tiff::testTiff)); EXPECT_TRUE(codec.CanLoad(tiffFile)); } } // ------------------------------------------------------------------------------------------- // TEST(TiffBitmapCodecTest, TryReadInfoReturnsEmptyOnWrongFileType) { TiffBitmapCodec codec; { std::uint8_t dummyData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; const InMemoryFile dummyFile(dummyData, sizeof(dummyData)); std::optional dummyBitmapInfo = codec.TryReadInfo(dummyFile); EXPECT_FALSE(dummyBitmapInfo.has_value()); } } // ------------------------------------------------------------------------------------------- // TEST(TiffBitmapCodecTest, TryReadInfoThrowsOnCorruptedFile) { TiffBitmapCodec codec; { const InMemoryFile corruptTiffFile(corruptTiff, sizeof(corruptTiff)); EXPECT_THROW( { codec.TryReadInfo(corruptTiffFile); }, Errors::FileFormatError ); } } // ------------------------------------------------------------------------------------------- // TEST(TiffBitmapCodecTest, TryReadInfoSucceedsForTiffs) { TiffBitmapCodec codec; { const InMemoryFile testTiffFile(Tiff::testTiff, sizeof(Tiff::testTiff)); std::optional testTiffBitmapInfo = codec.TryReadInfo(testTiffFile); EXPECT_TRUE(testTiffBitmapInfo.has_value()); } } // ------------------------------------------------------------------------------------------- // TEST(TiffBitmapCodecTest, Loads32BitColorTiffs) { TiffBitmapCodec codec; { const InMemoryFile testPngFile(testTiff, sizeof(testTiff)); std::optional bitmap = codec.TryLoad(testPngFile); ASSERT_TRUE(bitmap.has_value()); Bitmap definitiveBitmap = bitmap.value(); const BitmapMemory &memory = definitiveBitmap.Access(); ASSERT_EQ(memory.PixelFormat, PixelFormat::R8_G8_B8_A8_Unsigned); std::uint8_t r = reinterpret_cast(memory.Pixels)[0]; std::uint8_t g = reinterpret_cast(memory.Pixels)[1]; std::uint8_t b = reinterpret_cast(memory.Pixels)[2]; std::uint8_t a = reinterpret_cast(memory.Pixels)[3]; EXPECT_EQ(r, 0U); EXPECT_EQ(g, 0U); EXPECT_EQ(b, 0U); EXPECT_EQ(a, 1U); r = reinterpret_cast(memory.Pixels)[4]; g = reinterpret_cast(memory.Pixels)[5]; b = reinterpret_cast(memory.Pixels)[6]; b = reinterpret_cast(memory.Pixels)[7]; EXPECT_EQ(r, 255U); EXPECT_EQ(g, 0U); EXPECT_EQ(b, 0U); EXPECT_EQ(a, 1U); /* r = reinterpret_cast(memory.Pixels)[6]; g = reinterpret_cast(memory.Pixels)[7]; b = reinterpret_cast(memory.Pixels)[8]; EXPECT_EQ(r, 0U); EXPECT_EQ(g, 255U); EXPECT_EQ(b, 0U); r = reinterpret_cast(memory.Pixels)[9]; g = reinterpret_cast(memory.Pixels)[10]; b = reinterpret_cast(memory.Pixels)[11]; EXPECT_EQ(r, 0U); EXPECT_EQ(g, 0U); EXPECT_EQ(b, 255U); r = reinterpret_cast(memory.Pixels)[12]; g = reinterpret_cast(memory.Pixels)[13]; b = reinterpret_cast(memory.Pixels)[14]; EXPECT_EQ(r, 255U); EXPECT_EQ(g, 255U); EXPECT_EQ(b, 255U); */ } } // ------------------------------------------------------------------------------------------- // }}}} // namespace Nuclex::Pixels::Storage::Tiff #endif // defined(NUCLEX_PIXELS_HAVE_LIBTIFF)