Browse Source

Introduce ImageFlags to annotate cube map and array images.

With the intention that those will eventually contain also things like
YUp / YDown, PremultipliedAlpha and such.

This commit is mostly just busywork, wiring this into [Compressed]Image,
[Compressed]ImageView and Trade::ImageData and ensuring the flags get
correctly propagated during moves and conversions. Unfortunately in case
of Trade::ImageData it meant deprecating the current set of constructor
in order to insert an ImageFlags parameter before the importer state
pointer.

The only non-trivial piece of logic is when a 2D
[Compressed]ImageView gets converted to a 3D one, then the Array bit is
implicitly dropped, as 2D arrays of 1D images are not really a thing.
Instead, it's now possible to add new flags when doing the conversion --
for example to turn a 2D image to a (single-layer) 2D array image.
pull/578/head
Vladimír Vondruš 4 years ago
parent
commit
f14e15c4a9
  1. 8
      doc/changelog.dox
  2. 2
      src/Magnum/CMakeLists.txt
  3. 31
      src/Magnum/Image.cpp
  4. 101
      src/Magnum/Image.h
  5. 101
      src/Magnum/ImageFlags.cpp
  6. 183
      src/Magnum/ImageFlags.h
  7. 35
      src/Magnum/ImageView.cpp
  8. 206
      src/Magnum/ImageView.h
  9. 17
      src/Magnum/Implementation/ImageProperties.h
  10. 7
      src/Magnum/Magnum.h
  11. 1
      src/Magnum/Test/CMakeLists.txt
  12. 157
      src/Magnum/Test/ImageFlagsTest.cpp
  13. 110
      src/Magnum/Test/ImageTest.cpp
  14. 164
      src/Magnum/Test/ImageViewTest.cpp
  15. 46
      src/Magnum/Trade/ImageData.cpp
  16. 304
      src/Magnum/Trade/ImageData.h
  17. 6
      src/Magnum/Trade/Test/AbstractImporterTest.cpp
  18. 122
      src/Magnum/Trade/Test/ImageDataTest.cpp

8
doc/changelog.dox

@ -335,6 +335,9 @@ See also:
@ref CompressedImageView::size() as well as @ref Trade::ImageData::size()
now return a @cpp const& @ce instead of a value to allow creating a
@relativeref{Corrade,Containers::StridedArrayView} slice onto this member.
- @ref Image, @ref CompressedImage, @ref ImageView, @ref CompressedImageView
as well as @ref Trade::ImageData are now able to annotate array, cube map
and cube map array images using @ref ImageFlags
@subsubsection changelog-latest-changes-debugtools DebugTools library
@ -916,6 +919,11 @@ See also:
changed to have input first and output second, for consistency with other
interfaces, together with a switch to @ref Containers::StringView. The
original signature is marked as deprecated.
- Due to introduction of @ref ImageFlags, @ref Trade::ImageData constructors
that were taking @cpp const void* importerState @ce as the last parameter
are now deprecated in favor of constructors that take @ref ImageFlags *and*
`importerState`. Code that wasn't passing the `importerState` parameter
isn't affected by this change.
- @cpp Trade::TextureData::Type @ce was deprecated in favor of
@ref Trade::TextureType that is much less annoying to type, in addition
@cpp Trade::TextureData::Type::Cube @ce was deprecated in favor of

2
src/Magnum/CMakeLists.txt

@ -74,6 +74,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.cmake
# Files shared between main library and unit test library
set(Magnum_SRCS
FileCallback.cpp
ImageFlags.cpp
PixelStorage.cpp
Resource.cpp
Sampler.cpp
@ -95,6 +96,7 @@ set(Magnum_HEADERS
DimensionTraits.h
FileCallback.h
Image.h
ImageFlags.h
ImageView.h
Magnum.h
Mesh.h

31
src/Magnum/Image.cpp

@ -31,12 +31,15 @@
namespace Magnum {
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{storage, format, {}, pixelFormatSize(format), size, std::move(data)} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags) noexcept: Image{storage, format, {}, pixelFormatSize(format), size, std::move(data), flags} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, std::move(data)} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags) noexcept: Image{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, std::move(data), flags} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{std::move(data)} {
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _flags{flags}, _size{size}, _data{std::move(data)} {
CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Image: data too small, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this) << "bytes", );
#ifndef CORRADE_NO_ASSERT
Implementation::checkImageFlagsForSize("Image:", flags, size);
#endif
}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format) noexcept: Image{storage, format, {}, pixelFormatSize(format)} {}
@ -45,7 +48,7 @@ template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage sto
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _data{} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(Image<dimensions>&& other) noexcept: _storage{std::move(other._storage)}, _format{std::move(other._format)}, _formatExtra{std::move(other._formatExtra)}, _pixelSize{std::move(other._pixelSize)}, _size{std::move(other._size)}, _data{std::move(other._data)} {
template<UnsignedInt dimensions> Image<dimensions>::Image(Image<dimensions>&& other) noexcept: _storage{std::move(other._storage)}, _format{std::move(other._format)}, _formatExtra{std::move(other._formatExtra)}, _pixelSize{std::move(other._pixelSize)}, _flags{std::move(other._flags)}, _size{std::move(other._size)}, _data{std::move(other._data)} {
other._size = {};
}
@ -55,17 +58,18 @@ template<UnsignedInt dimensions> Image<dimensions>& Image<dimensions>::operator=
swap(_format, other._format);
swap(_formatExtra, other._formatExtra);
swap(_pixelSize, other._pixelSize);
swap(_flags, other._flags);
swap(_size, other._size);
swap(_data, other._data);
return *this;
}
template<UnsignedInt dimensions> Image<dimensions>::operator BasicMutableImageView<dimensions>() {
return BasicMutableImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
return BasicMutableImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data, _flags};
}
template<UnsignedInt dimensions> Image<dimensions>::operator BasicImageView<dimensions>() const {
return BasicImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
return BasicImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data, _flags};
}
template<UnsignedInt dimensions> std::pair<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>> Image<dimensions>::dataProperties() const {
@ -86,13 +90,17 @@ template<UnsignedInt dimensions> Containers::Array<char> Image<dimensions>::rele
return data;
}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: _storage{storage}, _format{format}, _size{size}, _data{std::move(data)} {}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags) noexcept: _storage{storage}, _format{format}, _flags{flags}, _size{size}, _data{std::move(data)} {
#ifndef CORRADE_NO_ASSERT
Implementation::checkImageFlagsForSize("CompressedImage:", flags, size);
#endif
}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: CompressedImage{storage, compressedPixelFormatWrap(format), size, std::move(data)} {}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags) noexcept: CompressedImage{storage, compressedPixelFormatWrap(format), size, std::move(data), flags} {}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage) noexcept: _storage{storage}, _format{} {}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(CompressedImage<dimensions>&& other) noexcept: _storage{std::move(other._storage)}, _format{std::move(other._format)}, _size{std::move(other._size)}, _data{std::move(other._data)}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(CompressedImage<dimensions>&& other) noexcept: _storage{std::move(other._storage)}, _format{std::move(other._format)}, _flags{other._flags}, _size{std::move(other._size)}, _data{std::move(other._data)}
{
other._size = {};
}
@ -101,17 +109,18 @@ template<UnsignedInt dimensions> CompressedImage<dimensions>& CompressedImage<di
using std::swap;
swap(_storage, other._storage);
swap(_format, other._format);
swap(_flags, other._flags);
swap(_size, other._size);
swap(_data, other._data);
return *this;
}
template<UnsignedInt dimensions> CompressedImage<dimensions>::operator BasicMutableCompressedImageView<dimensions>() {
return BasicMutableCompressedImageView<dimensions>{_storage, _format, _size, _data};
return BasicMutableCompressedImageView<dimensions>{_storage, _format, _size, _data, _flags};
}
template<UnsignedInt dimensions> CompressedImage<dimensions>::operator BasicCompressedImageView<dimensions>() const {
return BasicCompressedImageView<dimensions>{_storage, _format, _size, _data};
return BasicCompressedImageView<dimensions>{_storage, _format, _size, _data, _flags};
}
template<UnsignedInt dimensions> std::pair<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>> CompressedImage<dimensions>::dataProperties() const {

101
src/Magnum/Image.h

@ -32,6 +32,7 @@
#include <Corrade/Containers/Array.h>
#include "Magnum/DimensionTraits.h"
#include "Magnum/ImageFlags.h"
#include "Magnum/PixelStorage.h"
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -126,30 +127,35 @@ template<UnsignedInt dimensions> class Image {
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* The @p data array is expected to be of proper size for given
* parameters.
* parameters. For a 3D image, if @p flags contain
* @ref ImageFlag3D::CubeMap, the @p size is expected to match its
* restrictions.
*/
explicit Image(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
explicit Image(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Constructor
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref Image(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* Equivalent to calling @ref Image(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
explicit Image(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{{}, format, size, std::move(data)} {}
explicit Image(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept: Image{{}, format, size, std::move(data), flags} {}
/**
* @brief Construct an image placeholder
* @param storage Storage of pixel data
* @param format Format of pixel data
*
* Size is set to zero and data pointer to @cpp nullptr @ce. Move over
* a non-empty instance to make it useful.
* Size is set to zero, data pointer to @cpp nullptr @ce and data
* layout flags are empty. Move over a non-empty instance to make it
* useful.
*/
/*implicit*/ Image(PixelStorage storage, PixelFormat format) noexcept;
@ -170,8 +176,9 @@ template<UnsignedInt dimensions> class Image {
* @param pixelSize Size of a pixel in given format, in bytes
* @param size Image size, in pixels
* @param data Image data
* @param flags Image layout flags
*
* Unlike with @ref Image(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&),
* Unlike with @ref Image(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>),
* where pixel size is calculated automatically using
* @ref pixelFormatSize(), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
@ -179,16 +186,18 @@ template<UnsignedInt dimensions> class Image {
* @ref PixelFormat.
*
* The @p data array is expected to be of proper size for given
* parameters.
* parameters. For a 3D image, if @p flags contain
* @ref ImageFlag3D::CubeMap, the @p size is expected to match its
* restrictions.
*/
explicit Image(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
explicit Image(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept;
/** @overload
*
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/
explicit Image(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
explicit Image(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an image placeholder with implementation-specific pixel format
@ -219,12 +228,13 @@ template<UnsignedInt dimensions> class Image {
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Uses ADL to find a corresponding @cpp pixelFormatSize(T, U) @ce
* overload, then calls @ref Image(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* overload, then calls @ref Image(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>)
* with calculated pixel size.
*/
template<class T, class U> explicit Image(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
template<class T, class U> explicit Image(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an image with implementation-specific pixel format
@ -232,12 +242,13 @@ template<UnsignedInt dimensions> class Image {
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Uses ADL to find a corresponding @cpp pixelFormatSize(T) @ce
* overload, then calls @ref Image(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* overload, then calls @ref Image(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*/
template<class T> explicit Image(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
template<class T> explicit Image(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an image with implementation-specific pixel format
@ -245,22 +256,24 @@ template<UnsignedInt dimensions> class Image {
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref Image(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* Equivalent to calling @ref Image(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
template<class T, class U> explicit Image(T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{{}, format, formatExtra, size, std::move(data)} {}
template<class T, class U> explicit Image(T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept: Image{{}, format, formatExtra, size, std::move(data), flags} {}
/**
* @brief Construct an image with implementation-specific pixel format
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref Image(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* Equivalent to calling @ref Image(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
template<class T> explicit Image(T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{{}, format, size, std::move(data)} {}
template<class T> explicit Image(T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept: Image{{}, format, size, std::move(data), flags} {}
/**
* @brief Construct an image placeholder with implementation-specific pixel format
@ -332,6 +345,12 @@ template<UnsignedInt dimensions> class Image {
another function in an oneliner (e.g. saving screenshot) */
/*implicit*/ operator BasicMutableImageView<dimensions>();
/**
* @brief Layout flags
* @m_since_latest
*/
ImageFlags<dimensions> flags() const { return _flags; }
/** @brief Storage of pixel data */
PixelStorage storage() const { return _storage; }
@ -469,7 +488,11 @@ template<UnsignedInt dimensions> class Image {
PixelStorage _storage;
PixelFormat _format;
UnsignedInt _formatExtra;
/** @todo this could be a short, saving 8 bytes for 1D and 3D images on
64bit and 4 bytes for all dimensions on 32bit. Worth the pain? */
UnsignedInt _pixelSize;
/* 2-byte gap */
ImageFlags<dimensions> _flags;
VectorTypeFor<dimensions, Int> _size;
Containers::Array<char> _data;
};
@ -528,19 +551,24 @@ template<UnsignedInt dimensions> class CompressedImage {
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* For a 3D image, if @p flags contain @ref ImageFlag3D::CubeMap, the
* @p size is expected to match its restrictions.
*/
explicit CompressedImage(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
explicit CompressedImage(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Constructor
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref CompressedImage(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* Equivalent to calling @ref CompressedImage(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>)
* with default-constructed @ref CompressedPixelStorage.
*/
explicit CompressedImage(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: CompressedImage{{}, format, size, std::move(data)} {}
explicit CompressedImage(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept: CompressedImage{{}, format, size, std::move(data), flags} {}
/**
* @brief Construct a compressed image with implementation-specific format
@ -548,29 +576,35 @@ template<UnsignedInt dimensions> class CompressedImage {
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat.
*
* For a 3D image, if @p flags contain @ref ImageFlag3D::CubeMap, the
* @p size is expected to match its restrictions.
*/
template<class T> explicit CompressedImage(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
template<class T> explicit CompressedImage(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct a compressed image with implementation-specific format
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref CompressedImage(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* Equivalent to calling @ref CompressedImage(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>)
* with default-constructed @ref CompressedPixelStorage.
*/
template<class T> explicit CompressedImage(T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: CompressedImage{{}, format, size, std::move(data)} {}
template<class T> explicit CompressedImage(T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}) noexcept: CompressedImage{{}, format, size, std::move(data), flags} {}
/**
* @brief Construct an image placeholder
* @param storage Storage of compressed pixel data
*
* Format is undefined, size is zero and data is @cpp nullptr @ce. Move
* over a non-empty instance to make it useful.
* Format is undefined, size is zero, data is @cpp nullptr @ce and
* data layout flags are empty. Move over a non-empty instance to make
* it useful.
*/
/*implicit*/ CompressedImage(CompressedPixelStorage storage) noexcept;
@ -605,6 +639,12 @@ template<UnsignedInt dimensions> class CompressedImage {
another function in an oneliner (e.g. saving screenshot) */
/*implicit*/ operator BasicMutableCompressedImageView<dimensions>();
/**
* @brief Layout flags
* @m_since_latest
*/
ImageFlags<dimensions> flags() const { return _flags; }
/** @brief Storage of compressed pixel data */
CompressedPixelStorage storage() const { return _storage; }
@ -691,10 +731,11 @@ template<UnsignedInt dimensions> class CompressedImage {
private:
/* To be made public once block size and block data size are stored
together with the image */
explicit CompressedImage(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
explicit CompressedImage(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags) noexcept;
CompressedPixelStorage _storage;
CompressedPixelFormat _format;
ImageFlags<dimensions> _flags;
VectorTypeFor<dimensions, Int> _size;
Containers::Array<char> _data;
};
@ -708,12 +749,12 @@ typedef CompressedImage<2> CompressedImage2D;
/** @brief Three-dimensional compressed image */
typedef CompressedImage<3> CompressedImage3D;
template<UnsignedInt dimensions> template<class T, class U> inline Image<dimensions>::Image(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelFormatSizeAdl(format, formatExtra), size, std::move(data)} {
template<UnsignedInt dimensions> template<class T, class U> inline Image<dimensions>::Image(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags) noexcept: Image{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelFormatSizeAdl(format, formatExtra), size, std::move(data), flags} {
static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> inline Image<dimensions>::Image(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{storage, UnsignedInt(format), {}, Implementation::pixelFormatSizeAdl(format), size, std::move(data)} {
template<UnsignedInt dimensions> template<class T> inline Image<dimensions>::Image(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags) noexcept: Image{storage, UnsignedInt(format), {}, Implementation::pixelFormatSizeAdl(format), size, std::move(data), flags} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
@ -728,7 +769,7 @@ template<UnsignedInt dimensions> template<class T> inline Image<dimensions>::Ima
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> inline CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: CompressedImage{storage, UnsignedInt(format), size, std::move(data)} {
template<UnsignedInt dimensions> template<class T> inline CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags) noexcept: CompressedImage{storage, UnsignedInt(format), size, std::move(data), flags} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}

101
src/Magnum/ImageFlags.cpp

@ -0,0 +1,101 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "ImageFlags.h"
#include <Corrade/Containers/EnumSet.hpp>
namespace Magnum {
Debug& operator<<(Debug& debug, const ImageFlag1D value) {
const bool packed = debug.immediateFlags() >= Debug::Flag::Packed;
if(!packed)
debug << "ImageFlag1D" << Debug::nospace;
switch(value) {
/* LCOV_EXCL_START */
#define _c(value) case ImageFlag1D::value: return debug << (packed ? "" : "::") << Debug::nospace << #value;
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << (packed ? "" : "(") << Debug::nospace << reinterpret_cast<void*>(UnsignedShort(value)) << Debug::nospace << (packed ? "" : ")");
}
Debug& operator<<(Debug& debug, const ImageFlag2D value) {
const bool packed = debug.immediateFlags() >= Debug::Flag::Packed;
if(!packed)
debug << "ImageFlag2D" << Debug::nospace;
switch(value) {
/* LCOV_EXCL_START */
#define _c(value) case ImageFlag2D::value: return debug << (packed ? "" : "::") << Debug::nospace << #value;
_c(Array)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << (packed ? "" : "(") << Debug::nospace << reinterpret_cast<void*>(UnsignedShort(value)) << Debug::nospace << (packed ? "" : ")");
}
Debug& operator<<(Debug& debug, const ImageFlag3D value) {
const bool packed = debug.immediateFlags() >= Debug::Flag::Packed;
if(!packed)
debug << "ImageFlag3D" << Debug::nospace;
switch(value) {
/* LCOV_EXCL_START */
#define _c(value) case ImageFlag3D::value: return debug << (packed ? "" : "::") << Debug::nospace << #value;
_c(Array)
_c(CubeMap)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << (packed ? "" : "(") << Debug::nospace << reinterpret_cast<void*>(UnsignedShort(value)) << Debug::nospace << (packed ? "" : ")");
}
Debug& operator<<(Debug& debug, const ImageFlags1D value) {
return Containers::enumSetDebugOutput(debug, value, debug.immediateFlags() >= Debug::Flag::Packed ? "{}" : "ImageFlags1D{}", {
});
}
Debug& operator<<(Debug& debug, const ImageFlags2D value) {
return Containers::enumSetDebugOutput(debug, value, debug.immediateFlags() >= Debug::Flag::Packed ? "{}" : "ImageFlags2D{}", {
ImageFlag2D::Array
});
}
Debug& operator<<(Debug& debug, const ImageFlags3D value) {
return Containers::enumSetDebugOutput(debug, value, debug.immediateFlags() >= Debug::Flag::Packed ? "{}" : "ImageFlags3D{}", {
ImageFlag3D::Array,
ImageFlag3D::CubeMap
});
}
}

183
src/Magnum/ImageFlags.h

@ -0,0 +1,183 @@
#ifndef Magnum_ImageFlags_h
#define Magnum_ImageFlags_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Enum @ref Magnum::ImageFlag1D, @ref Magnum::ImageFlag2D, @ref Magnum::ImageFlag3D, enum set @ref Magnum::ImageFlags1D, @ref Magnum::ImageFlags2D, @ref Magnum::ImageFlags3D, alias @ref Magnum::ImageFlag, @ref Magnum::ImageFlags
* @m_since_latest
*/
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/Magnum.h"
#include "Magnum/visibility.h"
namespace Magnum {
/**
@brief 1D image layout flag
@m_since_latest
Used by @ref Image1D, @ref ImageView1D and @ref Trade::ImageData1D. Currently
no flags specific to 1D images are defined.
@see @ref ImageFlags1D
*/
enum class ImageFlag1D: UnsignedShort {};
/**
@brief 2D image layout flag
@m_since_latest
Used by @ref Image2D, @ref ImageView2D and @ref Trade::ImageData2D.
@see @ref ImageFlags2D
*/
enum class ImageFlag2D: UnsignedShort {
/**
* The image is a 1D array instead of 2D. I.e., no filtering is done along
* the Y axis and mip levels don't shorten along the Y axis.
*
* Guaranteed to have the same value as @ref ImageFlag3D::Array.
*/
Array = 1 << 0,
};
/**
@brief 3D image layout flag
@m_since_latest
Used by @ref Image3D, @ref ImageView3D and @ref Trade::ImageData3D.
@see @ref ImageFlags3D
*/
enum class ImageFlag3D: UnsignedShort {
/**
* The image is a 2D array instead of 3D. I.e., no filtering is done along
* the Z axis and mip levels don't shorten along the Z axis.
*
* Guaranteed to have the same value as @ref ImageFlag2D::Array.
*/
Array = 1 << 0,
/**
* The image is a cube map instead of 3D. I.e., there's exactly six square
* 2D faces in order (+X, -X, +Y, -Y, +Z, -Z), filtering is done on face
* edges, and mip levels don't shorten along the Z axis. If combined with
* @ref ImageFlag3D::Array, the image is a cube map array, consisting of an
* exact multiple of six square 2D faces, with each six layers being one
* cube map.
*/
CubeMap = 1 << 1
};
/** @debugoperatorenum{ImageFlag1D} */
MAGNUM_EXPORT Debug& operator<<(Debug& debug, ImageFlag1D value);
/** @debugoperatorenum{ImageFlag2D} */
MAGNUM_EXPORT Debug& operator<<(Debug& debug, ImageFlag2D value);
/** @debugoperatorenum{ImageFlag3D} */
MAGNUM_EXPORT Debug& operator<<(Debug& debug, ImageFlag3D value);
/**
@brief 1D image layout flags
@m_since_latest
Used by @ref Image1D, @ref ImageView1D, @ref Trade::ImageData1D and
@ref GL::BufferImage1D.
*/
typedef Containers::EnumSet<ImageFlag1D> ImageFlags1D;
/**
@brief 2D image layout flags
@m_since_latest
Used by @ref Image2D, @ref ImageView2D, @ref Trade::ImageData2D and
@ref GL::BufferImage2D.
*/
typedef Containers::EnumSet<ImageFlag2D> ImageFlags2D;
/**
@brief 3D image layout flags
@m_since_latest
Used by @ref Image3D, @ref ImageView3D, @ref Trade::ImageData3D and
@ref GL::BufferImage3D.
*/
typedef Containers::EnumSet<ImageFlag3D> ImageFlags3D;
CORRADE_ENUMSET_OPERATORS(ImageFlags1D)
CORRADE_ENUMSET_OPERATORS(ImageFlags2D)
CORRADE_ENUMSET_OPERATORS(ImageFlags3D)
/** @debugoperatorenum{ImageFlags1D} */
MAGNUM_EXPORT Debug& operator<<(Debug& debug, ImageFlags1D value);
/** @debugoperatorenum{ImageFlags2D} */
MAGNUM_EXPORT Debug& operator<<(Debug& debug, ImageFlags2D value);
/** @debugoperatorenum{ImageFlags3D} */
MAGNUM_EXPORT Debug& operator<<(Debug& debug, ImageFlags3D value);
namespace Implementation {
template<UnsignedInt> struct ImageFlagTraits;
template<> struct ImageFlagTraits<1> {
typedef ImageFlag1D Type;
typedef ImageFlags1D SetType;
};
template<> struct ImageFlagTraits<2> {
typedef ImageFlag2D Type;
typedef ImageFlags2D SetType;
};
template<> struct ImageFlagTraits<3> {
typedef ImageFlag3D Type;
typedef ImageFlags3D SetType;
};
}
/**
@brief Image layout flag
@m_since_latest
Expands to @ref ImageFlag1D, @ref ImageFlag2D or @ref ImageFlag3D based on
dimension count.
@see @ref ImageFlags
*/
template<UnsignedInt dimensions> using ImageFlag = typename Implementation::ImageFlagTraits<dimensions>::Type;
/**
@brief Image layout flags
@m_since_latest
Expands to @ref ImageFlags1D, @ref ImageFlags2D or @ref ImageFlags3D based on
dimension count.
@see @ref ImageFlag
*/
template<UnsignedInt dimensions> using ImageFlags = typename Implementation::ImageFlagTraits<dimensions>::SetType;
}
#endif

35
src/Magnum/ImageView.cpp

@ -30,11 +30,11 @@
namespace Magnum {
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: ImageView{storage, format, {}, pixelFormatSize(format), size, data} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: ImageView{storage, format, {}, pixelFormatSize(format), size, data, flags} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, data} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, data, flags} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{reinterpret_cast<Type*>(data.data()), data.size()} {
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _flags{flags}, _size{size}, _data{reinterpret_cast<Type*>(data.data()), data.size()} {
#ifdef MAGNUM_BUILD_DEPRECATED
#ifndef CORRADE_NO_ASSERT
if(size.product() && !_data && !_data.size())
@ -44,13 +44,20 @@ template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(co
#else
CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "ImageView: data too small, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this) << "bytes", );
#endif
#ifndef CORRADE_NO_ASSERT
Implementation::checkImageFlagsForSize("ImageView:", flags, size);
#endif
}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, format, {}, pixelFormatSize(format), size} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const ImageFlags<dimensions> flags) noexcept: ImageView{storage, format, {}, pixelFormatSize(format), size, flags} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const ImageFlags<dimensions> flags) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, flags} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{nullptr} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const ImageFlags<dimensions> flags) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _flags{flags}, _size{size}, _data{nullptr} {
#ifndef CORRADE_NO_ASSERT
Implementation::checkImageFlagsForSize("ImageView:", flags, size);
#endif
}
template<UnsignedInt dimensions, class T> std::pair<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>> ImageView<dimensions, T>::dataProperties() const {
return Implementation::imageDataProperties<dimensions>(*this);
@ -66,13 +73,21 @@ template<UnsignedInt dimensions, class T> auto ImageView<dimensions, T>::pixels(
return Implementation::imagePixelView<dimensions, Type>(*this, data());
}
template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: _storage{storage}, _format{format}, _size{size}, _data{reinterpret_cast<Type*>(data.data()), data.size()} {}
template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: _storage{storage}, _format{format}, _flags{flags}, _size{size}, _data{reinterpret_cast<Type*>(data.data()), data.size()} {
#ifndef CORRADE_NO_ASSERT
Implementation::checkImageFlagsForSize("CompressedImageView:", flags, size);
#endif
}
template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: _storage{storage}, _format{format}, _size{size} {}
template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const ImageFlags<dimensions> flags) noexcept: _storage{storage}, _format{format}, _flags{flags}, _size{size} {
#ifndef CORRADE_NO_ASSERT
Implementation::checkImageFlagsForSize("CompressedImageView:", flags, size);
#endif
}
template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: CompressedImageView{storage, compressedPixelFormatWrap(format), size, data} {}
template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: CompressedImageView{storage, compressedPixelFormatWrap(format), size, data, flags} {}
template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{storage, compressedPixelFormatWrap(format), size} {}
template<UnsignedInt dimensions, class T> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, const ImageFlags<dimensions> flags) noexcept: CompressedImageView{storage, compressedPixelFormatWrap(format), size, flags} {}
template<UnsignedInt dimensions, class T> std::pair<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>> CompressedImageView<dimensions, T>::dataProperties() const {
return Implementation::compressedImageDataProperties<dimensions>(*this);

206
src/Magnum/ImageView.h

@ -32,6 +32,7 @@
#include <Corrade/Containers/ArrayView.h>
#include "Magnum/DimensionTraits.h"
#include "Magnum/ImageFlags.h"
#include "Magnum/PixelStorage.h"
#include "Magnum/Math/Vector3.h"
@ -171,43 +172,51 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* The @p data array is expected to be of proper size for given
* parameters.
* parameters. For a 3D image, if @p flags contain
* @ref ImageFlag3D::CubeMap, the @p size is expected to match its
* restrictions.
*/
explicit ImageView(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
explicit ImageView(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Constructor
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* Equivalent to calling @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
explicit ImageView(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: ImageView{{}, format, size, data} {}
explicit ImageView(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept: ImageView{{}, format, size, data, flags} {}
/**
* @brief Construct an empty view
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
* @param flags Image layout flags
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
* assign a memory view to the image. For a 3D image, if @p flags
* contain @ref ImageFlag3D::CubeMap, the @p size is expected to match
* its restrictions.
*/
explicit ImageView(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept;
explicit ImageView(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an empty view
* @param format Format of pixel data
* @param size Image size
* @param flags Image layout flags
*
* Equivalent to calling @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&)
* Equivalent to calling @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
explicit ImageView(PixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, size} {}
explicit ImageView(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept: ImageView{{}, format, size, flags} {}
/**
* @brief Construct an image view with implementation-specific pixel format
@ -217,8 +226,9 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @param pixelSize Size of a pixel in given format, in bytes
* @param size Image size, in pixels
* @param data Image data
* @param flags Image layout flags
*
* Unlike with @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>),
* Unlike with @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>),
* where pixel size is calculated automatically using
* @ref pixelFormatSize(), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
@ -226,16 +236,18 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @ref PixelFormat.
*
* The @p data array is expected to be of proper size for given
* parameters.
* parameters. For a 3D image, if @p flags contain
* @ref ImageFlag3D::CubeMap, the @p size is expected to match its
* restrictions.
*/
explicit ImageView(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
explicit ImageView(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept;
/** @overload
*
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/
explicit ImageView(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
explicit ImageView(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an empty view with implementation-specific pixel format
@ -244,8 +256,9 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @param formatExtra Additional pixel format specifier
* @param pixelSize Size of a pixel in given format, in bytes
* @param size Image size, in pixels
* @param flags Image layout flags
*
* Unlike with @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&),
* Unlike with @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, ImageFlags<dimensions>),
* where pixel size is calculated automatically using
* @ref pixelFormatSize(), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
@ -253,16 +266,18 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @ref PixelFormat.
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
* assign a memory view to the image. For a 3D image, if @p flags
* contain @ref ImageFlag3D::CubeMap, the @p size is expected to match
* its restrictions.
*/
explicit ImageView(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size) noexcept;
explicit ImageView(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept;
/** @overload
*
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/
explicit ImageView(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size) noexcept;
explicit ImageView(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an image view with implementation-specific pixel format
@ -271,12 +286,13 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Uses ADL to find a corresponding @cpp pixelFormatSize(T, U) @ce
* overload, then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* overload, then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>)
* with calculated pixel size.
*/
template<class U, class V> explicit ImageView(PixelStorage storage, U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
template<class U, class V> explicit ImageView(PixelStorage storage, U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an image view with implementation-specific pixel format
@ -284,12 +300,13 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Uses ADL to find a corresponding @cpp pixelFormatSize(T) @ce
* overload, then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* overload, then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*/
template<class U> explicit ImageView(PixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
template<class U> explicit ImageView(PixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an image view with implementation-specific pixel format
@ -297,22 +314,24 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref ImageView(PixelStorage, U, V, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* Equivalent to calling @ref ImageView(PixelStorage, U, V, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
template<class U, class V> explicit ImageView(U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: ImageView{{}, format, formatExtra, size, data} {}
template<class U, class V> explicit ImageView(U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept: ImageView{{}, format, formatExtra, size, data, flags} {}
/**
* @brief Construct an image view with implementation-specific pixel format
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref ImageView(PixelStorage, U, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* Equivalent to calling @ref ImageView(PixelStorage, U, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
template<class U> explicit ImageView(U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: ImageView{{}, format, size, data} {}
template<class U> explicit ImageView(U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept: ImageView{{}, format, size, data, flags} {}
/**
* @brief Construct an empty view with implementation-specific pixel format
@ -320,57 +339,67 @@ template<UnsignedInt dimensions, class T> class ImageView {
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param flags Image layout flags
*
* Uses ADL to find a corresponding @cpp pixelFormatSize(T, U) @ce
* overload, then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&)
* overload, then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, ImageFlags<dimensions>)
* with calculated pixel size.
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
*/
template<class U, class V> explicit ImageView(PixelStorage storage, U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size) noexcept;
template<class U, class V> explicit ImageView(PixelStorage storage, U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an empty view with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
* @param flags Image layout flags
*
* Uses ADL to find a corresponding @cpp pixelFormatSize(T) @ce
* overload, then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&)
* overload, then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, ImageFlags<dimensions>)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
*/
template<class U> explicit ImageView(PixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size) noexcept;
template<class U> explicit ImageView(PixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an empty view with implementation-specific pixel format
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param flags Image layout flags
*
* Equivalent to calling @ref ImageView(PixelStorage, U, V, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* Equivalent to calling @ref ImageView(PixelStorage, U, V, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
template<class U, class V> explicit ImageView(U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, formatExtra, size} {}
template<class U, class V> explicit ImageView(U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept: ImageView{{}, format, formatExtra, size, flags} {}
/**
* @brief Construct an empty view with implementation-specific pixel format
* @param format Format of pixel data
* @param size Image size
* @param flags Image layout flags
*
* Equivalent to calling @ref ImageView(PixelStorage, U, const VectorTypeFor<dimensions, Int>&)
* Equivalent to calling @ref ImageView(PixelStorage, U, const VectorTypeFor<dimensions, Int>&, ImageFlags<dimensions>)
* with default-constructed @ref PixelStorage.
*/
template<class U> explicit ImageView(U format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, size} {}
template<class U> explicit ImageView(U format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept: ImageView{{}, format, size, flags} {}
/**
* @brief Construct from a view of lower dimension count
* @m_since{2019,10}
*
* Size in the new dimension(s) is set to @cpp 1 @ce. Original image
* flags are preserved, except for @ref ImageFlag2D::Array when
* constructing a 3D image from a 2D image (i.e., a 1D array image), as
* there's no concept of 2D arrays of 1D images. Use the @p flags
* parameter to add arbitrary other flags.
*/
template<UnsignedInt otherDimensions, class = typename std::enable_if<(otherDimensions < dimensions)>::type> /*implicit*/ ImageView(const ImageView<otherDimensions, T>& other) noexcept;
template<UnsignedInt otherDimensions, class = typename std::enable_if<(otherDimensions < dimensions)>::type> /*implicit*/ ImageView(const ImageView<otherDimensions, T>& other, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Convert a mutable view to a const one
@ -378,6 +407,12 @@ template<UnsignedInt dimensions, class T> class ImageView {
*/
template<class U, class = typename std::enable_if<std::is_const<T>::value && !std::is_const<U>::value>::type> /*implicit*/ ImageView(const ImageView<dimensions, U>& other) noexcept;
/**
* @brief Layout flags
* @m_since_latest
*/
ImageFlags<dimensions> flags() const { return _flags; }
/** @brief Storage of pixel data */
PixelStorage storage() const { return _storage; }
@ -484,6 +519,7 @@ template<UnsignedInt dimensions, class T> class ImageView {
PixelFormat _format;
UnsignedInt _formatExtra;
UnsignedInt _pixelSize;
ImageFlags<dimensions> _flags;
VectorTypeFor<dimensions, Int> _size;
Containers::ArrayView<Type> _data;
};
@ -668,40 +704,49 @@ template<UnsignedInt dimensions, class T> class CompressedImageView {
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* For a 3D image, if @p flags contain @ref ImageFlag3D::CubeMap, the
* @p size is expected to match its restrictions.
*/
explicit CompressedImageView(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
explicit CompressedImageView(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Constructor
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>)
* with default-constructed @ref CompressedPixelStorage.
*/
explicit CompressedImageView(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: CompressedImageView{{}, format, size, data} {}
explicit CompressedImageView(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept: CompressedImageView{{}, format, size, data, flags} {}
/**
* @brief Construct an empty view
* @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
* @param flags Image layout flags
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
* assign a memory view to the image. For a 3D image, if @p flags
* contain @ref ImageFlag3D::CubeMap, the @p size is expected to match
* its restrictions.
*/
explicit CompressedImageView(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept;
explicit CompressedImageView(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an empty view
* @param format Format of compressed pixel data
* @param size Image size
* @param flags Image layout flags
*
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&)
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, ImageFlags<dimensions>)
* with default-constructed @ref CompressedPixelStorage.
*/
explicit CompressedImageView(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{{}, format, size} {}
explicit CompressedImageView(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept: CompressedImageView{{}, format, size, flags} {}
/**
* @brief Construct an image view with implementation-specific format
@ -709,51 +754,67 @@ template<UnsignedInt dimensions, class T> class CompressedImageView {
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat.
*
* For a 3D image, if @p flags contain @ref ImageFlag3D::CubeMap, the
* @p size is expected to match its restrictions.
*/
template<class U> explicit CompressedImageView(CompressedPixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
template<class U> explicit CompressedImageView(CompressedPixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an image view with implementation-specific format
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
*
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>, ImageFlags<dimensions>)
* with default-constructed @ref CompressedPixelStorage.
*/
template<class U> explicit CompressedImageView(U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: CompressedImageView{{}, format, size, data} {}
template<class U> explicit CompressedImageView(U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags = {}) noexcept: CompressedImageView{{}, format, size, data, flags} {}
/**
* @brief Construct an empty view with implementation-specific format
* @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
* @param flags Image layout flags
*
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat. Data pointer is set to
* @cpp nullptr @ce, call @ref setData() to assign a memory view to the
* image.
* @p format to @ref CompressedPixelFormat.
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image. For a 3D image, if @p flags
* contain @ref ImageFlag3D::CubeMap, the @p size is expected to match
* its restrictions.
*/
template<class U> explicit CompressedImageView(CompressedPixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size) noexcept;
template<class U> explicit CompressedImageView(CompressedPixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Construct an empty view with implementation-specific format
* @param format Format of compressed pixel data
* @param size Image size
* @param flags Image layout flags
*
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&)
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, ImageFlags<dimensions>)
* with default-constructed @ref CompressedPixelStorage.
*/
template<class U> explicit CompressedImageView(U format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{{}, format, size} {}
template<class U> explicit CompressedImageView(U format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags = {}) noexcept: CompressedImageView{{}, format, size, flags} {}
/**
* @brief Construct from a view of lower dimension count
* @m_since{2019,10}
*
* Size in the new dimension(s) is set to @cpp 1 @ce. Original image
* flags are preserved, except for @ref ImageFlag2D::Array when
* constructing a 3D image from a 2D image (i.e., a 1D array image), as
* there's no concept of 2D arrays of 1D images. Use the @p flags
* parameter to add arbitrary other flags.
*/
template<UnsignedInt otherDimensions, class = typename std::enable_if<(otherDimensions < dimensions)>::type> /*implicit*/ CompressedImageView(const CompressedImageView<otherDimensions, T>& other) noexcept;
template<UnsignedInt otherDimensions, class = typename std::enable_if<(otherDimensions < dimensions)>::type> /*implicit*/ CompressedImageView(const CompressedImageView<otherDimensions, T>& other, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Convert a mutable view to a const one
@ -761,6 +822,12 @@ template<UnsignedInt dimensions, class T> class CompressedImageView {
*/
template<class U, class = typename std::enable_if<std::is_const<T>::value && !std::is_const<U>::value>::type> /*implicit*/ CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept;
/**
* @brief Layout flags
* @m_since_latest
*/
ImageFlags<dimensions> flags() const { return _flags; }
/** @brief Storage of compressed pixel data */
CompressedPixelStorage storage() const { return _storage; }
@ -817,11 +884,12 @@ template<UnsignedInt dimensions, class T> class CompressedImageView {
/* To be made public once block size and block data size are stored
together with the image */
explicit CompressedImageView(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
explicit CompressedImageView(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size) noexcept;
explicit CompressedImageView(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data, ImageFlags<dimensions> flags) noexcept;
explicit CompressedImageView(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, ImageFlags<dimensions> flags) noexcept;
CompressedPixelStorage _storage;
CompressedPixelFormat _format;
ImageFlags<dimensions> _flags;
VectorTypeFor<dimensions, Int> _size;
Containers::ArrayView<Type> _data;
};
@ -899,47 +967,61 @@ typedef BasicMutableCompressedImageView<2> MutableCompressedImageView2D;
*/
typedef BasicMutableCompressedImageView<3> MutableCompressedImageView3D;
template<UnsignedInt dimensions, class T> template<class U, class V> inline ImageView<dimensions, T>::ImageView(const PixelStorage storage, const U format, const V formatExtra, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: ImageView{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelFormatSizeAdl(format, formatExtra), size, data} {
template<UnsignedInt dimensions, class T> template<class U, class V> inline ImageView<dimensions, T>::ImageView(const PixelStorage storage, const U format, const V formatExtra, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: ImageView{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelFormatSizeAdl(format, formatExtra), size, data, flags} {
static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions, class T> template<class U> inline ImageView<dimensions, T>::ImageView(const PixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: ImageView{storage, UnsignedInt(format), {}, Implementation::pixelFormatSizeAdl(format), size, data} {
template<UnsignedInt dimensions, class T> template<class U> inline ImageView<dimensions, T>::ImageView(const PixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: ImageView{storage, UnsignedInt(format), {}, Implementation::pixelFormatSizeAdl(format), size, data, flags} {
static_assert(sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions, class T> template<class U, class V> inline ImageView<dimensions, T>::ImageView(const PixelStorage storage, const U format, const V formatExtra, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelFormatSizeAdl(format, formatExtra), size} {
template<UnsignedInt dimensions, class T> template<class U, class V> inline ImageView<dimensions, T>::ImageView(const PixelStorage storage, const U format, const V formatExtra, const VectorTypeFor<dimensions, Int>& size, const ImageFlags<dimensions> flags) noexcept: ImageView{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelFormatSizeAdl(format, formatExtra), size, flags} {
static_assert(sizeof(U) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions, class T> template<class U> inline ImageView<dimensions, T>::ImageView(const PixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, UnsignedInt(format), {}, Implementation::pixelFormatSizeAdl(format), size} {
template<UnsignedInt dimensions, class T> template<class U> inline ImageView<dimensions, T>::ImageView(const PixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size, const ImageFlags<dimensions> flags) noexcept: ImageView{storage, UnsignedInt(format), {}, Implementation::pixelFormatSizeAdl(format), size, flags} {
static_assert(sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
#ifndef DOXYGEN_GENERATING_OUTPUT /* it complains otherwise. why? don't know, don't want to know */
template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, class> ImageView<dimensions, T>::ImageView(const ImageView<otherDimensions, T>& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _size{Math::Vector<dimensions, Int>::pad(other._size, 1)}, _data{other._data} {}
template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, class> ImageView<dimensions, T>::ImageView(const ImageView<otherDimensions, T>& other, const ImageFlags<dimensions> flags) noexcept:
_storage{other._storage},
_format{other._format},
_formatExtra{other._formatExtra},
_pixelSize{other._pixelSize},
/* Removing the Array bit and transferring the rest, as documented */
_flags{ImageFlag<dimensions>(UnsignedShort(other._flags)&~UnsignedShort(ImageFlag2D::Array))|flags},
_size{Math::Vector<dimensions, Int>::pad(other._size, 1)},
_data{other._data} {}
#endif
template<UnsignedInt dimensions, class T> template<class U, class> ImageView<dimensions, T>::ImageView(const ImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _size{other._size}, _data{other._data} {}
template<UnsignedInt dimensions, class T> template<class U, class> ImageView<dimensions, T>::ImageView(const ImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _flags{other._flags}, _size{other._size}, _data{other._data} {}
template<UnsignedInt dimensions, class T> template<class U> inline CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: CompressedImageView{storage, UnsignedInt(format), size, data} {
template<UnsignedInt dimensions, class T> template<class U> inline CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: CompressedImageView{storage, UnsignedInt(format), size, data, flags} {
static_assert(sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions, class T> template<class U> inline CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{storage, UnsignedInt(format), size} {
template<UnsignedInt dimensions, class T> template<class U> inline CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size, const ImageFlags<dimensions> flags) noexcept: CompressedImageView{storage, UnsignedInt(format), size, flags} {
static_assert(sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
#ifndef DOXYGEN_GENERATING_OUTPUT /* it complains otherwise. why? don't know, don't want to know */
template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, class> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<otherDimensions, T>& other) noexcept: _storage{other._storage}, _format{other._format}, _size{Math::Vector<dimensions, Int>::pad(other._size, 1)}, _data{other._data} {}
template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, class> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<otherDimensions, T>& other, const ImageFlags<dimensions> flags) noexcept:
_storage{other._storage},
_format{other._format},
/* Removing the Array bit and transferring the rest, as documented */
_flags{ImageFlag<dimensions>(UnsignedShort(other._flags)&~UnsignedShort(ImageFlag2D::Array))|flags},
_size{Math::Vector<dimensions, Int>::pad(other._size, 1)},
_data{other._data} {}
#endif
template<UnsignedInt dimensions, class T> template<class U, class> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _size{other._size}, _data{other._data} {}
template<UnsignedInt dimensions, class T> template<class U, class> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _flags{other._flags}, _size{other._size}, _data{other._data} {}
}

17
src/Magnum/Implementation/ImageProperties.h

@ -29,10 +29,27 @@
#include <Corrade/Containers/StridedArrayView.h>
#include "Magnum/Magnum.h"
#ifndef CORRADE_NO_ASSERT
#include "Magnum/ImageFlags.h"
#endif
#include "Magnum/DimensionTraits.h"
namespace Magnum { namespace Implementation {
/* Used in *Image and Compressed*Image constructors */
#ifndef CORRADE_NO_ASSERT
inline void checkImageFlagsForSize(const char*, const ImageFlags1D, const Math::Vector<1, Int>&) {}
inline void checkImageFlagsForSize(const char*, const ImageFlags2D, const Vector2i&) {}
inline void checkImageFlagsForSize(const char* const prefix, const ImageFlags3D flags, const Vector3i& size) {
CORRADE_ASSERT(!(flags & ImageFlag3D::CubeMap) || size.x() == size.y(),
prefix << "expected square faces for a cube map, got" << Debug::packed << size.xy(), );
CORRADE_ASSERT(!(flags & ImageFlag3D::CubeMap) || (flags & ImageFlag3D::Array) || size.z() == 6,
prefix << "expected exactly 6 faces for a cube map, got" << size.z(), );
CORRADE_ASSERT(!(flags >= (ImageFlag3D::CubeMap|ImageFlag3D::Array)) || size.z() % 6 == 0,
prefix << "expected a multiple of 6 faces for a cube map array, got" << size.z(), );
}
#endif
/* Used in *Image::dataProperties() */
template<std::size_t dimensions, class T> std::pair<Math::Vector<dimensions, std::size_t>, Math::Vector<dimensions, std::size_t>> imageDataProperties(const T& image) {
std::pair<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>> dataProperties = image.storage().dataProperties(image.pixelSize(), Vector3i::pad(image.size(), 1));

7
src/Magnum/Magnum.h

@ -1226,6 +1226,13 @@ template<class T> class CORRADE_DEPRECATED("use Math::Vector3 or Containers::Arr
enum class InputFileCallbackPolicy: UnsignedByte;
enum class ImageFlag1D: UnsignedShort;
enum class ImageFlag2D: UnsignedShort;
enum class ImageFlag3D: UnsignedShort;
typedef Containers::EnumSet<ImageFlag1D> ImageFlags1D;
typedef Containers::EnumSet<ImageFlag2D> ImageFlags2D;
typedef Containers::EnumSet<ImageFlag3D> ImageFlags3D;
template<UnsignedInt> class Image;
typedef Image<1> Image1D;
typedef Image<2> Image2D;

1
src/Magnum/Test/CMakeLists.txt

@ -29,6 +29,7 @@ set(CMAKE_FOLDER "Magnum/Test")
corrade_add_test(FileCallbackTest FileCallbackTest.cpp LIBRARIES Magnum)
corrade_add_test(ImageTest ImageTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(ImageFlagsTest ImageFlagsTest.cpp LIBRARIES Magnum)
corrade_add_test(ImageViewTest ImageViewTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(MeshTest MeshTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(PixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumTestLib)

157
src/Magnum/Test/ImageFlagsTest.cpp

@ -0,0 +1,157 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/DebugStl.h>
#include "Magnum/ImageFlags.h"
namespace Magnum { namespace Test { namespace {
struct ImageFlagsTest: TestSuite::Tester {
explicit ImageFlagsTest();
void matchingValues();
void debugFlag1D();
void debugFlag2D();
void debugFlag3D();
void debugFlag1DPacked();
void debugFlag2DPacked();
void debugFlag3DPacked();
void debugFlags1D();
void debugFlags2D();
void debugFlags3D();
void debugFlags1DPacked();
void debugFlags2DPacked();
void debugFlags3DPacked();
};
ImageFlagsTest::ImageFlagsTest() {
addTests({&ImageFlagsTest::matchingValues,
&ImageFlagsTest::debugFlag1D,
&ImageFlagsTest::debugFlag2D,
&ImageFlagsTest::debugFlag3D,
&ImageFlagsTest::debugFlag1DPacked,
&ImageFlagsTest::debugFlag2DPacked,
&ImageFlagsTest::debugFlag3DPacked,
&ImageFlagsTest::debugFlags1D,
&ImageFlagsTest::debugFlags2D,
&ImageFlagsTest::debugFlags3D,
&ImageFlagsTest::debugFlags1DPacked,
&ImageFlagsTest::debugFlags2DPacked,
&ImageFlagsTest::debugFlags3DPacked});
}
void ImageFlagsTest::matchingValues() {
CORRADE_COMPARE(UnsignedShort(ImageFlag3D::Array), UnsignedShort(ImageFlag2D::Array));
}
void ImageFlagsTest::debugFlag1D() {
std::ostringstream out;
/** @todo use a real flag once it exists */
Debug{&out} << ImageFlag1D(0xcafe);
CORRADE_COMPARE(out.str(), "ImageFlag1D(0xcafe)\n");
}
void ImageFlagsTest::debugFlag2D() {
std::ostringstream out;
Debug{&out} << ImageFlag2D::Array << ImageFlag2D(0xcafe);
CORRADE_COMPARE(out.str(), "ImageFlag2D::Array ImageFlag2D(0xcafe)\n");
}
void ImageFlagsTest::debugFlag3D() {
std::ostringstream out;
Debug{&out} << ImageFlag3D::CubeMap << ImageFlag3D(0xcafe);
CORRADE_COMPARE(out.str(), "ImageFlag3D::CubeMap ImageFlag3D(0xcafe)\n");
}
void ImageFlagsTest::debugFlag1DPacked() {
std::ostringstream out;
/* Last is not packed, ones before should not make any flags persistent */
/** @todo use real flags once they exist */
Debug{&out} << Debug::packed << ImageFlag1D(0xcafe) << ImageFlag1D(0xbeef);
CORRADE_COMPARE(out.str(), "0xcafe ImageFlag1D(0xbeef)\n");
}
void ImageFlagsTest::debugFlag2DPacked() {
std::ostringstream out;
/* Last is not packed, ones before should not make any flags persistent */
Debug{&out} << Debug::packed << ImageFlag2D::Array << Debug::packed << ImageFlag2D(0xcafe) << ImageFlag2D(0xbeef);
CORRADE_COMPARE(out.str(), "Array 0xcafe ImageFlag2D(0xbeef)\n");
}
void ImageFlagsTest::debugFlag3DPacked() {
std::ostringstream out;
/* Last is not packed, ones before should not make any flags persistent */
Debug{&out} << Debug::packed << ImageFlag3D::CubeMap << Debug::packed << ImageFlag3D(0xcafe) << ImageFlag3D(0xbeef);
CORRADE_COMPARE(out.str(), "CubeMap 0xcafe ImageFlag3D(0xbeef)\n");
}
void ImageFlagsTest::debugFlags1D() {
std::ostringstream out;
/** @todo use real flags once they exist */
Debug{&out} << (ImageFlag1D{}|ImageFlag1D(0xcafe)) << ImageFlags1D{};
CORRADE_COMPARE(out.str(), "ImageFlag1D(0xcafe) ImageFlags1D{}\n");
}
void ImageFlagsTest::debugFlags2D() {
std::ostringstream out;
Debug{&out} << (ImageFlag2D::Array|ImageFlag2D(0xcafe)) << ImageFlags2D{};
CORRADE_COMPARE(out.str(), "ImageFlag2D::Array|ImageFlag2D(0xcafe) ImageFlags2D{}\n");
}
void ImageFlagsTest::debugFlags3D() {
std::ostringstream out;
Debug{&out} << (ImageFlag3D::Array|ImageFlag3D::CubeMap |ImageFlag3D(0xcaf0)) << ImageFlags3D{};
CORRADE_COMPARE(out.str(), "ImageFlag3D::Array|ImageFlag3D::CubeMap|ImageFlag3D(0xcaf0) ImageFlags3D{}\n");
}
void ImageFlagsTest::debugFlags1DPacked() {
std::ostringstream out;
/** @todo use real flags once they exist */
Debug{&out} << Debug::packed << (ImageFlag1D{}|ImageFlag1D(0xcafe)) << Debug::packed << ImageFlags1D{} << ImageFlag1D(0xbeef);
CORRADE_COMPARE(out.str(), "0xcafe {} ImageFlag1D(0xbeef)\n");
}
void ImageFlagsTest::debugFlags2DPacked() {
std::ostringstream out;
Debug{&out} << Debug::packed << (ImageFlag2D::Array|ImageFlag2D(0xcaf0)) << Debug::packed << ImageFlags2D{} << ImageFlag2D(0xbeef);
CORRADE_COMPARE(out.str(), "Array|0xcaf0 {} ImageFlag2D(0xbeef)\n");
}
void ImageFlagsTest::debugFlags3DPacked() {
std::ostringstream out;
Debug{&out} << Debug::packed << (ImageFlag3D::Array|ImageFlag3D::CubeMap |ImageFlag3D(0xcaf0)) << Debug::packed << ImageFlags3D{} << ImageFlag3D(0xbeef);
CORRADE_COMPARE(out.str(), "Array|CubeMap|0xcaf0 {} ImageFlag3D(0xbeef)\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::Test::ImageFlagsTest)

110
src/Magnum/Test/ImageTest.cpp

@ -51,7 +51,9 @@ struct ImageTest: TestSuite::Tester {
void constructCompressedImplementationSpecific();
void constructInvalidSize();
void constructInvalidCubeMap();
void constructCompressedInvalidSize();
void constructCompressedInvalidCubeMap();
void constructCopy();
void constructCopyCompressed();
@ -106,7 +108,9 @@ ImageTest::ImageTest() {
&ImageTest::constructCompressedImplementationSpecific,
&ImageTest::constructInvalidSize,
&ImageTest::constructInvalidCubeMap,
&ImageTest::constructCompressedInvalidSize,
&ImageTest::constructCompressedInvalidCubeMap,
&ImageTest::constructCopy,
&ImageTest::constructCopyCompressed,
@ -179,8 +183,9 @@ namespace Vk {
void ImageTest::constructGeneric() {
{
auto data = new char[4*4];
Image2D a{PixelFormat::RGBA8Unorm, {1, 3}, Containers::Array<char>{data, 4*4}};
Image2D a{PixelFormat::RGBA8Unorm, {1, 3}, Containers::Array<char>{data, 4*4}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RGBA8Unorm);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -191,8 +196,9 @@ void ImageTest::constructGeneric() {
} {
auto data = new char[3*2];
Image2D a{PixelStorage{}.setAlignment(1),
PixelFormat::R16UI, {1, 3}, Containers::Array<char>{data, 3*2}};
PixelFormat::R16UI, {1, 3}, Containers::Array<char>{data, 3*2}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::R16UI);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -207,6 +213,7 @@ void ImageTest::constructGenericPlaceholder() {
{
Image2D a{PixelFormat::RG32F};
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RG32F);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -217,6 +224,7 @@ void ImageTest::constructGenericPlaceholder() {
Image2D a{PixelStorage{}.setAlignment(1),
PixelFormat::RGB16F};
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::RGB16F);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -230,8 +238,9 @@ void ImageTest::constructImplementationSpecific() {
/* Single format */
{
auto data = new char[3*12];
Image2D a{Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array<char>{data, 3*12}};
Image2D a{Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array<char>{data, 3*12}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -242,8 +251,9 @@ void ImageTest::constructImplementationSpecific() {
} {
auto data = new char[3*12];
Image2D a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array<char>{data, 3*12}};
Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array<char>{data, 3*12}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -256,8 +266,9 @@ void ImageTest::constructImplementationSpecific() {
/* Format + extra */
{
auto data = new char[3*8];
Image2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*8}};
Image2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*8}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -268,8 +279,9 @@ void ImageTest::constructImplementationSpecific() {
} {
auto data = new char[3*6];
Image2D a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
@ -281,8 +293,9 @@ void ImageTest::constructImplementationSpecific() {
/* Manual pixel size */
{
auto data = new char[3*6];
Image2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, Containers::Array<char>{data, 3*6}};
Image2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -298,6 +311,7 @@ void ImageTest::constructImplementationSpecificPlaceholder() {
{
Image2D a{Vk::PixelFormat::R32G32B32F};
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -308,6 +322,7 @@ void ImageTest::constructImplementationSpecificPlaceholder() {
Image2D a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F};
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -320,6 +335,7 @@ void ImageTest::constructImplementationSpecificPlaceholder() {
{
Image2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort};
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -330,6 +346,7 @@ void ImageTest::constructImplementationSpecificPlaceholder() {
Image2D a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort};
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
@ -341,6 +358,7 @@ void ImageTest::constructImplementationSpecificPlaceholder() {
{
Image2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6};
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -354,8 +372,9 @@ void ImageTest::constructCompressedGeneric() {
{
auto data = new char[8];
CompressedImage2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4},
Containers::Array<char>{data, 8}};
Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -365,8 +384,9 @@ void ImageTest::constructCompressedGeneric() {
auto data = new char[8];
CompressedImage2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBAUnorm, {4, 4},
Containers::Array<char>{data, 8}};
Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), Vector2i(4, 4));
@ -379,6 +399,7 @@ void ImageTest::constructCompressedGenericPlaceholder() {
{
CompressedImage2D a;
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), CompressedPixelFormat{});
CORRADE_COMPARE(a.size(), Vector2i{});
@ -386,6 +407,7 @@ void ImageTest::constructCompressedGenericPlaceholder() {
} {
CompressedImage2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4})};
CORRADE_COMPARE(a.flags(), ImageFlags2D{});
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), CompressedPixelFormat{});
CORRADE_COMPARE(a.size(), Vector2i{});
@ -398,8 +420,9 @@ void ImageTest::constructCompressedImplementationSpecific() {
{
auto data = new char[8];
CompressedImage2D a{GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4},
Containers::Array<char>{data, 8}};
Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -409,8 +432,9 @@ void ImageTest::constructCompressedImplementationSpecific() {
auto data = new char[8];
CompressedImage2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4},
Containers::Array<char>{data, 8}};
Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -434,6 +458,24 @@ void ImageTest::constructInvalidSize() {
CORRADE_COMPARE(out.str(), "Image: data too small, got 9 but expected at least 12 bytes\n");
}
void ImageTest::constructInvalidCubeMap() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
std::ostringstream out;
Error redirectError{&out};
Image3D{PixelFormat::RGBA8Unorm, {3, 3, 5}, Containers::Array<char>{3*3*5*4}, ImageFlag3D::CubeMap};
Image3D{PixelFormat::RGBA8Unorm, {3, 4, 6}, Containers::Array<char>{3*4*6*4}, ImageFlag3D::CubeMap};
Image3D{PixelFormat::RGBA8Unorm, {3, 3, 17}, Containers::Array<char>{3*3*17*4}, ImageFlag3D::CubeMap |ImageFlag3D::Array};
Image3D{PixelFormat::RGBA8Unorm, {4, 3, 18}, Containers::Array<char>{4*3*18*4}, ImageFlag3D::CubeMap |ImageFlag3D::Array};
CORRADE_COMPARE(out.str(),
"Image: expected exactly 6 faces for a cube map, got 5\n"
"Image: expected square faces for a cube map, got {3, 4}\n"
"Image: expected a multiple of 6 faces for a cube map array, got 17\n"
"Image: expected square faces for a cube map, got {4, 3}\n");
}
void ImageTest::constructCompressedInvalidSize() {
CORRADE_EXPECT_FAIL("Size checking for compressed image data is not implemented yet.");
@ -453,6 +495,24 @@ void ImageTest::constructCompressedInvalidSize() {
}
}
void ImageTest::constructCompressedInvalidCubeMap() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
std::ostringstream out;
Error redirectError{&out};
CompressedImage3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 3, 5}, Containers::Array<char>{8*5}, ImageFlag3D::CubeMap};
CompressedImage3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 4, 6}, Containers::Array<char>{8*6}, ImageFlag3D::CubeMap};
CompressedImage3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 3, 17}, Containers::Array<char>{8*17}, ImageFlag3D::CubeMap |ImageFlag3D::Array};
CompressedImage3D{CompressedPixelFormat::Bc1RGBAUnorm, {4, 3, 18}, Containers::Array<char>{8*18}, ImageFlag3D::CubeMap |ImageFlag3D::Array};
CORRADE_COMPARE(out.str(),
"CompressedImage: expected exactly 6 faces for a cube map, got 5\n"
"CompressedImage: expected square faces for a cube map, got {3, 4}\n"
"CompressedImage: expected a multiple of 6 faces for a cube map array, got 17\n"
"CompressedImage: expected square faces for a cube map, got {4, 3}\n");
}
void ImageTest::constructCopy() {
CORRADE_VERIFY(!std::is_copy_constructible<Image2D>{});
CORRADE_VERIFY(!std::is_copy_assignable<Image2D>{});
@ -466,12 +526,13 @@ void ImageTest::constructCopyCompressed() {
void ImageTest::constructMoveGeneric() {
auto data = new char[3*16];
Image2D a{PixelStorage{}.setAlignment(1),
PixelFormat::RGBA32F, {1, 3}, Containers::Array<char>{data, 3*16}};
PixelFormat::RGBA32F, {1, 3}, Containers::Array<char>{data, 3*16}, ImageFlag2D::Array};
Image2D b(std::move(a));
CORRADE_COMPARE(a.data(), nullptr);
CORRADE_COMPARE(a.size(), Vector2i{});
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), PixelFormat::RGBA32F);
CORRADE_COMPARE(b.formatExtra(), 0);
@ -487,6 +548,7 @@ void ImageTest::constructMoveGeneric() {
CORRADE_COMPARE(b.data(), data2);
CORRADE_COMPARE(b.size(), (Vector2i{2, 6}));
CORRADE_COMPARE(c.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(c.storage().alignment(), 1);
CORRADE_COMPARE(c.format(), PixelFormat::RGBA32F);
CORRADE_COMPARE(c.formatExtra(), 0);
@ -502,12 +564,13 @@ void ImageTest::constructMoveGeneric() {
void ImageTest::constructMoveImplementationSpecific() {
auto data = new char[3*6];
Image2D a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array};
Image2D b(std::move(a));
CORRADE_COMPARE(a.data(), nullptr);
CORRADE_COMPARE(a.size(), Vector2i{});
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), 1337);
@ -524,6 +587,7 @@ void ImageTest::constructMoveImplementationSpecific() {
CORRADE_COMPARE(b.data(), data2);
CORRADE_COMPARE(b.size(), Vector2i(2, 6));
CORRADE_COMPARE(c.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(c.storage().alignment(), 1);
CORRADE_COMPARE(c.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(c.formatExtra(), 1337);
@ -537,12 +601,13 @@ void ImageTest::constructMoveCompressedGeneric() {
auto data = new char[8];
CompressedImage2D a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc3RGBAUnorm, {4, 4}, Containers::Array<char>{data, 8}};
CompressedPixelFormat::Bc3RGBAUnorm, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CompressedImage2D b{std::move(a)};
CORRADE_COMPARE(a.data(), nullptr);
CORRADE_COMPARE(a.size(), Vector2i{});
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), CompressedPixelFormat::Bc3RGBAUnorm);
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
@ -556,6 +621,7 @@ void ImageTest::constructMoveCompressedGeneric() {
CORRADE_COMPARE(b.data(), data2);
CORRADE_COMPARE(b.size(), (Vector2i{8, 4}));
CORRADE_COMPARE(c.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(c.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(c.format(), CompressedPixelFormat::Bc3RGBAUnorm);
CORRADE_COMPARE(c.size(), (Vector2i{4, 4}));
@ -570,12 +636,13 @@ void ImageTest::constructMoveCompressedImplementationSpecific() {
auto data = new char[8];
CompressedImage2D a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CompressedImage2D b{std::move(a)};
CORRADE_COMPARE(a.data(), nullptr);
CORRADE_COMPARE(a.size(), Vector2i{});
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
@ -589,6 +656,7 @@ void ImageTest::constructMoveCompressedImplementationSpecific() {
CORRADE_COMPARE(b.data(), data2);
CORRADE_COMPARE(b.size(), (Vector2i{8, 4}));
CORRADE_COMPARE(c.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(c.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(c.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(c.size(), (Vector2i{4, 4}));
@ -601,9 +669,10 @@ template<class T> void ImageTest::toViewGeneric() {
auto data = new char[3*4];
typename MutabilityTraits<T>::ImageType a{PixelStorage{}.setAlignment(1),
PixelFormat::RG16I, {1, 3}, Containers::Array<char>{data, 3*4}};
PixelFormat::RG16I, {1, 3}, Containers::Array<char>{data, 3*4}, ImageFlag2D::Array};
ImageView<2, T> b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), PixelFormat::RG16I);
CORRADE_COMPARE(b.formatExtra(), 0);
@ -617,9 +686,10 @@ template<class T> void ImageTest::toViewImplementationSpecific() {
auto data = new char[3*6];
typename MutabilityTraits<T>::ImageType a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array};
ImageView<2, T> b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), 1337);
@ -634,9 +704,10 @@ template<class T> void ImageTest::toViewCompressedGeneric() {
auto data = new char[8];
typename MutabilityTraits<T>::CompressedImageType a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBUnorm, {4, 4}, Containers::Array<char>{data, 8}};
CompressedPixelFormat::Bc1RGBUnorm, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CompressedImageView<2, T> b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), CompressedPixelFormat::Bc1RGBUnorm);
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
@ -650,9 +721,10 @@ template<class T> void ImageTest::toViewCompressedImplementationSpecific() {
auto data = new char[8];
typename MutabilityTraits<T>::CompressedImageType a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CompressedImageView<2, T> b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));

164
src/Magnum/Test/ImageViewTest.cpp

@ -60,7 +60,9 @@ struct ImageViewTest: TestSuite::Tester {
void constructNullptr();
void constructInvalidSize();
void constructInvalidCubeMap();
void constructCompressedInvalidSize();
void constructCompressedInvalidCubeMap();
void dataProperties();
void dataPropertiesCompressed();
@ -113,7 +115,9 @@ ImageViewTest::ImageViewTest() {
&ImageViewTest::constructNullptr,
&ImageViewTest::constructInvalidSize,
&ImageViewTest::constructInvalidCubeMap,
&ImageViewTest::constructCompressedInvalidSize,
&ImageViewTest::constructCompressedInvalidCubeMap,
&ImageViewTest::dataProperties,
&ImageViewTest::dataPropertiesCompressed,
@ -175,8 +179,9 @@ template<class T> void ImageViewTest::constructGeneric() {
{
T data[4*4]{};
ImageView<2, T> a{PixelFormat::RGBA8Unorm, {1, 3}, data};
ImageView<2, T> a{PixelFormat::RGBA8Unorm, {1, 3}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RGBA8Unorm);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -187,8 +192,9 @@ template<class T> void ImageViewTest::constructGeneric() {
} {
T data[3*2]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
PixelFormat::R16UI, {1, 3}, data};
PixelFormat::R16UI, {1, 3}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::R16UI);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -203,8 +209,9 @@ template<class T> void ImageViewTest::constructGenericEmpty() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
{
ImageView<2, T> a{PixelFormat::RG32F, {2, 6}};
ImageView<2, T> a{PixelFormat::RG32F, {2, 6}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RG32F);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -213,8 +220,9 @@ template<class T> void ImageViewTest::constructGenericEmpty() {
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
} {
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
PixelFormat::RGB16F, {8, 3}};
PixelFormat::RGB16F, {8, 3}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::RGB16F);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -230,8 +238,9 @@ template<class T> void ImageViewTest::constructImplementationSpecific() {
/* Single format */
{
T data[3*12]{};
ImageView<2, T> a{Vk::PixelFormat::R32G32B32F, {1, 3}, data};
ImageView<2, T> a{Vk::PixelFormat::R32G32B32F, {1, 3}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -242,8 +251,9 @@ template<class T> void ImageViewTest::constructImplementationSpecific() {
} {
T data[3*12]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F, {1, 3}, data};
Vk::PixelFormat::R32G32B32F, {1, 3}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -256,8 +266,9 @@ template<class T> void ImageViewTest::constructImplementationSpecific() {
/* Format + extra */
{
T data[3*8]{};
ImageView<2, T> a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data};
ImageView<2, T> a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -268,8 +279,9 @@ template<class T> void ImageViewTest::constructImplementationSpecific() {
} {
T data[3*6]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
@ -281,8 +293,9 @@ template<class T> void ImageViewTest::constructImplementationSpecific() {
/* Manual pixel size */
{
T data[3*6]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data};
ImageView<2, T> a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -298,8 +311,9 @@ template<class T> void ImageViewTest::constructImplementationSpecificEmpty() {
/* Single format */
{
ImageView<2, T> a{Vk::PixelFormat::R32G32B32F, {2, 16}};
ImageView<2, T> a{Vk::PixelFormat::R32G32B32F, {2, 16}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -308,8 +322,9 @@ template<class T> void ImageViewTest::constructImplementationSpecificEmpty() {
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
} {
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F, {1, 2}};
Vk::PixelFormat::R32G32B32F, {1, 2}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -320,8 +335,9 @@ template<class T> void ImageViewTest::constructImplementationSpecificEmpty() {
/* Format + extra */
{
ImageView<2, T> a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}};
ImageView<2, T> a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -330,8 +346,9 @@ template<class T> void ImageViewTest::constructImplementationSpecificEmpty() {
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
} {
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {8, 2}};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {8, 2}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
@ -341,8 +358,9 @@ template<class T> void ImageViewTest::constructImplementationSpecificEmpty() {
/* Manual pixel size */
{
ImageView<2, T> a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {3, 3}};
ImageView<2, T> a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {3, 3}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -357,8 +375,9 @@ template<class T> void ImageViewTest::constructCompressedGeneric() {
{
T data[8]{};
CompressedImageView<2, T> a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, data};
CompressedImageView<2, T> a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -368,8 +387,9 @@ template<class T> void ImageViewTest::constructCompressedGeneric() {
T data[8]{};
CompressedImageView<2, T> a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBAUnorm, {4, 4},
data};
data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -382,16 +402,18 @@ template<class T> void ImageViewTest::constructCompressedGenericEmpty() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
{
CompressedImageView<2, T> a{CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}};
CompressedImageView<2, T> a{CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{8, 16}));
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
} {
CompressedImageView<2, T> a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}};
CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{8, 16}));
@ -406,8 +428,9 @@ template<class T> void ImageViewTest::constructCompressedImplementationSpecific(
{
T data[8]{};
CompressedImageView<2, T> a{GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4},
data};
data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -416,8 +439,9 @@ template<class T> void ImageViewTest::constructCompressedImplementationSpecific(
} {
T data[8]{};
CompressedImageView<2, T> a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, data};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -433,16 +457,18 @@ template<class T> void ImageViewTest::constructCompressedImplementationSpecificE
/* Format with autodetection */
{
CompressedImageView<2, T> a{GL::CompressedPixelFormat::RGBS3tcDxt1, {8, 16}};
CompressedImageView<2, T> a{GL::CompressedPixelFormat::RGBS3tcDxt1, {8, 16}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{8, 16}));
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
} {
CompressedImageView<2, T> a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 8}};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 8}, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 8}));
@ -456,7 +482,9 @@ void ImageViewTest::construct3DFrom1D() {
/* Copy of "Manual pixel size" in constructImplementationSpecific(), as
that exposes most fields */
const char data[3*6]{};
ImageView1D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, 3, data};
/** @todo use a real flag once it exists */
ImageView1D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, 3, data, ImageFlag1D(0xdea0)};
CORRADE_COMPARE(a.flags(), ImageFlag1D(0xdea0));
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -465,7 +493,10 @@ void ImageViewTest::construct3DFrom1D() {
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*6);
ImageView3D b = a; /* implicit conversion allowed */
/* Not testing the flags parameter here to be sure implicit conversion
works as well, it's tested in construct3DFrom2D() below */
ImageView3D b = a;
CORRADE_COMPARE(b.flags(), ImageFlag3D(0xdea0));
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -486,7 +517,8 @@ void ImageViewTest::construct3DFrom2D() {
/* Copy of "Manual pixel size" in constructImplementationSpecific(), as
that exposes most fields */
char data[3*6]{};
MutableImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data};
MutableImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data, ImageFlag2D::Array|ImageFlag2D(0xde00)};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array|ImageFlag2D(0xde00));
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -495,7 +527,10 @@ void ImageViewTest::construct3DFrom2D() {
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*6);
MutableImageView3D b = a;
MutableImageView3D b = {a, ImageFlag3D(0x00a0)};
/* The Array flag got implicitly stripped away, the rest got passed through
and combined with the flags argument */
CORRADE_COMPARE(b.flags(), ImageFlag3D(0xdea0));
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -516,15 +551,20 @@ void ImageViewTest::constructCompressed3DFrom1D() {
/** @todo S3TC doesn't have 1D compression so this might blow up once we
check for block sizes */
const char data[8]{};
/** @todo use a real flag once it exists */
CompressedImageView1D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, 4, data};
GL::CompressedPixelFormat::RGBS3tcDxt1, 4, data, ImageFlag1D(0xdea0)};
CORRADE_COMPARE(a.flags(), ImageFlag1D(0xdea0));
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), 4);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 8);
/* Not testing the flags parameter here to be sure implicit conversion
works as well, it's tested in constructCompressed3DFrom2D() below */
CompressedImageView3D b = a;
CORRADE_COMPARE(b.flags(), ImageFlag3D(0xdea0));
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector3i{4, 1, 1}));
@ -544,14 +584,18 @@ void ImageViewTest::constructCompressed3DFrom2D() {
most fields */
char data[8*2]{};
MutableCompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 8}, data};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 8}, data, ImageFlag2D::Array|ImageFlag2D(0xde00)};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array|ImageFlag2D(0xde00));
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 8}));
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 8*2);
MutableCompressedImageView3D b = a;
MutableCompressedImageView3D b = {a, ImageFlag3D(0x00a0)};
/* The Array flag got implicitly stripped away, the rest got passed through
and combined with the flags argument */
CORRADE_COMPARE(b.flags(), ImageFlag3D(0xdea0));
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector3i{4, 8, 1}));
@ -568,7 +612,8 @@ void ImageViewTest::constructFromMutable() {
/* Copy of "Manual pixel size" in constructImplementationSpecific(), as
that exposes most fields */
char data[3*6]{};
MutableImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data};
MutableImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -578,6 +623,7 @@ void ImageViewTest::constructFromMutable() {
CORRADE_COMPARE(a.data().size(), 3*6);
ImageView2D b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -592,7 +638,8 @@ void ImageViewTest::constructCompressedFromMutable() {
most fields */
char data[8]{};
MutableCompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, data};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, data, ImageFlag2D::Array};
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -600,6 +647,7 @@ void ImageViewTest::constructCompressedFromMutable() {
CORRADE_COMPARE(a.data().size(), 8);
CompressedImageView2D b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
@ -610,16 +658,14 @@ void ImageViewTest::constructCompressedFromMutable() {
void ImageViewTest::constructNullptr() {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_SKIP("This is still allowed on a deprecated build, can't test.");
#endif
#ifdef CORRADE_NO_ASSERT
#elif defined(CORRADE_NO_ASSERT)
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
#else
std::ostringstream out;
Error redirectError{&out};
ImageView2D{PixelFormat::RGB8Unorm, {1, 3}, nullptr};
CORRADE_COMPARE(out.str(), "ImageView: data too small, got 0 but expected at least 12 bytes\n");
#endif
}
void ImageViewTest::constructInvalidSize() {
@ -636,6 +682,29 @@ void ImageViewTest::constructInvalidSize() {
CORRADE_COMPARE(out.str(), "ImageView: data too small, got 9 but expected at least 12 bytes\n");
}
void ImageViewTest::constructInvalidCubeMap() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
const char data[4*3*18*4]{};
std::ostringstream out;
Error redirectError{&out};
ImageView3D{PixelFormat::RGBA8Unorm, {3, 3, 5}, data, ImageFlag3D::CubeMap};
ImageView3D{PixelFormat::RGBA8Unorm, {3, 4, 6}, data, ImageFlag3D::CubeMap};
ImageView3D{PixelFormat::RGBA8Unorm, {3, 3, 17}, data, ImageFlag3D::CubeMap |ImageFlag3D::Array};
ImageView3D{PixelFormat::RGBA8Unorm, {4, 3, 18}, data, ImageFlag3D::CubeMap |ImageFlag3D::Array};
/* The data-less variant should call into the same assertion helper */
ImageView3D{PixelFormat::RGBA8Unorm, {3, 3, 5}, ImageFlag3D::CubeMap};
CORRADE_COMPARE(out.str(),
"ImageView: expected exactly 6 faces for a cube map, got 5\n"
"ImageView: expected square faces for a cube map, got {3, 4}\n"
"ImageView: expected a multiple of 6 faces for a cube map array, got 17\n"
"ImageView: expected square faces for a cube map, got {4, 3}\n"
"ImageView: expected exactly 6 faces for a cube map, got 5\n");
}
void ImageViewTest::constructCompressedInvalidSize() {
CORRADE_EXPECT_FAIL("Size checking for compressed image data is not implemented yet.");
@ -657,6 +726,29 @@ void ImageViewTest::constructCompressedInvalidSize() {
}
}
void ImageViewTest::constructCompressedInvalidCubeMap() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
const char data[8*18]{};
std::ostringstream out;
Error redirectError{&out};
CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 3, 5}, data, ImageFlag3D::CubeMap};
CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 4, 6}, data, ImageFlag3D::CubeMap};
CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 3, 17}, data, ImageFlag3D::CubeMap |ImageFlag3D::Array};
CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {4, 3, 18}, data, ImageFlag3D::CubeMap |ImageFlag3D::Array};
/* The data-less variant should call into the same assertion helper */
CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 3, 5}, ImageFlag3D::CubeMap};
CORRADE_COMPARE(out.str(),
"CompressedImageView: expected exactly 6 faces for a cube map, got 5\n"
"CompressedImageView: expected square faces for a cube map, got {3, 4}\n"
"CompressedImageView: expected a multiple of 6 faces for a cube map array, got 17\n"
"CompressedImageView: expected square faces for a cube map, got {4, 3}\n"
"CompressedImageView: expected exactly 6 faces for a cube map, got 5\n");
}
void ImageViewTest::dataProperties() {
const char data[224]{};
ImageView3D image{

46
src/Magnum/Trade/ImageData.cpp

@ -33,61 +33,68 @@
namespace Magnum { namespace Trade {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, format, {}, pixelFormatSize(format), size, std::move(data), importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, format, {}, pixelFormatSize(format), size, std::move(data), flags, importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{storage, format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, importerState} {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, flags, importerState} {
CORRADE_ASSERT(!(dataFlags & DataFlag::Owned),
"Trade::ImageData: can't construct a non-owned instance with" << dataFlags, );
_dataFlags = dataFlags;
}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{{}, format, size, std::move(data), importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{{}, format, size, std::move(data), flags, importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, importerState} {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, flags, importerState} {
CORRADE_ASSERT(!(dataFlags & DataFlag::Owned),
"Trade::ImageData: can't construct a non-owned instance with" << dataFlags, );
_dataFlags = dataFlags;
}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, std::move(data), importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, std::move(data), flags, importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _compressed{false}, _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{std::move(data)}, _importerState{importerState} {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _compressed{false}, _flags{flags}, _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{std::move(data)}, _importerState{importerState} {
CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= _data.size(), "Trade::ImageData: data too small, got" << _data.size() << "but expected at least" << Magnum::Implementation::imageDataSize(*this) << "bytes", );
#ifndef CORRADE_NO_ASSERT
Magnum::Implementation::checkImageFlagsForSize("Trade::ImageData:", flags, size);
#endif
}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, dataFlags, data, importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, dataFlags, data, flags, importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{storage, format, formatExtra, pixelSize, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, importerState} {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, format, formatExtra, pixelSize, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, flags, importerState} {
CORRADE_ASSERT(!(dataFlags & DataFlag::Owned),
"Trade::ImageData: can't construct a non-owned instance with" << dataFlags, );
_dataFlags = dataFlags;
}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _compressed{true}, _compressedStorage{storage}, _compressedFormat{format}, _size{size}, _data{std::move(data)}, _importerState{importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _compressed{true}, _flags{flags}, _compressedStorage{storage}, _compressedFormat{format}, _size{size}, _data{std::move(data)}, _importerState{importerState} {
#ifndef CORRADE_NO_ASSERT
Magnum::Implementation::checkImageFlagsForSize("Trade::ImageData:", flags, size);
#endif
}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{storage, format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, importerState} {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, flags, importerState} {
CORRADE_ASSERT(!(dataFlags & DataFlag::Owned),
"Trade::ImageData: can't construct a non-owned instance with" << dataFlags, );
_dataFlags = dataFlags;
}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{{}, format, size, std::move(data), importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{{}, format, size, std::move(data), flags, importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, importerState} {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, flags, importerState} {
CORRADE_ASSERT(!(dataFlags & DataFlag::Owned),
"Trade::ImageData: can't construct a non-owned instance with" << dataFlags, );
_dataFlags = dataFlags;
}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, compressedPixelFormatWrap(format), size, std::move(data), importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, compressedPixelFormatWrap(format), size, std::move(data), flags, importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{storage, format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, importerState} {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, format, size, Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, flags, importerState} {
CORRADE_ASSERT(!(dataFlags & DataFlag::Owned),
"Trade::ImageData: can't construct a non-owned instance with" << dataFlags, );
_dataFlags = dataFlags;
}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(ImageData<dimensions>&& other) noexcept: _dataFlags{other._dataFlags}, _compressed{std::move(other._compressed)}, _size{std::move(other._size)}, _data{std::move(other._data)}, _importerState{std::move(other._importerState)} {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(ImageData<dimensions>&& other) noexcept: _dataFlags{other._dataFlags}, _compressed{std::move(other._compressed)}, _flags{std::move(other._flags)}, _size{std::move(other._size)}, _data{std::move(other._data)}, _importerState{std::move(other._importerState)} {
if(_compressed) {
new(&_compressedStorage) CompressedPixelStorage{std::move(other._compressedStorage)};
_compressedFormat = std::move(other._compressedFormat);
@ -110,6 +117,7 @@ template<UnsignedInt dimensions> ImageData<dimensions>& ImageData<dimensions>::o
using std::swap;
swap(_dataFlags, other._dataFlags);
swap(_compressed, other._compressed);
swap(_flags, other._flags);
if(_compressed) {
swap(_compressedStorage, other._compressedStorage);
swap(_compressedFormat, other._compressedFormat);
@ -181,21 +189,21 @@ template<UnsignedInt dimensions> Containers::StridedArrayView<dimensions + 1, ch
template<UnsignedInt dimensions> ImageData<dimensions>::operator BasicImageView<dimensions>() const {
CORRADE_ASSERT(!_compressed, "Trade::ImageData: the image is compressed", (BasicImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size}));
return BasicImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
return BasicImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data, _flags};
}
template<UnsignedInt dimensions> ImageData<dimensions>::operator BasicMutableImageView<dimensions>() {
CORRADE_ASSERT(_dataFlags & DataFlag::Mutable,
"Trade::ImageData: the image is not mutable", (BasicMutableImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size}));
CORRADE_ASSERT(!_compressed, "Trade::ImageData: the image is compressed", (BasicMutableImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size}));
return BasicMutableImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
return BasicMutableImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data, _flags};
}
template<UnsignedInt dimensions> ImageData<dimensions>::operator BasicCompressedImageView<dimensions>() const {
CORRADE_ASSERT(_compressed, "Trade::ImageData: the image is not compressed", (BasicCompressedImageView<dimensions>{_compressedStorage, _compressedFormat, _size}));
return BasicCompressedImageView<dimensions>{
_compressedStorage,
_compressedFormat, _size, _data};
_compressedFormat, _size, _data, _flags};
}
template<UnsignedInt dimensions> ImageData<dimensions>::operator BasicMutableCompressedImageView<dimensions>() {
@ -205,7 +213,7 @@ template<UnsignedInt dimensions> ImageData<dimensions>::operator BasicMutableCom
CORRADE_ASSERT(_compressed, "Trade::ImageData: the image is not compressed", (BasicMutableCompressedImageView<dimensions>{_compressedStorage, _compressedFormat, _size}));
return BasicMutableCompressedImageView<dimensions>{
_compressedStorage,
_compressedFormat, _size, _data};
_compressedFormat, _size, _data, _flags};
}
template<UnsignedInt dimensions> Containers::Array<char> ImageData<dimensions>::release() {

304
src/Magnum/Trade/ImageData.h

@ -32,6 +32,7 @@
#include <Corrade/Containers/Array.h>
#include "Magnum/DimensionTraits.h"
#include "Magnum/ImageFlags.h"
#include "Magnum/PixelStorage.h"
#include "Magnum/Trade/Data.h"
#include "Magnum/Trade/Trade.h"
@ -115,17 +116,30 @@ template<UnsignedInt dimensions> class ImageData {
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since_latest
*
* The @p data array is expected to be of proper size for given
* parameters.
* parameters. For a 3D image, if @p flags contain
* @ref ImageFlag3D::CubeMap, the @p size is expected to match its
* restrictions.
*
* The @ref dataFlags() are implicitly set to a combination of
* @ref DataFlag::Owned and @ref DataFlag::Mutable. For non-owned data
* use the @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, const void*)
* use the @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* constructor instead.
*/
explicit ImageData(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
explicit ImageData(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{storage, format, size, std::move(data), {}, importerState} {}
#endif
/**
* @brief Construct a non-owned uncompressed image data
@ -134,28 +148,49 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size
* @param dataFlags Data flags
* @param data View on image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since{2020,06}
* @m_since_latest
*
* Compared to @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Compared to @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* creates an instance that doesn't own the passed data. The
* @p dataFlags parameter can contain @ref DataFlag::Mutable to
* indicate the external data can be modified, and is expected to *not*
* have @ref DataFlag::Owned set.
*/
explicit ImageData(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
explicit ImageData(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{storage, format, size, dataFlags, data, {}, importerState} {}
#endif
/**
* @brief Construct an uncompressed image data
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since_latest
*
* Equivalent to calling @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Equivalent to calling @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* with default-constructed @ref PixelStorage.
*/
explicit ImageData(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
explicit ImageData(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{format, size, std::move(data), {}, importerState} {}
#endif
/**
* @brief Construct a non-owned uncompressed image data
@ -163,16 +198,26 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size
* @param dataFlags Data flags
* @param data View on image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since{2020,06}
* @m_since_latest
*
* Compared to @ref ImageData(PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Compared to @ref ImageData(PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* creates an instance that doesn't own the passed data. The
* @p dataFlags parameter can contain @ref DataFlag::Mutable to
* indicate the external data can be modified, and is expected to *not*
* have @ref DataFlag::Owned set.
*/
explicit ImageData(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
explicit ImageData(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{format, size, dataFlags, data, {}, importerState} {}
#endif
/**
* @brief Construct an uncompressed image data with implementation-specific pixel format
@ -182,9 +227,11 @@ template<UnsignedInt dimensions> class ImageData {
* @param pixelSize Size of a pixel in given format, in bytes
* @param size Image size, in pixels
* @param data Image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since_latest
*
* Unlike with @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*),
* Unlike with @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*),
* where pixel size is calculated automatically using
* @ref pixelFormatSize(), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
@ -192,19 +239,38 @@ template<UnsignedInt dimensions> class ImageData {
* @ref Magnum::PixelFormat "PixelFormat".
*
* The @p data array is expected to be of proper size for given
* parameters. The @ref dataFlags() are implicitly set to a combination
* of @ref DataFlag::Owned and @ref DataFlag::Mutable. For non-owned
* data use the @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, const void*)
* parameters. For a 3D image, if @p flags contain
* @ref ImageFlag3D::CubeMap, the @p size is expected to match its
* restrictions. The @ref dataFlags() are implicitly set to a
* combination of @ref DataFlag::Owned and @ref DataFlag::Mutable. For
* non-owned data use the @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* constructor instead.
*/
explicit ImageData(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
explicit ImageData(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
/** @overload
* @m_since_latest
*
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/
explicit ImageData(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
explicit ImageData(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{storage, format, formatExtra, pixelSize, size, std::move(data), {}, importerState} {}
/**
* @overload
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, PixelFormat, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{storage, format, formatExtra, pixelSize, size, std::move(data), {}, importerState} {}
#endif
/**
* @brief Construct a non-owned uncompressed image data with implementation-specific pixel format
@ -215,24 +281,41 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size, in pixels
* @param dataFlags Data flags
* @param data View on image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since{2020,06}
* @m_since_latest
*
* Compared to @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Compared to @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* creates an instance that doesn't own the passed data. The
* @p dataFlags parameter can contain @ref DataFlag::Mutable to
* indicate the external data can be modified, and is expected to *not*
* have @ref DataFlag::Owned set.
*/
explicit ImageData(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
explicit ImageData(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
/** @overload
* @m_since{2020,06}
* @m_since_latest
*
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/
explicit ImageData(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
explicit ImageData(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{storage, format, formatExtra, pixelSize, size, dataFlags, data, {}, importerState} {}
/**
* @overload
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, PixelFormat, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{storage, format, formatExtra, pixelSize, size, dataFlags, data, {}, importerState} {}
#endif
/**
* @brief Construct an uncompressed image data with implementation-specific pixel format
@ -241,13 +324,24 @@ template<UnsignedInt dimensions> class ImageData {
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since_latest
*
* Uses ADL to find a corresponding @cpp pixelFormatSize(T, U) @ce
* overload, then calls @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* overload, then calls @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* with calculated pixel size.
*/
template<class T, class U> explicit ImageData(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
template<class T, class U> explicit ImageData(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
template<class T, class U> explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{storage, format, formatExtra, size, std::move(data), {}, importerState} {}
#endif
/**
* @brief Construct a non-owned uncompressed image data with implementation-specific pixel format
@ -257,16 +351,26 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size
* @param dataFlags Data flags
* @param data View on image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since{2020,06}
* @m_since_latest
*
* Compared to @ref ImageData(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Compared to @ref ImageData(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* creates an instance that doesn't own the passed data. The
* @p dataFlags parameter can contain @ref DataFlag::Mutable to
* indicate the external data can be modified, and is expected to *not*
* have @ref DataFlag::Owned set.
*/
template<class T, class U> explicit ImageData(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
template<class T, class U> explicit ImageData(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
template<class T, class U> explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{storage, format, formatExtra, size, dataFlags, data, {}, importerState} {}
#endif
/**
* @brief Construct an uncompressed image data with implementation-specific pixel format
@ -274,13 +378,24 @@ template<UnsignedInt dimensions> class ImageData {
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since_latest
*
* Uses ADL to find a corresponding @cpp pixelFormatSize(T) @ce
* overload, then calls @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* overload, then calls @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*/
template<class T> explicit ImageData(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
template<class T> explicit ImageData(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
template<class T> explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{storage, format, size, std::move(data), {}, importerState} {}
#endif
/**
* @brief Construct a non-owned uncompressed image data with implementation-specific pixel format
@ -289,16 +404,26 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size
* @param dataFlags Data flags
* @param data view on image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since{2020,06}
* @m_since_latest
*
* Compared to @ref ImageData(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Compared to @ref ImageData(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* creates an instance that doesn't own the passed data. The
* @p dataFlags parameter can contain @ref DataFlag::Mutable to
* indicate the external data can be modified, and is expected to *not*
* have @ref DataFlag::Owned set.
*/
template<class T> explicit ImageData(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
template<class T> explicit ImageData(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
template<class T> explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{storage, format, size, dataFlags, data, {}, importerState} {}
#endif
/**
* @brief Construct a compressed image data
@ -306,9 +431,20 @@ template<UnsignedInt dimensions> class ImageData {
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since_latest
*/
explicit ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
explicit ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{storage, format, size, std::move(data), {}, importerState} {}
#endif
/**
* @brief Construct a non-owned compressed image data
@ -317,28 +453,49 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size
* @param dataFlags Data flags
* @param data View on image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since{2020,06}
* @m_since_latest
*
* Compared to @ref ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Compared to @ref ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* creates an instance that doesn't own the passed data. The
* @p dataFlags parameter can contain @ref DataFlag::Mutable to
* indicate the external data can be modified, and is expected to *not*
* have @ref DataFlag::Owned set.
*/
explicit ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
explicit ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{storage, format, size, dataFlags, data, {}, importerState} {}
#endif
/**
* @brief Construct a compressed image data
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since_latest
*
* Equivalent to calling @ref ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Equivalent to calling @ref ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* with default-constructed @ref CompressedPixelStorage.
*/
explicit ImageData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
explicit ImageData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{format, size, std::move(data), {}, importerState} {}
#endif
/**
* @brief Construct a non-owned compressed image data
@ -346,16 +503,26 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size
* @param dataFlags Data flags
* @param data View on image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since{2020,06}
* @m_since_latest
*
* Compared to @ref ImageData(CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Compared to @ref ImageData(CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* creates an instance that doesn't own the passed data. The
* @p dataFlags parameter can contain @ref DataFlag::Mutable to
* indicate the external data can be modified, and is expected to *not*
* have @ref DataFlag::Owned set.
*/
explicit ImageData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
explicit ImageData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{format, size, dataFlags, data, {}, importerState} {}
#endif
/**
* @brief Construct a compressed image data
@ -363,12 +530,26 @@ template<UnsignedInt dimensions> class ImageData {
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since_latest
*
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat.
*
* For a 3D image, if @p flags contain @ref ImageFlag3D::CubeMap, the
* @p size is expected to match its restrictions.
*/
template<class T> explicit ImageData(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* instead.
*/
template<class T> explicit ImageData(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
template<class T> explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: ImageData{storage, format, size, std::move(data), {}, importerState} {}
#endif
/**
* @brief Construct a non-owned compressed image data
@ -377,16 +558,26 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size
* @param dataFlags Data flags
* @param data View on image data
* @param flags Image layout flags
* @param importerState Importer-specific state
* @m_since{2020,06}
* @m_since_latest
*
* Compared to @ref ImageData(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* Compared to @ref ImageData(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, ImageFlags<dimensions>, const void*)
* creates an instance that doesn't own the passed data. The
* @p dataFlags parameter can contain @ref DataFlag::Mutable to
* indicate the external data can be modified, and is expected to *not*
* have @ref DataFlag::Owned set.
*/
template<class T> explicit ImageData(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
template<class T> explicit ImageData(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags = {}, const void* importerState = nullptr) noexcept;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief ImageData(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* @m_deprecated_since_latest Use @ref ImageData(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, DataFlags, Containers::ArrayView<const void>, ImageFlags<dimensions>, const void*)
* instead.
*/
template<class T> explicit CORRADE_DEPRECATED("use a constructor with an extra ImageFlags argument instead") ImageData(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState) noexcept: ImageData{storage, format, size, dataFlags, data, {}, importerState} {}
#endif
/**
* @brief Construct from existing data with attached importer state
@ -458,6 +649,12 @@ template<UnsignedInt dimensions> class ImageData {
*/
/*implicit*/ operator BasicMutableCompressedImageView<dimensions>();
/**
* @brief Layout flags
* @m_since_latest
*/
ImageFlags<dimensions> flags() const { return _flags; }
/**
* @brief Storage of pixel data
*
@ -677,12 +874,13 @@ template<UnsignedInt dimensions> class ImageData {
friend AbstractImporter;
friend AbstractImageConverter;
explicit ImageData(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
explicit ImageData(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, ImageFlags<dimensions> flags, const void* importerState = nullptr) noexcept;
explicit ImageData(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, const void* importerState = nullptr) noexcept;
explicit ImageData(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, DataFlags dataFlags, Containers::ArrayView<const void> data, ImageFlags<dimensions> flags, const void* importerState = nullptr) noexcept;
DataFlags _dataFlags;
bool _compressed;
ImageFlags<dimensions> _flags;
union {
PixelStorage _storage;
CompressedPixelStorage _compressedStorage;
@ -707,32 +905,32 @@ typedef ImageData<2> ImageData2D;
/** @brief Three-dimensional image data */
typedef ImageData<3> ImageData3D;
template<UnsignedInt dimensions> template<class T, class U> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), UnsignedInt(formatExtra), Magnum::Implementation::pixelFormatSizeAdl(format, formatExtra), size, std::move(data), importerState} {
template<UnsignedInt dimensions> template<class T, class U> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), UnsignedInt(formatExtra), Magnum::Implementation::pixelFormatSizeAdl(format, formatExtra), size, std::move(data), flags, importerState} {
static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T, class U> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), UnsignedInt(formatExtra), Magnum::Implementation::pixelFormatSizeAdl(format, formatExtra), size, dataFlags, data, importerState} {
template<UnsignedInt dimensions> template<class T, class U> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), UnsignedInt(formatExtra), Magnum::Implementation::pixelFormatSizeAdl(format, formatExtra), size, dataFlags, data, flags, importerState} {
static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), {}, Magnum::Implementation::pixelFormatSizeAdl(format), size, std::move(data), importerState} {
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), {}, Magnum::Implementation::pixelFormatSizeAdl(format), size, std::move(data), flags, importerState} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), {}, Magnum::Implementation::pixelFormatSizeAdl(format), size, dataFlags, data, importerState} {
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), {}, Magnum::Implementation::pixelFormatSizeAdl(format), size, dataFlags, data, flags, importerState} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), size, std::move(data), importerState} {
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), size, std::move(data), flags, importerState} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), size, dataFlags, data, importerState} {
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const ImageFlags<dimensions> flags, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), size, dataFlags, data, flags, importerState} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}

6
src/Magnum/Trade/Test/AbstractImporterTest.cpp

@ -6980,7 +6980,7 @@ void AbstractImporterTest::image1D() {
return {};
}
Containers::Optional<ImageData1D> doImage1D(UnsignedInt id, UnsignedInt level) override {
if(id == 7 && level == 2) return ImageData1D{PixelFormat::RGBA8Unorm, {}, {}, &state};
if(id == 7 && level == 2) return ImageData1D{PixelFormat::RGBA8Unorm, {}, {}, ImageFlags1D{}, &state};
return {};
}
} importer;
@ -7302,7 +7302,7 @@ void AbstractImporterTest::image2D() {
return {};
}
Containers::Optional<ImageData2D> doImage2D(UnsignedInt id, UnsignedInt level) override {
if(id == 7 && level == 2) return ImageData2D{PixelFormat::RGBA8Unorm, {}, {}, &state};
if(id == 7 && level == 2) return ImageData2D{PixelFormat::RGBA8Unorm, {}, {}, ImageFlags2D{}, &state};
return {};
}
} importer;
@ -7624,7 +7624,7 @@ void AbstractImporterTest::image3D() {
return {};
}
Containers::Optional<ImageData3D> doImage3D(UnsignedInt id, UnsignedInt level) override {
if(id == 7 && level == 2) return ImageData3D{PixelFormat::RGBA8Unorm, {}, {}, &state};
if(id == 7 && level == 2) return ImageData3D{PixelFormat::RGBA8Unorm, {}, {}, ImageFlags3D{}, &state};
return {};
}
} importer;

122
src/Magnum/Trade/Test/ImageDataTest.cpp

@ -57,7 +57,9 @@ struct ImageDataTest: TestSuite::Tester {
void constructCompressedImplementationSpecificNotOwnedFlagOwned();
void constructInvalidSize();
void constructInvalidCubeMap();
void constructCompressedInvalidSize();
void constructCompressedInvalidCubeMap();
void constructCopy();
@ -127,7 +129,9 @@ ImageDataTest::ImageDataTest() {
&ImageDataTest::constructCompressedImplementationSpecificNotOwnedFlagOwned,
&ImageDataTest::constructInvalidSize,
&ImageDataTest::constructInvalidCubeMap,
&ImageDataTest::constructCompressedInvalidSize,
&ImageDataTest::constructCompressedInvalidCubeMap,
&ImageDataTest::constructCopy,
@ -202,10 +206,11 @@ void ImageDataTest::constructGeneric() {
{
auto data = new char[4*4];
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{PixelFormat::RGBA8Unorm, {1, 3}, Containers::Array<char>{data, 4*4}, &state};
ImageData2D a{PixelFormat::RGBA8Unorm, {1, 3}, Containers::Array<char>{data, 4*4}, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RGBA8Unorm);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -222,10 +227,11 @@ void ImageDataTest::constructGeneric() {
auto data = new char[3*2];
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{PixelStorage{}.setAlignment(1),
PixelFormat::R16UI, {1, 3}, Containers::Array<char>{data, 3*2}, &state};
PixelFormat::R16UI, {1, 3}, Containers::Array<char>{data, 3*2}, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::R16UI);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -247,10 +253,11 @@ void ImageDataTest::constructImplementationSpecific() {
auto data = new char[3*12];
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array<char>{data, 3*12}, &state};
Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array<char>{data, 3*12}, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -270,10 +277,11 @@ void ImageDataTest::constructImplementationSpecific() {
auto data = new char[3*6];
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, &state};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
@ -291,10 +299,11 @@ void ImageDataTest::constructImplementationSpecific() {
{
auto data = new char[3*6];
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, Containers::Array<char>{data, 3*6}, &state};
ImageData2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -315,10 +324,11 @@ void ImageDataTest::constructCompressedGeneric() {
auto data = new char[8];
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4},
Containers::Array<char>{data, 8}, &state};
Containers::Array<char>{data, 8}, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.compressedFormat(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -332,10 +342,11 @@ void ImageDataTest::constructCompressedGeneric() {
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBAUnorm, {4, 4},
Containers::Array<char>{data, 8}, &state};
Containers::Array<char>{data, 8}, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.compressedFormat(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), Vector2i(4, 4));
@ -354,10 +365,11 @@ void ImageDataTest::constructCompressedImplementationSpecific() {
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4},
Containers::Array<char>{data, 8}, &state};
Containers::Array<char>{data, 8}, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.compressedFormat(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -378,10 +390,11 @@ void ImageDataTest::constructGenericNotOwned() {
{
char data[4*4];
int state;
ImageData2D a{PixelFormat::RGBA8Unorm, {1, 3}, instanceData.dataFlags, data, &state};
ImageData2D a{PixelFormat::RGBA8Unorm, {1, 3}, instanceData.dataFlags, data, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), instanceData.dataFlags);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RGBA8Unorm);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -400,10 +413,11 @@ void ImageDataTest::constructGenericNotOwned() {
char data[3*2];
int state;
ImageData2D a{PixelStorage{}.setAlignment(1),
PixelFormat::R16UI, {1, 3}, instanceData.dataFlags, data, &state};
PixelFormat::R16UI, {1, 3}, instanceData.dataFlags, data, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), instanceData.dataFlags);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::R16UI);
CORRADE_COMPARE(a.formatExtra(), 0);
@ -430,10 +444,11 @@ void ImageDataTest::constructImplementationSpecificNotOwned() {
char data[3*12];
int state;
ImageData2D a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F, {1, 3}, instanceData.dataFlags, data, &state};
Vk::PixelFormat::R32G32B32F, {1, 3}, instanceData.dataFlags, data, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), instanceData.dataFlags);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
@ -455,10 +470,11 @@ void ImageDataTest::constructImplementationSpecificNotOwned() {
char data[3*6];
int state;
ImageData2D a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, instanceData.dataFlags, data, &state};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, instanceData.dataFlags, data, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), instanceData.dataFlags);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
@ -478,10 +494,11 @@ void ImageDataTest::constructImplementationSpecificNotOwned() {
{
char data[3*6];
int state;
ImageData2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, instanceData.dataFlags, data, &state};
ImageData2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, instanceData.dataFlags, data, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), instanceData.dataFlags);
CORRADE_VERIFY(!a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
@ -507,10 +524,11 @@ void ImageDataTest::constructCompressedGenericNotOwned() {
char data[8];
int state;
ImageData2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4},
instanceData.dataFlags, data, &state};
instanceData.dataFlags, data, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), instanceData.dataFlags);
CORRADE_VERIFY(a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.compressedFormat(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -526,10 +544,11 @@ void ImageDataTest::constructCompressedGenericNotOwned() {
int state;
ImageData2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBAUnorm, {4, 4},
instanceData.dataFlags, data, &state};
instanceData.dataFlags, data, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), instanceData.dataFlags);
CORRADE_VERIFY(a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.compressedFormat(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), Vector2i(4, 4));
@ -553,10 +572,11 @@ void ImageDataTest::constructCompressedImplementationSpecificNotOwned() {
int state;
ImageData2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4},
instanceData.dataFlags, data, &state};
instanceData.dataFlags, data, ImageFlag2D::Array, &state};
CORRADE_COMPARE(a.dataFlags(), instanceData.dataFlags);
CORRADE_VERIFY(a.isCompressed());
CORRADE_COMPARE(a.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.compressedFormat(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
@ -649,6 +669,24 @@ void ImageDataTest::constructInvalidSize() {
CORRADE_COMPARE(out.str(), "Trade::ImageData: data too small, got 9 but expected at least 12 bytes\n");
}
void ImageDataTest::constructInvalidCubeMap() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
std::ostringstream out;
Error redirectError{&out};
ImageData3D{PixelFormat::RGBA8Unorm, {3, 3, 5}, Containers::Array<char>{3*3*5*4}, ImageFlag3D::CubeMap};
ImageData3D{PixelFormat::RGBA8Unorm, {3, 4, 6}, Containers::Array<char>{3*4*6*4}, ImageFlag3D::CubeMap};
ImageData3D{PixelFormat::RGBA8Unorm, {3, 3, 17}, Containers::Array<char>{3*3*17*4}, ImageFlag3D::CubeMap |ImageFlag3D::Array};
ImageData3D{PixelFormat::RGBA8Unorm, {4, 3, 18}, Containers::Array<char>{4*3*18*4}, ImageFlag3D::CubeMap |ImageFlag3D::Array};
CORRADE_COMPARE(out.str(),
"Trade::ImageData: expected exactly 6 faces for a cube map, got 5\n"
"Trade::ImageData: expected square faces for a cube map, got {3, 4}\n"
"Trade::ImageData: expected a multiple of 6 faces for a cube map array, got 17\n"
"Trade::ImageData: expected square faces for a cube map, got {4, 3}\n");
}
void ImageDataTest::constructCompressedInvalidSize() {
CORRADE_EXPECT_FAIL("Size checking for compressed image data is not implemented yet.");
@ -668,6 +706,24 @@ void ImageDataTest::constructCompressedInvalidSize() {
}
}
void ImageDataTest::constructCompressedInvalidCubeMap() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
std::ostringstream out;
Error redirectError{&out};
ImageData3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 3, 5}, Containers::Array<char>{8*5}, ImageFlag3D::CubeMap};
ImageData3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 4, 6}, Containers::Array<char>{8*6}, ImageFlag3D::CubeMap};
ImageData3D{CompressedPixelFormat::Bc1RGBAUnorm, {3, 3, 17}, Containers::Array<char>{8*17}, ImageFlag3D::CubeMap |ImageFlag3D::Array};
ImageData3D{CompressedPixelFormat::Bc1RGBAUnorm, {4, 3, 18}, Containers::Array<char>{8*18}, ImageFlag3D::CubeMap |ImageFlag3D::Array};
CORRADE_COMPARE(out.str(),
"Trade::ImageData: expected exactly 6 faces for a cube map, got 5\n"
"Trade::ImageData: expected square faces for a cube map, got {3, 4}\n"
"Trade::ImageData: expected a multiple of 6 faces for a cube map array, got 17\n"
"Trade::ImageData: expected square faces for a cube map, got {4, 3}\n");
}
void ImageDataTest::constructCopy() {
CORRADE_VERIFY(!std::is_copy_constructible<ImageData2D>{});
CORRADE_VERIFY(!std::is_copy_assignable<ImageData2D>{});
@ -677,7 +733,7 @@ void ImageDataTest::constructMoveGeneric() {
auto data = new char[3*16];
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{PixelStorage{}.setAlignment(1),
PixelFormat::RGBA32F, {1, 3}, Containers::Array<char>{data, 3*16}, &state};
PixelFormat::RGBA32F, {1, 3}, Containers::Array<char>{data, 3*16}, ImageFlag2D::Array, &state};
ImageData2D b(std::move(a));
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
@ -685,6 +741,7 @@ void ImageDataTest::constructMoveGeneric() {
CORRADE_COMPARE(b.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!b.isCompressed());
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), PixelFormat::RGBA32F);
CORRADE_COMPARE(b.formatExtra(), 0);
@ -703,6 +760,7 @@ void ImageDataTest::constructMoveGeneric() {
CORRADE_COMPARE(c.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!c.isCompressed());
CORRADE_COMPARE(c.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(c.storage().alignment(), 1);
CORRADE_COMPARE(c.format(), PixelFormat::RGBA32F);
CORRADE_COMPARE(c.formatExtra(), 0);
@ -720,7 +778,7 @@ void ImageDataTest::constructMoveImplementationSpecific() {
auto data = new char[3*6];
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, &state};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array, &state};
ImageData2D b(std::move(a));
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
@ -728,6 +786,7 @@ void ImageDataTest::constructMoveImplementationSpecific() {
CORRADE_COMPARE(b.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!b.isCompressed());
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), 1337);
@ -747,6 +806,7 @@ void ImageDataTest::constructMoveImplementationSpecific() {
CORRADE_COMPARE(c.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!c.isCompressed());
CORRADE_COMPARE(c.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(c.storage().alignment(), 1);
CORRADE_COMPARE(c.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(c.formatExtra(), 1337);
@ -762,7 +822,7 @@ void ImageDataTest::constructMoveCompressedGeneric() {
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc3RGBAUnorm, {4, 4}, Containers::Array<char>{data, 8}, &state};
CompressedPixelFormat::Bc3RGBAUnorm, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array, &state};
ImageData2D b{std::move(a)};
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
@ -770,6 +830,7 @@ void ImageDataTest::constructMoveCompressedGeneric() {
CORRADE_COMPARE(b.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(b.isCompressed());
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.compressedFormat(), CompressedPixelFormat::Bc3RGBAUnorm);
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
@ -786,6 +847,7 @@ void ImageDataTest::constructMoveCompressedGeneric() {
CORRADE_COMPARE(c.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(c.isCompressed());
CORRADE_COMPARE(c.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(c.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(c.compressedFormat(), CompressedPixelFormat::Bc3RGBAUnorm);
CORRADE_COMPARE(c.size(), (Vector2i{4, 4}));
@ -799,7 +861,7 @@ void ImageDataTest::constructMoveCompressedImplementationSpecific() {
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
ImageData2D a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}, &state};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array, &state};
ImageData2D b{std::move(a)};
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
@ -807,6 +869,7 @@ void ImageDataTest::constructMoveCompressedImplementationSpecific() {
CORRADE_COMPARE(b.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(b.isCompressed());
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.compressedFormat(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
@ -823,6 +886,7 @@ void ImageDataTest::constructMoveCompressedImplementationSpecific() {
CORRADE_COMPARE(c.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(c.isCompressed());
CORRADE_COMPARE(c.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(c.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(c.compressedFormat(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(c.size(), (Vector2i{4, 4}));
@ -836,7 +900,7 @@ void ImageDataTest::constructMoveAttachState() {
/* GCC 11 pointlessly complains that "maybe uninitialized" w/o the {} */
int stateOld{}, stateNew{};
ImageData2D a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, &stateOld};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array, &stateOld};
ImageData2D b{std::move(a), &stateNew};
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
@ -844,6 +908,7 @@ void ImageDataTest::constructMoveAttachState() {
CORRADE_COMPARE(b.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(!b.isCompressed());
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), 1337);
@ -860,7 +925,7 @@ void ImageDataTest::constructMoveCompressedAttachState() {
int stateOld{}, stateNew{};
ImageData2D a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}, &stateOld};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array, &stateOld};
ImageData2D b{std::move(a), &stateNew};
CORRADE_COMPARE(a.data(), static_cast<const void*>(nullptr));
@ -868,6 +933,7 @@ void ImageDataTest::constructMoveCompressedAttachState() {
CORRADE_COMPARE(b.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_VERIFY(b.isCompressed());
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.compressedStorage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.compressedFormat(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
@ -881,9 +947,10 @@ template<class T> void ImageDataTest::toViewGeneric() {
auto data = new char[3*4];
typename MutabilityTraits<T>::ImageType a{PixelStorage{}.setAlignment(1),
PixelFormat::RG16I, {1, 3}, Containers::Array<char>{data, 3*4}};
PixelFormat::RG16I, {1, 3}, Containers::Array<char>{data, 3*4}, ImageFlag2D::Array};
ImageView<2, T> b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), PixelFormat::RG16I);
CORRADE_COMPARE(b.formatExtra(), 0);
@ -897,9 +964,10 @@ template<class T> void ImageDataTest::toViewImplementationSpecific() {
auto data = new char[3*6];
typename MutabilityTraits<T>::ImageType a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}};
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}, ImageFlag2D::Array};
ImageView<2, T> b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), 1337);
@ -914,9 +982,10 @@ template<class T> void ImageDataTest::toViewCompressedGeneric() {
auto data = new char[8];
typename MutabilityTraits<T>::ImageType a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBUnorm, {4, 4}, Containers::Array<char>{data, 8}};
CompressedPixelFormat::Bc1RGBUnorm, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CompressedImageView<2, T> b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), CompressedPixelFormat::Bc1RGBUnorm);
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
@ -930,9 +999,10 @@ template<class T> void ImageDataTest::toViewCompressedImplementationSpecific() {
auto data = new char[8];
typename MutabilityTraits<T>::ImageType a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}};
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}, ImageFlag2D::Array};
CompressedImageView<2, T> b = a;
CORRADE_COMPARE(b.flags(), ImageFlag2D::Array);
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));

Loading…
Cancel
Save