From 6ea868d7236197295ac94467e711f7b67393f2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 19 Aug 2015 20:31:36 +0200 Subject: [PATCH] TgaImageConverter: properly handle pixel storage alignment. --- .../Test/TgaImageConverterTest.cpp | 49 ++++++++++++++++--- .../TgaImageConverter/TgaImageConverter.cpp | 9 +++- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp b/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp index 9742db607..37770c202 100644 --- a/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp +++ b/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "Magnum/Image.h" @@ -46,24 +47,39 @@ class TgaImageConverterTest: public TestSuite::Tester { void wrongFormat(); void wrongType(); - void data(); + void rgb(); + void rgba(); }; namespace { - constexpr char originalData[] = { + /* Padded to four byte alignment (the resulting file is *not* padded) */ + constexpr char OriginalDataRGB[] = { + 1, 2, 3, 2, 3, 4, 0, 0, + 3, 4, 5, 4, 5, 6, 0, 0, + 5, 6, 7, 6, 7, 8, 0, 0 + }; + constexpr char ConvertedDataRGB[] = { 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6, 5, 6, 7, 6, 7, 8 }; - const ImageView2D original(PixelFormat::RGB, PixelType::UnsignedByte, {2, 3}, originalData); + const ImageView2D OriginalRGB{PixelFormat::RGB, PixelType::UnsignedByte, {2, 3}, OriginalDataRGB}; + + constexpr char OriginalDataRGBA[] = { + 1, 2, 3, 4, 2, 3, 4, 5, + 3, 4, 5, 6, 4, 5, 6, 7, + 5, 6, 7, 8, 6, 7, 8, 9 + }; + const ImageView2D OriginalRGBA{PixelFormat::RGBA, PixelType::UnsignedByte, {2, 3}, OriginalDataRGBA}; } TgaImageConverterTest::TgaImageConverterTest() { addTests({&TgaImageConverterTest::wrongFormat, &TgaImageConverterTest::wrongType, - &TgaImageConverterTest::data}); + &TgaImageConverterTest::rgb, + &TgaImageConverterTest::rgba}); } void TgaImageConverterTest::wrongFormat() { @@ -88,19 +104,36 @@ void TgaImageConverterTest::wrongType() { CORRADE_COMPARE(out.str(), "Trade::TgaImageConverter::exportToData(): unsupported color type PixelType::Float\n"); } -void TgaImageConverterTest::data() { - const auto data = TgaImageConverter().exportToData(original); +void TgaImageConverterTest::rgb() { + const auto data = TgaImageConverter().exportToData(OriginalRGB); TgaImporter importer; CORRADE_VERIFY(importer.openData(data)); std::optional converted = importer.image2D(0); CORRADE_VERIFY(converted); + CORRADE_COMPARE(converted->storage().alignment(), 1); CORRADE_COMPARE(converted->size(), Vector2i(2, 3)); CORRADE_COMPARE(converted->format(), PixelFormat::RGB); CORRADE_COMPARE(converted->type(), PixelType::UnsignedByte); - CORRADE_COMPARE((std::string{converted->data(), 2*3*3}), - (std::string{original.data(), 2*3*3})); + CORRADE_COMPARE_AS(converted->data(), Containers::ArrayView{ConvertedDataRGB}, + TestSuite::Compare::Container); +} + +void TgaImageConverterTest::rgba() { + const auto data = TgaImageConverter().exportToData(OriginalRGBA); + + TgaImporter importer; + CORRADE_VERIFY(importer.openData(data)); + std::optional converted = importer.image2D(0); + CORRADE_VERIFY(converted); + + CORRADE_COMPARE(converted->storage().alignment(), 4); + CORRADE_COMPARE(converted->size(), Vector2i(2, 3)); + CORRADE_COMPARE(converted->format(), PixelFormat::RGBA); + CORRADE_COMPARE(converted->type(), PixelType::UnsignedByte); + CORRADE_COMPARE_AS(converted->data(), Containers::ArrayView{OriginalDataRGBA}, + TestSuite::Compare::Container); } }}} diff --git a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp index aed8dc2d4..517ce9c73 100644 --- a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp +++ b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp @@ -90,8 +90,13 @@ Containers::Array TgaImageConverter::doExportToData(const ImageView2D& ima header->width = UnsignedShort(Utility::Endianness::littleEndian(image.size().x())); header->height = UnsignedShort(Utility::Endianness::littleEndian(image.size().y())); - /* Fill data */ - std::copy(image.data().data(), image.data()+pixelSize*image.size().product(), data.begin()+sizeof(TgaHeader)); + /* Fill data or copy them row by row if we need to drop the padding */ + const std::size_t rowSize = image.size().x()*pixelSize; + const std::size_t rowStride = std::get<1>(image.dataProperties()).x(); + if(rowStride != rowSize) { + for(std::int_fast32_t y = 0; y != image.size().y(); ++y) + std::copy_n(image.data() + y*rowStride, rowSize, data.begin() + sizeof(TgaHeader) + y*rowSize); + } else std::copy(image.data().data(), image.data()+pixelSize*image.size().product(), data.begin() + sizeof(TgaHeader)); if(image.format() == PixelFormat::RGB) { auto pixels = reinterpret_cast*>(data.begin()+sizeof(TgaHeader));