Browse Source

Fix image data size computation with pixel storage skip applied.

It now tries to find smallest line/rectangle/cube that covers the area.
Previously it was a bit more in some cases.
pull/162/merge
Vladimír Vondruš 10 years ago
parent
commit
1cfd2dc7b5
  1. 4
      src/Magnum/BufferImage.h
  2. 4
      src/Magnum/Image.h
  3. 2
      src/Magnum/ImageView.h
  4. 10
      src/Magnum/PixelStorage.cpp
  5. 63
      src/Magnum/PixelStorage.h
  6. 99
      src/Magnum/Test/PixelStorageTest.cpp
  7. 2
      src/Magnum/Trade/ImageData.cpp
  8. 2
      src/Magnum/Trade/ImageData.h
  9. 2
      src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp

4
src/Magnum/BufferImage.h

@ -145,7 +145,7 @@ template<UnsignedInt dimensions> class BufferImage {
* *
* See @ref PixelStorage::dataProperties() for more information. * See @ref PixelStorage::dataProperties() for more information.
*/ */
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const { std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::imageDataProperties<dimensions>(*this); return Implementation::imageDataProperties<dimensions>(*this);
} }
@ -333,7 +333,7 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL. * WebGL.
*/ */
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const { std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::compressedImageDataProperties<dimensions>(*this); return Implementation::compressedImageDataProperties<dimensions>(*this);
} }
#endif #endif

4
src/Magnum/Image.h

@ -135,7 +135,7 @@ template<UnsignedInt dimensions> class Image {
* *
* See @ref PixelStorage::dataProperties() for more information. * See @ref PixelStorage::dataProperties() for more information.
*/ */
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const { std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::imageDataProperties<dimensions>(*this); return Implementation::imageDataProperties<dimensions>(*this);
} }
@ -339,7 +339,7 @@ template<UnsignedInt dimensions> class CompressedImage {
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL. * WebGL.
*/ */
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const { std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::compressedImageDataProperties<dimensions>(*this); return Implementation::compressedImageDataProperties<dimensions>(*this);
} }
#endif #endif

2
src/Magnum/ImageView.h

@ -134,7 +134,7 @@ template<UnsignedInt dimensions> class ImageView {
* *
* See @ref PixelStorage::dataProperties() for more information. * See @ref PixelStorage::dataProperties() for more information.
*/ */
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const { std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::imageDataProperties<dimensions>(*this); return Implementation::imageDataProperties<dimensions>(*this);
} }

10
src/Magnum/PixelStorage.cpp

@ -156,7 +156,7 @@ std::size_t PixelStorage::pixelSize(PixelFormat format, PixelType type) {
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
} }
std::tuple<std::size_t, Math::Vector3<std::size_t>, std::size_t> PixelStorage::dataProperties(const PixelFormat format, const PixelType type, const Vector3i& size) const { std::tuple<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>, std::size_t> PixelStorage::dataProperties(const PixelFormat format, const PixelType type, const Vector3i& size) const {
const std::size_t pixelSize = PixelStorage::pixelSize(format, type); const std::size_t pixelSize = PixelStorage::pixelSize(format, type);
const Math::Vector3<std::size_t> dataSize{ const Math::Vector3<std::size_t> dataSize{
std::size_t(((( std::size_t((((
@ -170,13 +170,13 @@ std::tuple<std::size_t, Math::Vector3<std::size_t>, std::size_t> PixelStorage::d
std::size_t(size.y()), std::size_t(size.y()),
#endif #endif
std::size_t(size.z())}; std::size_t(size.z())};
const std::size_t offset = (Math::Vector3<std::size_t>{pixelSize, dataSize.x(), dataSize.xy().product()}*Math::Vector3<std::size_t>{_skip}).sum();
return std::make_tuple(offset, size.product() ? dataSize : Math::Vector3<std::size_t>{}, pixelSize); return std::make_tuple(Math::Vector3<std::size_t>{pixelSize, dataSize.x(), dataSize.xy().product()}*Math::Vector3<std::size_t>{_skip},
size.product() ? dataSize : Math::Vector3<std::size_t>{}, pixelSize);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
std::tuple<std::size_t, Math::Vector3<std::size_t>, std::size_t> CompressedPixelStorage::dataProperties(const Vector3i& size) const { std::tuple<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>, std::size_t> CompressedPixelStorage::dataProperties(const Vector3i& size) const {
CORRADE_ASSERT(_blockDataSize && _blockSize.product(), "CompressedPixelStorage::dataProperties(): expected non-zero storage parameters", {}); CORRADE_ASSERT(_blockDataSize && _blockSize.product(), "CompressedPixelStorage::dataProperties(): expected non-zero storage parameters", {});
const Vector3i blockCount = (size + _blockSize - Vector3i{1})/_blockSize; const Vector3i blockCount = (size + _blockSize - Vector3i{1})/_blockSize;
@ -186,7 +186,7 @@ std::tuple<std::size_t, Math::Vector3<std::size_t>, std::size_t> CompressedPixel
std::size_t(blockCount.z())}; std::size_t(blockCount.z())};
const Vector3i skipBlockCount = (_skip + _blockSize - Vector3i{1})/_blockSize; const Vector3i skipBlockCount = (_skip + _blockSize - Vector3i{1})/_blockSize;
const std::size_t offset = (Math::Vector3<std::size_t>{1, dataSize.x(), dataSize.xy().product()}*Math::Vector3<std::size_t>{skipBlockCount}).sum()*_blockDataSize; const Math::Vector3<std::size_t> offset = (Math::Vector3<std::size_t>{1, dataSize.x(), dataSize.xy().product()}*Math::Vector3<std::size_t>{skipBlockCount})*_blockDataSize;
return std::make_tuple(offset, size.product() ? dataSize : Math::Vector3<std::size_t>{}, _blockDataSize); return std::make_tuple(offset, size.product() ? dataSize : Math::Vector3<std::size_t>{}, _blockDataSize);
} }

63
src/Magnum/PixelStorage.h

@ -203,14 +203,14 @@ class MAGNUM_EXPORT PixelStorage {
/** /**
* @brief Data properties for given parameters * @brief Data properties for given parameters
* *
* Returns byte offset, (row length, row count, layer count) and pixel * Returns byte offset in each direction, (row length, row count, layer
* size for image of given @p size with current pixel storage * count) and pixel size for image of given @p size with current pixel
* parameters, @p format and @p type. The offset reflects the @ref skip() * storage parameters, @p format and @p type. The offset reflects the
* parameter. Adding byte offset and product of the vector gives * @ref skip() parameter. Adding byte offset and product of the vector
* minimal byte count to store given data. * gives minimal byte count to store given data.
* @see @ref pixelSize() * @see @ref pixelSize()
*/ */
std::tuple<std::size_t, Math::Vector3<std::size_t>, std::size_t> dataProperties(PixelFormat format, PixelType type, const Vector3i& size) const; std::tuple<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>, std::size_t> dataProperties(PixelFormat format, PixelType type, const Vector3i& size) const;
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
protected: protected:
@ -306,15 +306,16 @@ class MAGNUM_EXPORT CompressedPixelStorage: public PixelStorage {
/** /**
* @brief Data properties for given parameters * @brief Data properties for given parameters
* *
* Returns byte offset, count of blocks in each dimension and block * Returns byte offset in each dimension, count of blocks in each
* data size for image of given @p size with current pixel storage * dimension and block data size for image of given @p size with
* parameters. Adding byte offset and product of the vector multiplied * current pixel storage parameters. Adding byte offset and product of
* with block data size gives minimal byte count to store given data. * the vector multiplied with block data size gives minimal byte count
* to store given data.
* *
* Expects @ref compressedBlockSize() and @ref compressedBlockDataSize() * Expects @ref compressedBlockSize() and @ref compressedBlockDataSize()
* to be non-zero. * to be non-zero.
*/ */
std::tuple<std::size_t, Math::Vector3<std::size_t>, std::size_t> dataProperties(const Vector3i& size) const; std::tuple<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>, std::size_t> dataProperties(const Vector3i& size) const;
/* Overloads to remove WTF-factor from method chaining order */ /* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
@ -369,37 +370,38 @@ constexpr PixelStorage::PixelStorage() noexcept:
namespace Implementation { namespace Implementation {
/* Used in *Image::dataProperties() */ /* Used in *Image::dataProperties() */
template<std::size_t dimensions, class T> std::tuple<std::size_t, Math::Vector<dimensions, std::size_t>, std::size_t> imageDataProperties(const T& image) { template<std::size_t dimensions, class T> std::tuple<Math::Vector<dimensions, std::size_t>, Math::Vector<dimensions, std::size_t>, std::size_t> imageDataProperties(const T& image) {
std::size_t offset; Math::Vector3<std::size_t> offset, dataSize;
Math::Vector3<std::size_t> dataSize;
std::size_t pixelSize; std::size_t pixelSize;
std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(image.size(), 1)); std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(image.size(), 1));
return std::make_tuple(offset, Math::Vector<dimensions, std::size_t>::pad(dataSize), pixelSize); return std::make_tuple(Math::Vector<dimensions, std::size_t>::pad(offset), Math::Vector<dimensions, std::size_t>::pad(dataSize), pixelSize);
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/* Used in Compressed*Image::dataProperties() */ /* Used in Compressed*Image::dataProperties() */
template<std::size_t dimensions, class T> std::tuple<std::size_t, Math::Vector<dimensions, std::size_t>, std::size_t> compressedImageDataProperties(const T& image) { template<std::size_t dimensions, class T> std::tuple<Math::Vector<dimensions, std::size_t>, Math::Vector<dimensions, std::size_t>, std::size_t> compressedImageDataProperties(const T& image) {
std::size_t offset; Math::Vector3<std::size_t> offset, blockCount;
Math::Vector3<std::size_t> blockCount;
std::size_t blockSize; std::size_t blockSize;
std::tie(offset, blockCount, blockSize) = image.storage().dataProperties(Vector3i::pad(image.size(), 1)); std::tie(offset, blockCount, blockSize) = image.storage().dataProperties(Vector3i::pad(image.size(), 1));
return std::make_tuple(offset, Math::Vector<dimensions, std::size_t>::pad(blockCount), blockSize); return std::make_tuple(Math::Vector<dimensions, std::size_t>::pad(offset), Math::Vector<dimensions, std::size_t>::pad(blockCount), blockSize);
} }
#endif #endif
/* Used in image query functions */ /* Used in image query functions */
template<std::size_t dimensions, class T> std::size_t imageDataSizeFor(const T& image, const Math::Vector<dimensions, Int>& size) { template<std::size_t dimensions, class T> std::size_t imageDataSizeFor(const T& image, const Math::Vector<dimensions, Int>& size) {
const auto paddedSize = Vector3i::pad(size, 1); Math::Vector3<std::size_t> offset, dataSize;
std::size_t offset;
Math::Vector3<std::size_t> dataSize;
std::size_t pixelSize; std::size_t pixelSize;
std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), paddedSize); std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(size, 1));
/* I would subtract also (dataSize.x() - pixelSize*paddedSize.x()) but NVidia /* Smallest line/rectangle/cube that covers the area */
then complains that the buffer is too small */ std::size_t dataOffset = 0;
return offset + dataSize.product() - (dataSize.y() - paddedSize.y())*dataSize.x(); if(offset.z())
dataOffset += offset.z();
else if(offset.y())
dataOffset += offset.y();
else if(offset.x())
dataOffset += offset.x();
return dataOffset + dataSize.product();
} }
/* Used in data size assertions */ /* Used in data size assertions */
@ -419,14 +421,13 @@ namespace Implementation {
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
return {0, dataSize}; return {0, dataSize};
std::size_t offset; Math::Vector3<std::size_t> offset, blockCount;
Math::Vector3<std::size_t> blockCount;
std::size_t blockDataSize; std::size_t blockDataSize;
std::tie(offset, blockCount, blockDataSize) = image.storage().dataProperties(Vector3i::pad(size, 1)); std::tie(offset, blockCount, blockDataSize) = image.storage().dataProperties(Vector3i::pad(size, 1));
const auto realBlockCount = Math::Vector3<std::size_t>{(Vector3i::pad(size, 1) + image.storage().compressedBlockSize() - Vector3i{1})/image.storage().compressedBlockSize()}; const auto realBlockCount = Math::Vector3<std::size_t>{(Vector3i::pad(size, 1) + image.storage().compressedBlockSize() - Vector3i{1})/image.storage().compressedBlockSize()};
return {offset, (blockCount.product() - (blockCount.x() - realBlockCount.x()) - (blockCount.y() - realBlockCount.y())*blockCount.x())*blockDataSize}; return {offset.sum(), (blockCount.product() - (blockCount.x() - realBlockCount.x()) - (blockCount.y() - realBlockCount.y())*blockCount.x())*blockDataSize};
} }
/* Used in image query functions */ /* Used in image query functions */

99
src/Magnum/Test/PixelStorageTest.cpp

@ -45,7 +45,9 @@ struct PixelStorageTest: TestSuite::Tester {
void dataPropertiesImageHeight(); void dataPropertiesImageHeight();
#endif #endif
void dataSize(); void dataSize1D();
void dataSize2D();
void dataSize3D();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void dataPropertiesCompressed(); void dataPropertiesCompressed();
@ -70,7 +72,9 @@ PixelStorageTest::PixelStorageTest() {
&PixelStorageTest::dataPropertiesImageHeight, &PixelStorageTest::dataPropertiesImageHeight,
#endif #endif
&PixelStorageTest::dataSize, &PixelStorageTest::dataSize1D,
&PixelStorageTest::dataSize2D,
&PixelStorageTest::dataSize3D,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&PixelStorageTest::dataPropertiesCompressed, &PixelStorageTest::dataPropertiesCompressed,
@ -96,16 +100,16 @@ void PixelStorageTest::dataProperties() {
storage.setAlignment(1); storage.setAlignment(1);
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {0, 0, 0}, 4})); (std::tuple<Vector3st, Vector3st, std::size_t>{{}, {0, 0, 0}, 4}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {4, 1, 1}, 4})); (std::tuple<Vector3st, Vector3st, std::size_t>{{}, {4, 1, 1}, 4}));
#if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {8, 2, 1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {8, 2, 1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {8, 2, 1}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{}, {8, 2, 1}, 1}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {2, 4, 1}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{}, {2, 4, 1}, 1}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {2, 4, 6}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{}, {2, 4, 6}, 1}));
#endif #endif
} }
@ -115,16 +119,16 @@ void PixelStorageTest::dataPropertiesAlignment() {
.setSkip({3, 2, 1}); .setSkip({3, 2, 1});
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3*4, {0, 0, 0}, 4})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3*4, 0, 0}, {0, 0, 0}, 4}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{8 + 16 + 3*4, {8, 1, 1}, 4})); (std::tuple<Vector3st, Vector3st, std::size_t>{{12, 16, 8}, {8, 1, 1}, 4}));
#if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {8, 2, 1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {8, 2, 1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{16 + 16 + 3, {8, 2, 1}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 16, 16}, {8, 2, 1}, 1}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{32 + 16 + 3, {8, 4, 1}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 16, 32}, {8, 4, 1}, 1}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}),
(std::tuple<std::size_t, Vector3st, std::size_t>{32 + 16 + 3, {8, 4, 6}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 16, 32}, {8, 4, 6}, 1}));
#endif #endif
} }
@ -136,15 +140,15 @@ void PixelStorageTest::dataPropertiesRowLength() {
.setSkip({3, 7, 0}); .setSkip({3, 7, 0});
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3*4 + 7*15*4, {0, 0, 0}, 4})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3*4, 7*15*4, 0}, {0, 0, 0}, 4}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3*4 + 7*15*4, {60, 1, 1}, 4})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3*4, 7*15*4, 0}, {60, 1, 1}, 4}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {4, 2, 1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {4, 2, 1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3 + 7*16, {16, 2, 1}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 7*16, 0}, {16, 2, 1}, 1}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3 + 7*16, {16, 4, 1}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 7*16, 0}, {16, 4, 1}, 1}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3 + 7*16, {16, 4, 6}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 7*16, 0}, {16, 4, 6}, 1}));
} }
#endif #endif
@ -156,39 +160,66 @@ void PixelStorageTest::dataPropertiesImageHeight() {
.setSkip({3, 7, 2}); .setSkip({3, 7, 2});
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3*4, {0, 0, 0}, 4})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3*4, 0, 0}, {0, 0, 0}, 4}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3*4 + 7*1*4 + 2*128*1*4, {4, 128, 1}, 4})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3*4, 7*1*4, 2*128*1*4}, {4, 128, 1}, 4}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {4, 2, 1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {4, 2, 1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3 + 7*1*4 + 2*128*4, {4, 128, 1}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 7*1*4, 2*128*4}, {4, 128, 1}, 1}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3 + 7*1*2 + 2*128*2, {2, 128, 1}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 7*1*2, 2*128*2}, {2, 128, 1}, 1}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}),
(std::tuple<std::size_t, Vector3st, std::size_t>{3 + 7*1*2 + 2*128*2, {2, 128, 6}, 1})); (std::tuple<Vector3st, Vector3st, std::size_t>{{3, 7*1*2, 2*128*2}, {2, 128, 6}, 1}));
} }
#endif #endif
void PixelStorageTest::dataSize() { void PixelStorageTest::dataSize1D() {
const Image1D image{PixelStorage{}.setAlignment(2)
.setSkip({2, 0, 0}),
PixelFormat::RGB, PixelType::UnsignedByte};
CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Math::Vector<1, Int>{3}),
16);
}
void PixelStorageTest::dataSize2D() {
/* The same parameters as in PixelStorageGLTest 3D case */ /* The same parameters as in PixelStorageGLTest 3D case */
const Image2D image{PixelStorage{}.setAlignment(2) const Image2D image{PixelStorage{}.setAlignment(2)
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
.setRowLength(3) .setRowLength(7)
#endif
.setSkip({2, 3, 0}),
PixelFormat::RGB, PixelType::UnsignedByte};
#if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)
CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{5, 9}),
(3 + 9)*15);
#else
CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{5, 9}),
(3 + 9)*22);
#endif
}
void PixelStorageTest::dataSize3D() {
/* The same parameters as in PixelStorageGLTest 3D case */
const Image3D image{PixelStorage{}.setAlignment(2)
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
.setRowLength(7)
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.setImageHeight(5) .setImageHeight(10)
#endif #endif
.setSkip({2, 3, 1}), .setSkip({2, 3, 1}),
PixelFormat::RGB, PixelType::UnsignedByte}; PixelFormat::RGB, PixelType::UnsignedByte};
#if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)
CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{2, 3}), CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}),
3*6 + 3*6 + 6 + 3*6); (1 + 3)*9*15);
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{2, 3}), CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}),
3*10 + 3*10 + 6 + 3*10); (1 + 3)*9*22);
#else #else
CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{2, 3}), CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}),
5*10 + 3*10 + 6 + 3*10); (1 + 3)*10*22);
#endif #endif
} }
@ -199,7 +230,7 @@ void PixelStorageTest::dataPropertiesCompressed() {
.setCompressedBlockDataSize(16); .setCompressedBlockDataSize(16);
CORRADE_COMPARE(storage.dataProperties({2, 8, 11}), CORRADE_COMPARE(storage.dataProperties({2, 8, 11}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {1, 2, 3}, 16})); (std::tuple<Vector3st, Vector3st, std::size_t>{{}, {1, 2, 3}, 16}));
} }
void PixelStorageTest::dataPropertiesCompressedRowLength() { void PixelStorageTest::dataPropertiesCompressedRowLength() {
@ -210,7 +241,7 @@ void PixelStorageTest::dataPropertiesCompressedRowLength() {
.setSkip({5, 8, 0}); .setSkip({5, 8, 0});
CORRADE_COMPARE(storage.dataProperties({2, 8, 11}), CORRADE_COMPARE(storage.dataProperties({2, 8, 11}),
(std::tuple<std::size_t, Vector3st, std::size_t>{(2 + 8)*9, {4, 2, 3}, 9})); (std::tuple<Vector3st, Vector3st, std::size_t>{{2*9, 8*9, 0}, {4, 2, 3}, 9}));
} }
void PixelStorageTest::dataPropertiesCompressedImageHeight() { void PixelStorageTest::dataPropertiesCompressedImageHeight() {
@ -221,7 +252,7 @@ void PixelStorageTest::dataPropertiesCompressedImageHeight() {
.setSkip({5, 8, 11}); .setSkip({5, 8, 11});
CORRADE_COMPARE(storage.dataProperties({2, 8, 11}), CORRADE_COMPARE(storage.dataProperties({2, 8, 11}),
(std::tuple<std::size_t, Vector3st, std::size_t>{(2 + 2 + 9)*16, {1, 3, 3}, 16})); (std::tuple<Vector3st, Vector3st, std::size_t>{{2*16, 2*16, 9*16}, {1, 3, 3}, 16}));
} }
void PixelStorageTest::dataOffsetSizeCompressed() { void PixelStorageTest::dataOffsetSizeCompressed() {

2
src/Magnum/Trade/ImageData.cpp

@ -63,7 +63,7 @@ template<UnsignedInt dimensions> std::size_t ImageData<dimensions>::pixelSize()
return PixelStorage::pixelSize(_format, _type); return PixelStorage::pixelSize(_format, _type);
} }
template<UnsignedInt dimensions> std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> ImageData<dimensions>::dataProperties() const { template<UnsignedInt dimensions> std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> ImageData<dimensions>::dataProperties() const {
CORRADE_ASSERT(!_compressed, "Trade::ImageData::dataProperties(): the image is compressed", {}); CORRADE_ASSERT(!_compressed, "Trade::ImageData::dataProperties(): the image is compressed", {});
return Implementation::imageDataProperties<dimensions>(*this); return Implementation::imageDataProperties<dimensions>(*this);
} }

2
src/Magnum/Trade/ImageData.h

@ -210,7 +210,7 @@ template<UnsignedInt dimensions> class ImageData {
* @ref PixelStorage::dataProperties() for more information. * @ref PixelStorage::dataProperties() for more information.
* @see @ref isCompressed() * @see @ref isCompressed()
*/ */
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const; std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const;
/* compressed data properties are not available because the importers /* compressed data properties are not available because the importers
are not setting any block size pixel storage properties to avoid are not setting any block size pixel storage properties to avoid

2
src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp

@ -98,7 +98,7 @@ Containers::Array<char> TgaImageConverter::doExportToData(const ImageView2D& ima
header->height = UnsignedShort(Utility::Endianness::littleEndian(image.size().y())); header->height = UnsignedShort(Utility::Endianness::littleEndian(image.size().y()));
/* Image data pointer including skip */ /* Image data pointer including skip */
const char* imageData = image.data() + std::get<0>(image.dataProperties()); const char* imageData = image.data() + std::get<0>(image.dataProperties()).sum();
/* Fill data or copy them row by row if we need to drop the padding */ /* 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 rowSize = image.size().x()*pixelSize;

Loading…
Cancel
Save