Browse Source

Pixel storage support, part 5: new data properties computation.

Removed *Image::dataSize() and added *Image::dataProperties(), which
returns all properties separately for better introspection. This function
is now just an convenience alias to PixelStorage::dataProperties(), which
takes into account proper alignment and all other storage properties.
pull/107/head
Vladimír Vondruš 11 years ago
parent
commit
d314634352
  1. 8
      src/Magnum/AbstractFramebuffer.cpp
  2. 33
      src/Magnum/AbstractTexture.cpp
  3. 4
      src/Magnum/BufferImage.cpp
  4. 35
      src/Magnum/BufferImage.h
  5. 49
      src/Magnum/CubeMapTexture.cpp
  6. 33
      src/Magnum/Image.h
  7. 35
      src/Magnum/ImageView.h
  8. 50
      src/Magnum/PixelStorage.cpp
  9. 125
      src/Magnum/PixelStorage.h
  10. 2
      src/Magnum/Test/BufferImageGLTest.cpp
  11. 190
      src/Magnum/Test/PixelStorageTest.cpp
  12. 8
      src/Magnum/Trade/ImageData.cpp
  13. 20
      src/Magnum/Trade/ImageData.h

8
src/Magnum/AbstractFramebuffer.cpp

@ -280,10 +280,10 @@ AbstractFramebuffer& AbstractFramebuffer::clear(const FramebufferClearMask mask)
void AbstractFramebuffer::read(const Range2Di& rectangle, Image2D& image) {
bindInternal(FramebufferTarget::Read);
const std::size_t dataSize = image.dataSize(rectangle.size());
const std::size_t dataSize = Implementation::imageDataSizeFor(image, rectangle.size());
char* const data = new char[dataSize];
(Context::current()->state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), dataSize, data);
image.setData(image.format(), image.type(), rectangle.size(), data);
image.setData(image.storage(), image.format(), image.type(), rectangle.size(), data);
}
Image2D AbstractFramebuffer::read(const Range2Di& rectangle, Image2D&& image) {
@ -297,10 +297,10 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D& image,
/* If the buffer doesn't have sufficient size, resize it */
/** @todo Explicitly reset also when buffer usage changes */
if(image.size() != rectangle.size())
image.setData(image.format(), image.type(), rectangle.size(), nullptr, usage);
image.setData(image.storage(), image.format(), image.type(), rectangle.size(), nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(Context::current()->state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), image.dataSize(rectangle.size()), nullptr);
(Context::current()->state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), Implementation::imageDataSizeFor(image, rectangle.size()), nullptr);
}
BufferImage2D AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D&& image, BufferUsage usage) {

33
src/Magnum/AbstractTexture.cpp

@ -1494,12 +1494,12 @@ void AbstractTexture::invalidateSubImageImplementationARB(GLint level, const Vec
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, Image<dimensions>& image) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level);
const std::size_t dataSize = image.dataSize(size);
const std::size_t dataSize = Implementation::imageDataSizeFor(image, size);
char* data = new char[dataSize];
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getImageImplementation)(level, image.format(), image.type(), dataSize, data);
image.setData(image.format(), image.type(), size, data);
image.setData(image.storage(), image.format(), image.type(), size, data);
}
template void MAGNUM_EXPORT AbstractTexture::image<1>(GLint, Image<1>&);
@ -1508,9 +1508,9 @@ template void MAGNUM_EXPORT AbstractTexture::image<3>(GLint, Image<3>&);
template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, BufferImage<dimensions>& image, BufferUsage usage) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level);
const std::size_t dataSize = image.dataSize(size);
const std::size_t dataSize = Implementation::imageDataSizeFor(image, size);
if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage);
image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getImageImplementation)(level, image.format(), image.type(), dataSize, nullptr);
@ -1522,15 +1522,15 @@ template void MAGNUM_EXPORT AbstractTexture::image<3>(GLint, BufferImage<3>&, Bu
template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLint level, CompressedImage<dimensions>& image) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level);
GLint dataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize);
GLint textureDataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
GLint format;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
Containers::Array<char> data{std::size_t(dataSize)};
Containers::Array<char> data{Implementation::compressedImageDataSizeFor(image, size, textureDataSize)};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getCompressedImageImplementation)(level, dataSize, data);
image.setData(CompressedPixelFormat(format), size, std::move(data));
(this->*Context::current()->state().texture->getCompressedImageImplementation)(level, data.size(), data);
image.setData(image.storage(), CompressedPixelFormat(format), size, std::move(data));
}
template void MAGNUM_EXPORT AbstractTexture::compressedImage<1>(GLint, CompressedImage<1>&);
@ -1539,12 +1539,13 @@ template void MAGNUM_EXPORT AbstractTexture::compressedImage<3>(GLint, Compresse
template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLint level, CompressedBufferImage<dimensions>& image, BufferUsage usage) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level);
GLint dataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize);
GLint textureDataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize);
GLint format;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
image.setData(CompressedPixelFormat(format), size, {nullptr, std::size_t(dataSize)}, usage);
image.setData(image.storage(), CompressedPixelFormat(format), size, {nullptr, dataSize}, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getCompressedImageImplementation)(level, dataSize, nullptr);
}
@ -1559,12 +1560,12 @@ template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint leve
const Math::Vector<dimensions, Int> size = range.size();
const Vector3i paddedOffset = Vector3i::pad(range.min());
const Vector3i paddedSize = Vector3i::pad(size, 1);
const std::size_t dataSize = image.dataSize(size);
const std::size_t dataSize = Implementation::imageDataSizeFor(image, size);
char* data = new char[dataSize];
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), dataSize, data);
image.setData(image.format(), image.type(), size, data);
image.setData(image.storage(), image.format(), image.type(), size, data);
}
template void MAGNUM_EXPORT AbstractTexture::subImage<1>(GLint, const Range1Di&, Image<1>&);
@ -1575,11 +1576,11 @@ template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint leve
createIfNotAlready();
const Math::Vector<dimensions, Int> size = range.size();
const std::size_t dataSize = image.dataSize(size);
const std::size_t dataSize = Implementation::imageDataSizeFor(image, size);
const Vector3i paddedOffset = Vector3i::pad(range.min());
const Vector3i paddedSize = Vector3i::pad(size, 1);
if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage);
image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), dataSize, nullptr);

4
src/Magnum/BufferImage.cpp

@ -29,7 +29,7 @@ namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor<dimensions, Int>& size, const void* const data, const BufferUsage usage): _storage{storage}, _format{format}, _type{type}, _size{size}, _buffer{Buffer::TargetHint::PixelPack} {
_buffer.setData({data, dataSize(size)}, usage);
_buffer.setData({data, Implementation::imageDataSizeFor(*this, size)}, usage);
}
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type): _storage{storage}, _format{format}, _type{type}, _buffer{Buffer::TargetHint::PixelPack} {}
@ -39,7 +39,7 @@ template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(const Pix
_format = format;
_type = type;
_size = size;
_buffer.setData({data, dataSize(size)}, usage);
_buffer.setData({data, Implementation::imageDataSizeFor(*this, size)}, usage);
}
template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(

35
src/Magnum/BufferImage.h

@ -34,7 +34,7 @@
#include "Magnum/Buffer.h"
#include "Magnum/DimensionTraits.h"
#include "Magnum/PixelStorage.h"
#include "Magnum/Math/Vector3.h"
#include "Magnum/Math/Vector4.h"
namespace Magnum {
@ -115,15 +115,23 @@ template<UnsignedInt dimensions> class BufferImage {
/** @brief Data type of pixel data */
PixelType type() const { return _type; }
/** @brief Pixel size (in bytes) */
std::size_t pixelSize() const { return Implementation::imagePixelSize(_format, _type); }
/**
* @brief Pixel size (in bytes)
*
* @see @ref PixelStorage::pixelSize()
*/
std::size_t pixelSize() const { return PixelStorage::pixelSize(_format, _type); }
/** @brief Image size */
VectorTypeFor<Dimensions, Int> size() const { return _size; }
/** @copydoc Image::dataSize() */
std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const {
return Implementation::imageDataSize<dimensions>(_format, _type, size);
/**
* @brief Image data properties
*
* See @ref PixelStorage::dataProperties() for more information.
*/
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::imageDataProperties<dimensions>(*this);
}
/** @brief Image buffer */
@ -274,6 +282,21 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
/** @brief Image size */
VectorTypeFor<Dimensions, Int> size() const { return _size; }
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Compressed image data properties
*
* See @ref CompressedPixelStorage::dataProperties() for more
* information.
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::compressedImageDataProperties<dimensions>(*this);
}
#endif
/** @brief Image buffer */
Buffer& buffer() { return _buffer; }

49
src/Magnum/CubeMapTexture.cpp

@ -60,11 +60,11 @@ void CubeMapTexture::image(const Int level, Image3D& image) {
createIfNotAlready();
const Vector3i size{imageSize(level), 6};
const std::size_t dataSize = image.dataSize(size);
const std::size_t dataSize = Implementation::imageDataSizeFor(image, size);
char* data = new char[dataSize];
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
glGetTextureImage(_id, level, GLenum(image.format()), GLenum(image.type()), dataSize, data);
image.setData(image.format(), image.type(), size, data);
image.setData(image.storage(), image.format(), image.type(), size, data);
}
Image3D CubeMapTexture::image(const Int level, Image3D&& image) {
@ -76,9 +76,9 @@ void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUs
createIfNotAlready();
const Vector3i size{imageSize(level), 6};
const std::size_t dataSize = image.dataSize(size);
const std::size_t dataSize = Implementation::imageDataSizeFor(image, size);
if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage);
image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
glGetTextureImage(_id, level, GLenum(image.format()), GLenum(image.type()), dataSize, nullptr);
@ -93,15 +93,16 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image)
createIfNotAlready();
const Vector3i size{imageSize(level), 6};
GLint dataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize);
GLint textureDataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize);
GLint format;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
Containers::Array<char> data{std::size_t(dataSize)};
Containers::Array<char> data{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
glGetCompressedTextureImage(_id, level, dataSize, data);
image.setData(CompressedPixelFormat(format), size, std::move(data));
image.setData(image.storage(), CompressedPixelFormat(format), size, std::move(data));
}
CompressedImage3D CubeMapTexture::compressedImage(const Int level, CompressedImage3D&& image) {
@ -113,13 +114,14 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i
createIfNotAlready();
const Vector3i size{imageSize(level), 6};
GLint dataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize);
GLint textureDataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize);
GLint format;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
image.setData(CompressedPixelFormat(format), size, {nullptr, std::size_t(dataSize)}, usage);
image.setData(image.storage(), CompressedPixelFormat(format), size, {nullptr, dataSize}, usage);
glGetCompressedTextureImage(_id, level, dataSize, nullptr);
}
@ -130,12 +132,12 @@ CompressedBufferImage3D CubeMapTexture::compressedImage(const Int level, Compres
void CubeMapTexture::image(const Coordinate coordinate, const Int level, Image2D& image) {
const Vector2i size = imageSize(level);
const std::size_t dataSize = image.dataSize(size);
const std::size_t dataSize = Implementation::imageDataSizeFor(image, size);
char* data = new char[dataSize];
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, data);
image.setData(image.format(), image.type(), size, data);
image.setData(image.storage(), image.format(), image.type(), size, data);
}
Image2D CubeMapTexture::image(const Coordinate coordinate, const Int level, Image2D&& image) {
@ -145,9 +147,9 @@ Image2D CubeMapTexture::image(const Coordinate coordinate, const Int level, Imag
void CubeMapTexture::image(const Coordinate coordinate, const Int level, BufferImage2D& image, const BufferUsage usage) {
const Vector2i size = imageSize(level);
const std::size_t dataSize = image.dataSize(size);
const std::size_t dataSize = Implementation::imageDataSizeFor(image, size);
if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage);
image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, nullptr);
@ -160,15 +162,15 @@ BufferImage2D CubeMapTexture::image(const Coordinate coordinate, const Int level
void CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedImage2D& image) {
const Vector2i size = imageSize(level);
GLint dataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize);
GLint textureDataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
GLint format;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
Containers::Array<char> data{std::size_t(dataSize)};
Containers::Array<char> data{Implementation::compressedImageDataSizeFor(image, size, textureDataSize)};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, data);
image.setData(CompressedPixelFormat(format), size, std::move(data));
(this->*Context::current()->state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, data.size(), data);
image.setData(image.storage(), CompressedPixelFormat(format), size, std::move(data));
}
CompressedImage2D CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedImage2D&& image) {
@ -178,12 +180,13 @@ CompressedImage2D CubeMapTexture::compressedImage(const Coordinate coordinate, c
void CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedBufferImage2D& image, const BufferUsage usage) {
const Vector2i size = imageSize(level);
GLint dataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize);
GLint textureDataSize;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize);
GLint format;
(this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
image.setData(CompressedPixelFormat(format), size, {nullptr, std::size_t(dataSize)}, usage);
image.setData(image.storage(), CompressedPixelFormat(format), size, {nullptr, dataSize}, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, nullptr);
}

33
src/Magnum/Image.h

@ -123,21 +123,23 @@ template<UnsignedInt dimensions> class Image {
/** @brief Data type of pixel data */
PixelType type() const { return _type; }
/** @brief Pixel size (in bytes) */
std::size_t pixelSize() const { return Implementation::imagePixelSize(_format, _type); }
/**
* @brief Pixel size (in bytes)
*
* @see @ref PixelStorage::pixelSize()
*/
std::size_t pixelSize() const { return PixelStorage::pixelSize(_format, _type); }
/** @brief Image size */
VectorTypeFor<dimensions, Int> size() const { return _size; }
/**
* @brief Size of data required to store image of given size
* @brief Image data properties
*
* Takes color format, type and row alignment of this image into
* account.
* @see @ref pixelSize()
* See @ref PixelStorage::dataProperties() for more information.
*/
std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const {
return Implementation::imageDataSize<dimensions>(_format, _type, size);
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::imageDataProperties<dimensions>(*this);
}
/**
@ -310,6 +312,21 @@ template<UnsignedInt dimensions> class CompressedImage {
/** @brief Image size */
VectorTypeFor<dimensions, Int> size() const { return _size; }
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Compressed image data properties
*
* See @ref CompressedPixelStorage::dataProperties() for more
* information.
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::compressedImageDataProperties<dimensions>(*this);
}
#endif
/** @brief Raw data */
Containers::ArrayView<char> data() { return _data; }

35
src/Magnum/ImageView.h

@ -33,7 +33,7 @@
#include "Magnum/DimensionTraits.h"
#include "Magnum/PixelStorage.h"
#include "Magnum/Math/Vector3.h"
#include "Magnum/Math/Vector4.h"
namespace Magnum {
@ -100,15 +100,23 @@ template<UnsignedInt dimensions> class ImageView {
/** @brief Data type of pixel data */
PixelType type() const { return _type; }
/** @brief Pixel size (in bytes) */
std::size_t pixelSize() const { return Implementation::imagePixelSize(_format, _type); }
/**
* @brief Pixel size (in bytes)
*
* @see @ref PixelStorage::pixelSize()
*/
std::size_t pixelSize() const { return PixelStorage::pixelSize(_format, _type); }
/** @brief Image size */
constexpr VectorTypeFor<dimensions, Int> size() const { return _size; }
/** @copydoc Image::dataSize() */
std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const {
return Implementation::imageDataSize<dimensions>(*this, _format, _type, size);
/**
* @brief Image data properties
*
* See @ref PixelStorage::dataProperties() for more information.
*/
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::imageDataProperties<dimensions>(*this);
}
/** @brief Pointer to raw data */
@ -233,6 +241,21 @@ template<UnsignedInt dimensions> class CompressedImageView {
/** @brief Image size */
constexpr VectorTypeFor<dimensions, Int> size() const { return _size; }
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Compressed image data properties
*
* See @ref CompressedPixelStorage::dataProperties() for more
* information.
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::compressedImageDataProperties<dimensions>(*this);
}
#endif
/** @brief Raw data */
constexpr Containers::ArrayView<const char> data() const { return _data; }

50
src/Magnum/PixelStorage.cpp

@ -28,11 +28,11 @@
#include <Corrade/Utility/Assert.h>
#include "Magnum/PixelFormat.h"
#include "Magnum/Math/Vector.h"
#include "Magnum/Math/Vector4.h"
namespace Magnum { namespace Implementation {
namespace Magnum {
std::size_t imagePixelSize(PixelFormat format, PixelType type) {
std::size_t PixelStorage::pixelSize(PixelFormat format, PixelType type) {
std::size_t size = 0;
switch(type) {
case PixelType::UnsignedByte:
@ -151,18 +151,40 @@ std::size_t imagePixelSize(PixelFormat format, PixelType type) {
CORRADE_ASSERT_UNREACHABLE();
}
template<UnsignedInt dimensions> std::size_t imageDataSize(const PixelFormat format, const PixelType type, Math::Vector<dimensions, Int> size) {
/** @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]*imagePixelSize(format, type) + 3)/4)*4;
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 {
const std::size_t pixelSize = PixelStorage::pixelSize(format, type);
const Math::Vector3<std::size_t> dataSize{
std::size_t((((
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
_rowLength ? _rowLength*pixelSize :
#endif
size[0]*pixelSize) + _alignment - 1)/_alignment)*_alignment),
#ifndef MAGNUM_TARGET_GLES2
std::size_t(_imageHeight ? _imageHeight : size.y()),
#else
std::size_t(size.y()),
#endif
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();
/** @todo Can't this be done somewhat nicer? */
size[0] = 1;
return rowSize*size.product();
return std::make_tuple(offset, size.product() ? dataSize : Math::Vector3<std::size_t>{}, pixelSize);
}
template MAGNUM_EXPORT std::size_t imageDataSize<1>(PixelFormat, PixelType, Math::Vector<1, Int>);
template MAGNUM_EXPORT std::size_t imageDataSize<2>(PixelFormat, PixelType, Math::Vector<2, Int>);
template MAGNUM_EXPORT std::size_t imageDataSize<3>(PixelFormat, PixelType, Math::Vector<3, Int>);
#ifndef MAGNUM_TARGET_GLES
std::tuple<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", {});
const Vector3i blockCount = (size + _blockSize - Vector3i{1})/_blockSize;
const Math::Vector3<std::size_t> dataSize{
std::size_t(_rowLength ? (_rowLength + _blockSize.x() - 1)/_blockSize.x() : blockCount.x()),
std::size_t(_imageHeight ? (_imageHeight + _blockSize.y() - 1)/_blockSize.y() : blockCount.y()),
std::size_t(blockCount.z())};
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;
}}
return std::make_tuple(offset, size.product() ? dataSize : Math::Vector3<std::size_t>{}, _blockDataSize);
}
#endif
}

125
src/Magnum/PixelStorage.h

@ -30,6 +30,7 @@
*/
#include <cstddef>
#include <tuple>
#include "Magnum/Magnum.h"
#include "Magnum/visibility.h"
@ -37,12 +38,6 @@
namespace Magnum {
namespace Implementation {
std::size_t MAGNUM_EXPORT imagePixelSize(PixelFormat format, PixelType type);
template<UnsignedInt dimensions> std::size_t imageDataSize(PixelFormat format, PixelType type, Math::Vector<dimensions, Int> size);
}
/**
@brief Pixel storage parameters
@ -63,8 +58,15 @@ currently used pixel pack/unpack parameters to avoid unnecessary calls to
@see @ref CompressedPixelStorage
*/
class PixelStorage {
class MAGNUM_EXPORT PixelStorage {
public:
/**
* @brief Pixel size for given format/type combination (in bytes)
*
* @see @ref dataProperties()
*/
static std::size_t pixelSize(PixelFormat format, PixelType type);
/**
* @brief Default constructor
*
@ -192,11 +194,23 @@ class PixelStorage {
return *this;
}
/**
* @brief Data properties for given parameters
*
* Returns byte offset, (row length, row count, layer count) and pixel
* size for image of given @p size with current pixel storage
* parameters, @p format and @p type. The offset reflects the @ref skip()
* parameter. Adding byte offset and product of the vector gives
* minimal byte count to store given data.
* @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;
#ifndef DOXYGEN_GENERATING_OUTPUT
protected:
#else
private:
#ifndef MAGNUM_TARGET_GLES
bool _swapBytes;
#endif
Int _alignment;
#endif
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
Int _rowLength;
#endif
@ -204,6 +218,12 @@ class PixelStorage {
Int _imageHeight;
#endif
Vector3i _skip;
private:
#ifndef MAGNUM_TARGET_GLES
bool _swapBytes;
#endif
Int _alignment;
};
#ifndef MAGNUM_TARGET_GLES
@ -223,7 +243,7 @@ Includes all parameters from @ref PixelStorage, except for @ref swapBytes() and
@requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
@requires_gl Compressed pixel storage is hardcoded in OpenGL ES and WebGL.
*/
class CompressedPixelStorage: public PixelStorage {
class MAGNUM_EXPORT CompressedPixelStorage: public PixelStorage {
public:
/**
* @brief Default constructor
@ -261,6 +281,19 @@ class CompressedPixelStorage: public PixelStorage {
return *this;
}
/**
* @brief Data properties for given parameters
*
* Returns byte offset, count of blocks in each dimension and block
* data size for image of given @p size with current pixel storage
* parameters. Adding byte offset and product of the vector multiplied
* with block data size gives minimal byte count to store given data.
*
* Expects @ref compressedBlockSize() and @ref compressedBlockDataSize()
* to be non-zero.
*/
std::tuple<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 */
#ifndef DOXYGEN_GENERATING_OUTPUT
CompressedPixelStorage& setRowLength(Int length) {
@ -291,17 +324,75 @@ class CompressedPixelStorage: public PixelStorage {
#endif
constexpr PixelStorage::PixelStorage() noexcept:
#ifndef MAGNUM_TARGET_GLES
_swapBytes{false},
#endif
_alignment{4},
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
_rowLength{0},
#endif
#ifndef MAGNUM_TARGET_GLES2
_imageHeight{0},
#endif
_skip{0} {}
_skip{0},
#ifndef MAGNUM_TARGET_GLES
_swapBytes{false},
#endif
_alignment{4} {}
namespace Implementation {
/* 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) {
std::size_t offset;
Math::Vector3<std::size_t> dataSize;
std::size_t pixelSize;
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);
}
#ifndef MAGNUM_TARGET_GLES2
/* 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) {
std::size_t offset;
Math::Vector3<std::size_t> blockCount;
std::size_t blockSize;
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);
}
#endif
/* 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) {
const auto paddedSize = Vector3i::pad(size, 1);
std::size_t offset;
Math::Vector3<std::size_t> dataSize;
std::size_t pixelSize;
std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), paddedSize);
/* I would subtract also (dataSize.x() - pixelSize*paddedSize.x()) but NVidia
then complains that the buffer is too small */
return offset + dataSize.product() - (dataSize.y() - paddedSize.y())*dataSize.x();
}
/* Used in data size assertions */
template<class T> inline std::size_t imageDataSize(const T& image) {
return imageDataSizeFor(image, image.size());
}
#ifndef MAGNUM_TARGET_GLES
/* Used in image query functions */
template<std::size_t dimensions, class T> std::size_t compressedImageDataSizeFor(const T& image, const Math::Vector<dimensions, Int>& size, std::size_t dataSize) {
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
return dataSize;
std::size_t offset;
Math::Vector3<std::size_t> blockCount;
std::size_t blockDataSize;
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()};
return offset + (blockCount.product() - (blockCount.x() - realBlockCount.x()) - (blockCount.y() - realBlockCount.y())*blockCount.x())*blockDataSize;
}
#endif
}
}

2
src/Magnum/Test/BufferImageGLTest.cpp

@ -58,7 +58,7 @@ BufferImageGLTest::BufferImageGLTest() {
}
void BufferImageGLTest::construct() {
const char data[] = { 'a', 0, 0, 0, 'b', 0, 0, 0, 'c', 0, 0, 0 };
const char data[] = { 'a', 'b', 'c' };
BufferImage2D a{PixelStorage{}.setAlignment(1),
PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, data, BufferUsage::StaticDraw};

190
src/Magnum/Test/PixelStorageTest.cpp

@ -35,31 +35,195 @@ struct PixelStorageTest: TestSuite::Tester {
explicit PixelStorageTest();
void pixelSize();
void dataProperties();
void dataPropertiesAlignment();
void dataPropertiesRowLength();
#ifndef MAGNUM_TARGET_GLES2
void dataPropertiesImageHeight();
#endif
void dataSize();
#ifndef MAGNUM_TARGET_GLES
void dataPropertiesCompressed();
void dataPropertiesCompressedRowLength();
void dataPropertiesCompressedImageHeight();
void dataSizeCompressed();
#endif
};
typedef Math::Vector3<std::size_t> Vector3st;
PixelStorageTest::PixelStorageTest() {
addTests({&PixelStorageTest::pixelSize,
&PixelStorageTest::dataSize});
&PixelStorageTest::dataProperties,
&PixelStorageTest::dataPropertiesAlignment,
&PixelStorageTest::dataPropertiesRowLength,
#ifndef MAGNUM_TARGET_GLES2
&PixelStorageTest::dataPropertiesImageHeight,
#endif
&PixelStorageTest::dataSize,
#ifndef MAGNUM_TARGET_GLES
&PixelStorageTest::dataPropertiesCompressed,
&PixelStorageTest::dataPropertiesCompressedRowLength,
&PixelStorageTest::dataPropertiesCompressedImageHeight,
&PixelStorageTest::dataSizeCompressed
#endif
});
}
void PixelStorageTest::pixelSize() {
CORRADE_COMPARE(Implementation::imagePixelSize(PixelFormat::RGBA, PixelType::UnsignedInt), 4*4);
CORRADE_COMPARE(Implementation::imagePixelSize(PixelFormat::DepthComponent, PixelType::UnsignedShort), 2);
CORRADE_COMPARE(Implementation::imagePixelSize(PixelFormat::StencilIndex, PixelType::UnsignedByte), 1);
CORRADE_COMPARE(Implementation::imagePixelSize(PixelFormat::DepthStencil, PixelType::UnsignedInt248), 4);
CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::RGBA, PixelType::UnsignedInt), 4*4);
CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::DepthComponent, PixelType::UnsignedShort), 2);
CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::StencilIndex, PixelType::UnsignedByte), 1);
CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::DepthStencil, PixelType::UnsignedInt248), 4);
}
void PixelStorageTest::dataProperties() {
PixelStorage storage;
storage.setAlignment(1);
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {0, 0, 0}, 4}));
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {4, 1, 1}, 4}));
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}));
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}));
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}));
}
void PixelStorageTest::dataPropertiesAlignment() {
PixelStorage storage;
storage.setAlignment(8)
.setSkip({3, 2, 1});
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}));
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}));
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}));
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}));
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}));
}
void PixelStorageTest::dataPropertiesRowLength() {
PixelStorage storage;
storage.setAlignment(4)
.setRowLength(15)
.setSkip({3, 7, 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}));
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}));
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}));
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}));
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}));
}
#ifndef MAGNUM_TARGET_GLES2
void PixelStorageTest::dataPropertiesImageHeight() {
PixelStorage storage;
storage.setAlignment(1)
.setImageHeight(128)
.setSkip({3, 7, 2});
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}));
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}));
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}));
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}));
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}));
}
#endif
void PixelStorageTest::dataSize() {
/* Verify that row size is properly rounded */
CORRADE_COMPARE(Image2D(PixelFormat::RGBA, PixelType::UnsignedByte).dataSize({}), 0);
CORRADE_COMPARE(Image2D(PixelFormat::Red, PixelType::UnsignedByte).dataSize({4, 2}), 8);
CORRADE_COMPARE(Image2D(PixelFormat::Red, PixelType::UnsignedByte).dataSize({2, 4}), 16);
CORRADE_COMPARE(Image2D(PixelFormat::RGBA, PixelType::UnsignedByte).dataSize(Vector2i(1)), 4);
CORRADE_COMPARE(Image2D(PixelFormat::RGBA, PixelType::UnsignedShort).dataSize({16, 8}),
4*2*16*8);
/* The same parameters as in PixelStorageGLTest 3D case */
const Image2D image{PixelStorage{}.setAlignment(2)
.setRowLength(3)
#ifndef MAGNUM_TARGET_GLES2
.setImageHeight(5)
#endif
.setSkip({2, 3, 1}),
PixelFormat::RGB, PixelType::UnsignedByte};
#ifndef MAGNUM_TARGET_GLES2
CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{2, 3}),
5*10 + 3*10 + 6 + 3*10);
#else
CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{2, 3}),
3*10 + 3*10 + 6 + 3*10);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void PixelStorageTest::dataPropertiesCompressed() {
CompressedPixelStorage storage;
storage.setCompressedBlockSize({3, 4, 5})
.setCompressedBlockDataSize(16);
CORRADE_COMPARE(storage.dataProperties({2, 8, 11}),
(std::tuple<std::size_t, Vector3st, std::size_t>{0, {1, 2, 3}, 16}));
}
void PixelStorageTest::dataPropertiesCompressedRowLength() {
CompressedPixelStorage storage;
storage.setCompressedBlockSize({3, 4, 5})
.setCompressedBlockDataSize(9)
.setRowLength(12)
.setSkip({5, 8, 0});
CORRADE_COMPARE(storage.dataProperties({2, 8, 11}),
(std::tuple<std::size_t, Vector3st, std::size_t>{(2 + 8)*9, {4, 2, 3}, 9}));
}
void PixelStorageTest::dataPropertiesCompressedImageHeight() {
CompressedPixelStorage storage;
storage.setCompressedBlockSize({3, 4, 5})
.setCompressedBlockDataSize(16)
.setImageHeight(12)
.setSkip({5, 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}));
}
void PixelStorageTest::dataSizeCompressed() {
/* Tf the storage doesn't contain any info about block sizes (the default,
using the provided value */
CORRADE_COMPARE(Implementation::compressedImageDataSizeFor(CompressedImage3D{},
Vector2i{37, 35}, 1579), 1579);
/* The same parameters as in PixelStorageGLTest 3D case */
const CompressedImage3D image{CompressedPixelStorage{}
.setCompressedBlockSize({4, 4, 1})
.setCompressedBlockDataSize(16)
.setRowLength(8)
.setImageHeight(8)
.setSkip({4, 4, 4})};
CORRADE_COMPARE(Implementation::compressedImageDataSizeFor(image, Vector3i{4, 4, 1}, 1579),
16*4*4 + 16*4);
}
#endif
}}

8
src/Magnum/Trade/ImageData.cpp

@ -56,12 +56,12 @@ template<UnsignedInt dimensions> CompressedPixelFormat ImageData<dimensions>::co
template<UnsignedInt dimensions> std::size_t ImageData<dimensions>::pixelSize() const {
CORRADE_ASSERT(!_compressed, "Trade::ImageData::pixelSize(): the image is compressed", {});
return Implementation::imagePixelSize(_format, _type);
return PixelStorage::pixelSize(_format, _type);
}
template<UnsignedInt dimensions> std::size_t ImageData<dimensions>::dataSize(const VectorTypeFor< dimensions, Int >& size) const {
CORRADE_ASSERT(!_compressed, "Trade::ImageData::dataSize(): the image is compressed", {});
return Implementation::imageDataSize<dimensions>(_format, _type, size);
template<UnsignedInt dimensions> std::tuple<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", {});
return Implementation::imageDataProperties<dimensions>(*this);
}
template<UnsignedInt dimensions> ImageData<dimensions>::operator ImageView<dimensions>()

20
src/Magnum/Trade/ImageData.h

@ -41,7 +41,7 @@ namespace Magnum { namespace Trade {
Access to either uncompressed or compressed image data provided by
@ref AbstractImporter subclasses, the compression state is distinguished with
@ref isCompressed(). Uncompressed images have @ref format(), @ref type(),
@ref pixelSize() and @ref dataSize() properties and are convertible to
@ref pixelSize() and @ref dataProperties() properties and are convertible to
@ref ImageView. Compressed images have just the @ref compressedFormat()
property and are convertible to @ref CompressedImageView.
@ -67,7 +67,7 @@ template<UnsignedInt dimensions> class ImageData {
* Note that the image data are not copied on construction, but they
* are deleted on class destruction.
*/
explicit ImageData(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, void* data): _compressed{false}, _storage{storage}, _format{format}, _type{type}, _size{size}, _data{reinterpret_cast<char*>(data), dataSize(size)} {}
explicit ImageData(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, void* data): _compressed{false}, _storage{storage}, _format{format}, _type{type}, _size{size}, _data{reinterpret_cast<char*>(data), Implementation::imageDataSizeFor(*this, size)} {}
/** @overload
* Similar to the above, but uses default @ref PixelStorage parameters.
@ -202,7 +202,7 @@ template<UnsignedInt dimensions> class ImageData {
* @brief Pixel size (in bytes)
*
* The image is expected to be uncompressed.
* @see @ref isCompressed()
* @see @ref isCompressed(), @ref PixelStorage::pixelSize()
*/
std::size_t pixelSize() const;
@ -210,13 +210,17 @@ template<UnsignedInt dimensions> class ImageData {
VectorTypeFor<dimensions, Int> size() const { return _size; }
/**
* @brief Size of data required to store uncompressed image of given size
* @brief Uncompressed image data properties
*
* The image is expected to be uncompressed. Takes color format, type
* and row alignment of this image into account.
* @see @ref isCompressed(), @ref pixelSize()
* The image is expected to be uncompressed. See
* @ref PixelStorage::dataProperties() for more information.
* @see @ref isCompressed()
*/
std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const;
std::tuple<std::size_t, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const;
/* compressed data properties are not available because the importers
are not setting any block size pixel storage properties to avoid
needless state changes -- thus the calculation can't be done */
/** @brief Raw data */
Containers::ArrayView<char> data() { return _data; }

Loading…
Cancel
Save