diff --git a/src/AbstractImage.cpp b/src/AbstractImage.cpp index 8b646f9fe..fa6f7d599 100644 --- a/src/AbstractImage.cpp +++ b/src/AbstractImage.cpp @@ -26,6 +26,7 @@ #include +#include "Math/Vector.h" #include "ColorFormat.h" namespace Magnum { @@ -135,4 +136,18 @@ std::size_t AbstractImage::pixelSize(ColorFormat format, ColorType type) { CORRADE_ASSERT_UNREACHABLE(); } +template std::size_t AbstractImage::dataSize(Math::Vector size) const { + /** @todo Code this properly when all @fn_gl{PixelStore} parameters are implemented */ + /* Row size, rounded to multiple of 4 bytes */ + const std::size_t rowSize = ((size[0]*pixelSize() + 3)/4)*4; + + /** @todo Can't this be done somewhat nicer? */ + size[0] = 1; + return rowSize*size.product(); +} + +template std::size_t AbstractImage::dataSize<1>(Math::Vector<1, Int>) const; +template std::size_t AbstractImage::dataSize<2>(Math::Vector<2, Int>) const; +template std::size_t AbstractImage::dataSize<3>(Math::Vector<3, Int>) const; + } diff --git a/src/AbstractImage.h b/src/AbstractImage.h index f8506c399..fee386cea 100644 --- a/src/AbstractImage.h +++ b/src/AbstractImage.h @@ -79,6 +79,8 @@ class MAGNUM_EXPORT AbstractImage { ~AbstractImage() = default; + template std::size_t dataSize(Math::Vector size) const; + #ifdef DOXYGEN_GENERATING_OUTPUT private: #else diff --git a/src/BufferImage.h b/src/BufferImage.h index 637a995e5..d60e0692b 100644 --- a/src/BufferImage.h +++ b/src/BufferImage.h @@ -88,6 +88,11 @@ template class MAGNUM_EXPORT BufferImage: public Abstrac /** @brief %Image size */ typename DimensionTraits::VectorType size() const { return _size; } + /** @copydoc Image::dataSize() */ + std::size_t dataSize(const typename DimensionTraits::VectorType& size) const { + return AbstractImage::dataSize(size); + } + /** @brief %Image buffer */ Buffer& buffer() { return _buffer; } diff --git a/src/Image.h b/src/Image.h index 7af8728e0..abf1eb8ba 100644 --- a/src/Image.h +++ b/src/Image.h @@ -96,6 +96,17 @@ template class Image: public AbstractImage { /** @brief %Image size */ typename DimensionTraits::VectorType size() const { return _size; } + /** + * @brief Size of data required to store image of given size + * + * Takes color format, type and row alignment of this image into + * account. + * @see @ref pixelSize() + */ + std::size_t dataSize(const typename DimensionTraits::VectorType& size) const { + return AbstractImage::dataSize(size); + } + /** * @brief Pointer to raw data * diff --git a/src/ImageReference.h b/src/ImageReference.h index 02bd8141f..85661d201 100644 --- a/src/ImageReference.h +++ b/src/ImageReference.h @@ -76,6 +76,11 @@ template class ImageReference: public AbstractImage { /** @brief %Image size */ constexpr typename DimensionTraits::VectorType size() const { return _size; } + /** @copydoc Image::dataSize() */ + std::size_t dataSize(const typename DimensionTraits::VectorType& size) const { + return AbstractImage::dataSize(size); + } + /** @brief Pointer to raw data */ constexpr const unsigned char* data() const { return _data; } diff --git a/src/Test/AbstractImageTest.cpp b/src/Test/AbstractImageTest.cpp index fce4f355c..864a9e601 100644 --- a/src/Test/AbstractImageTest.cpp +++ b/src/Test/AbstractImageTest.cpp @@ -26,6 +26,7 @@ #include #include "AbstractImage.h" +#include "Image.h" #include "ColorFormat.h" namespace Magnum { namespace Test { @@ -35,6 +36,7 @@ class AbstractImageTest: public TestSuite::Tester { explicit AbstractImageTest(); void pixelSize(); + void dataSize(); void debugFormat(); void debugType(); @@ -42,6 +44,7 @@ class AbstractImageTest: public TestSuite::Tester { AbstractImageTest::AbstractImageTest() { addTests({&AbstractImageTest::pixelSize, + &AbstractImageTest::dataSize, &AbstractImageTest::debugFormat, &AbstractImageTest::debugType}); @@ -54,6 +57,17 @@ void AbstractImageTest::pixelSize() { CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::DepthStencil, ColorType::UnsignedInt248), 4); } +void AbstractImageTest::dataSize() { + /* Verify that row size is properly rounded */ + CORRADE_COMPARE(Image2D(ColorFormat::RGBA, ColorType::UnsignedByte).dataSize({}), 0); + CORRADE_COMPARE(Image2D(ColorFormat::Red, ColorType::UnsignedByte).dataSize({4, 2}), 8); + CORRADE_COMPARE(Image2D(ColorFormat::Red, ColorType::UnsignedByte).dataSize({2, 4}), 16); + CORRADE_COMPARE(Image2D(ColorFormat::RGBA, ColorType::UnsignedByte).dataSize(Vector2i(1)), 4); + + CORRADE_COMPARE(Image2D(ColorFormat::RGBA, ColorType::UnsignedShort).dataSize({16, 8}), + 4*2*16*8); +} + void AbstractImageTest::debugFormat() { std::ostringstream o; Debug(&o) << ColorFormat::RGBA; diff --git a/src/Trade/ImageData.h b/src/Trade/ImageData.h index bc2f09dd4..2fd5ae143 100644 --- a/src/Trade/ImageData.h +++ b/src/Trade/ImageData.h @@ -86,6 +86,11 @@ template class ImageData: public AbstractImage { /** @brief %Image size */ typename DimensionTraits::VectorType size() const { return _size; } + /** @copydoc Image::dataSize() */ + std::size_t dataSize(const typename DimensionTraits::VectorType& size) const { + return AbstractImage::dataSize(size); + } + /** * @brief Pointer to raw data *