Browse Source

New Mutable[Compressed]ImageView types for non-const image data views.

pull/362/head
Vladimír Vondruš 7 years ago
parent
commit
41b975cb69
  1. 3
      doc/changelog.dox
  2. 8
      src/Magnum/GL/Texture.h
  3. 8
      src/Magnum/GL/TextureArray.h
  4. 28
      src/Magnum/Image.h
  5. 48
      src/Magnum/ImageView.cpp
  6. 294
      src/Magnum/ImageView.h
  7. 24
      src/Magnum/Magnum.h
  8. 66
      src/Magnum/Test/ImageTest.cpp
  9. 328
      src/Magnum/Test/ImageViewTest.cpp
  10. 26
      src/Magnum/Trade/ImageData.cpp
  11. 8
      src/Magnum/Trade/ImageData.h
  12. 64
      src/Magnum/Trade/Test/ImageDataTest.cpp

3
doc/changelog.dox

@ -46,6 +46,9 @@ See also:
- New @ref Image::pixels(), @ref ImageView::pixels() and
@ref Trade::ImageData::pixels() accessors for convenient direct access to
pixel data of any image
- New @ref MutableImageView2D "MutableImageView*D" and
@ref CompressedMutableImageView2D "CompressedMutableImageView*D" types for
mutable views onto image data
@subsubsection changelog-latest-new-audio Audio library

8
src/Magnum/GL/Texture.h

@ -1037,7 +1037,7 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* @deprecated_gl Prefer to use @ref setStorage() and @ref setSubImage()
* instead.
*/
Texture<dimensions>& setImage(Int level, TextureFormat internalFormat, const ImageView<dimensions>& image) {
Texture<dimensions>& setImage(Int level, TextureFormat internalFormat, const ImageView<dimensions, const char>& image) {
DataHelper<dimensions>::setImage(*this, level, internalFormat, image);
return *this;
}
@ -1093,7 +1093,7 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* @deprecated_gl Prefer to use @ref setStorage() and
* @ref setCompressedSubImage() instead.
*/
Texture<dimensions>& setCompressedImage(Int level, const CompressedImageView<dimensions>& image) {
Texture<dimensions>& setCompressedImage(Int level, const CompressedImageView<dimensions, const char>& image) {
DataHelper<dimensions>::setCompressedImage(*this, level, image);
return *this;
}
@ -1167,7 +1167,7 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* able to use @ref setStorage() as it uses implicit @ref PixelType
* value.
*/
Texture<dimensions>& setSubImage(Int level, const VectorTypeFor<dimensions, Int>& offset, const ImageView<dimensions>& image) {
Texture<dimensions>& setSubImage(Int level, const VectorTypeFor<dimensions, Int>& offset, const ImageView<dimensions, const char>& image) {
DataHelper<Dimensions>::setSubImage(*this, level, offset, image);
return *this;
}
@ -1219,7 +1219,7 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* @requires_gl Non-default @ref CompressedPixelStorage is not
* available in OpenGL ES and WebGL.
*/
Texture<dimensions>& setCompressedSubImage(Int level, const VectorTypeFor<dimensions, Int>& offset, const CompressedImageView<dimensions>& image) {
Texture<dimensions>& setCompressedSubImage(Int level, const VectorTypeFor<dimensions, Int>& offset, const CompressedImageView<dimensions, const char>& image) {
DataHelper<Dimensions>::setCompressedSubImage(*this, level, offset, image);
return *this;
}

8
src/Magnum/GL/TextureArray.h

@ -699,7 +699,7 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
* @deprecated_gl Prefer to use @ref setStorage() and @ref setSubImage()
* instead.
*/
TextureArray<dimensions>& setImage(Int level, TextureFormat internalFormat, const ImageView<dimensions+1>& image) {
TextureArray<dimensions>& setImage(Int level, TextureFormat internalFormat, const ImageView<dimensions+1, const char>& image) {
DataHelper<dimensions+1>::setImage(*this, level, internalFormat, image);
return *this;
}
@ -734,7 +734,7 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
* @deprecated_gl Prefer to use @ref setStorage() and
* @ref setCompressedSubImage() instead.
*/
TextureArray<dimensions>& setCompressedImage(Int level, const CompressedImageView<dimensions+1>& image) {
TextureArray<dimensions>& setCompressedImage(Int level, const CompressedImageView<dimensions+1, const char>& image) {
DataHelper<dimensions+1>::setCompressedImage(*this, level, image);
return *this;
}
@ -781,7 +781,7 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
* eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl_keyword{TexSubImage2D} / @fn_gl_keyword{TexSubImage3D}
*/
TextureArray<dimensions>& setSubImage(Int level, const VectorTypeFor<dimensions+1, Int>& offset, const ImageView<dimensions+1>& image) {
TextureArray<dimensions>& setSubImage(Int level, const VectorTypeFor<dimensions+1, Int>& offset, const ImageView<dimensions+1, const char>& image) {
DataHelper<dimensions+1>::setSubImage(*this, level, offset, image);
return *this;
}
@ -818,7 +818,7 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
* @requires_gl Non-default @ref CompressedPixelStorage is not
* available in OpenGL ES and WebGL.
*/
TextureArray<dimensions>& setCompressedSubImage(Int level, const VectorTypeFor<dimensions+1, Int>& offset, const CompressedImageView<dimensions+1>& image) {
TextureArray<dimensions>& setCompressedSubImage(Int level, const VectorTypeFor<dimensions+1, Int>& offset, const CompressedImageView<dimensions+1, const char>& image) {
DataHelper<dimensions+1>::setCompressedSubImage(*this, level, offset, image);
return *this;
}

28
src/Magnum/Image.h

@ -307,7 +307,9 @@ template<UnsignedInt dimensions> class Image {
/** @brief Conversion to view */
/* Not restricted to const&, because we might want to pass the view to
another function in an oneliner (e.g. saving screenshot) */
/*implicit*/ operator ImageView<dimensions>() const;
/*implicit*/ operator ImageView<dimensions, char>();
/** @overload */
/*implicit*/ operator ImageView<dimensions, const char>() const;
/** @brief Storage of pixel data */
PixelStorage storage() const { return _storage; }
@ -566,7 +568,11 @@ template<UnsignedInt dimensions> class CompressedImage {
CompressedImage<dimensions>& operator=(CompressedImage<dimensions>&& other) noexcept;
/** @brief Conversion to view */
/*implicit*/ operator CompressedImageView<dimensions>() const;
/* Not restricted to const&, because we might want to pass the view to
another function in an oneliner (e.g. saving screenshot) */
/*implicit*/ operator CompressedImageView<dimensions, char>();
/** @overload */
/*implicit*/ operator CompressedImageView<dimensions, const char>() const;
/** @brief Storage of compressed pixel data */
CompressedPixelStorage storage() const { return _storage; }
@ -700,14 +706,20 @@ template<UnsignedInt dimensions> inline CompressedImage<dimensions>& CompressedI
return *this;
}
template<UnsignedInt dimensions> inline Image<dimensions>::operator ImageView<dimensions>() const
{
return ImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
template<UnsignedInt dimensions> inline Image<dimensions>::operator ImageView<dimensions, char>() {
return ImageView<dimensions, char>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
}
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::operator CompressedImageView<dimensions>() const
{
return CompressedImageView<dimensions>{_storage, _format, _size, _data};
template<UnsignedInt dimensions> inline Image<dimensions>::operator ImageView<dimensions, const char>() const {
return ImageView<dimensions, const char>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
}
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::operator CompressedImageView<dimensions, char>() {
return CompressedImageView<dimensions, char>{_storage, _format, _size, _data};
}
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::operator CompressedImageView<dimensions, const char>() const {
return CompressedImageView<dimensions, const char>{_storage, _format, _size, _data};
}
template<UnsignedInt dimensions> inline Containers::Array<char> Image<dimensions>::release() {

48
src/Magnum/ImageView.cpp

@ -30,45 +30,51 @@
namespace Magnum {
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: ImageView{storage, format, {}, Magnum::pixelSize(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) noexcept: ImageView{storage, format, {}, Magnum::pixelSize(format), size, data} {}
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> 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) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, data} {}
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{reinterpret_cast<const char*>(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) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{reinterpret_cast<Type*>(data.data()), data.size()} {
CORRADE_ASSERT(!_data || Implementation::imageDataSize(*this) <= _data.size(), "ImageView::ImageView(): data too small, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this) << "bytes", );
}
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, format, {}, Magnum::pixelSize(format), size} {}
template<UnsignedInt dimensions, class T> ImageView<dimensions, T>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, format, {}, Magnum::pixelSize(format), size} {}
template<UnsignedInt dimensions> ImageView<dimensions>::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) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size} {}
template<UnsignedInt dimensions> ImageView<dimensions>::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) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{nullptr} {}
template<UnsignedInt dimensions> void ImageView<dimensions>::setData(const Containers::ArrayView<const void> data) {
template<UnsignedInt dimensions, class T> void ImageView<dimensions, T>::setData(const Containers::ArrayView<ErasedType> data) {
CORRADE_ASSERT(Implementation::imageDataSize(*this) <= data.size(), "ImageView::setData(): data too small, got" << data.size() << "but expected at least" << Implementation::imageDataSize(*this) << "bytes", );
_data = {reinterpret_cast<const char*>(data.data()), data.size()};
_data = {reinterpret_cast<Type*>(data.data()), data.size()};
}
template<UnsignedInt dimensions> Containers::StridedArrayView<dimensions + 1, const char> ImageView<dimensions>::pixels() const {
return Implementation::imagePixelView<dimensions, const char>(*this);
template<UnsignedInt dimensions, class T> auto ImageView<dimensions, T>::pixels() const -> Containers::StridedArrayView<dimensions + 1, Type> {
return Implementation::imagePixelView<dimensions, Type>(*this);
}
template<UnsignedInt dimensions> CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: _storage{storage}, _format{format}, _size{size}, _data{reinterpret_cast<const char*>(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) noexcept: _storage{storage}, _format{format}, _size{size}, _data{reinterpret_cast<Type*>(data.data()), data.size()} {}
template<UnsignedInt dimensions> CompressedImageView<dimensions>::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) noexcept: _storage{storage}, _format{format}, _size{size} {}
template<UnsignedInt dimensions> CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> 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) noexcept: CompressedImageView{storage, compressedPixelFormatWrap(format), size, data} {}
template<UnsignedInt dimensions> CompressedImageView<dimensions>::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) noexcept: CompressedImageView{storage, compressedPixelFormatWrap(format), size} {}
#ifndef DOXYGEN_GENERATING_OUTPUT
template class MAGNUM_EXPORT ImageView<1>;
template class MAGNUM_EXPORT ImageView<2>;
template class MAGNUM_EXPORT ImageView<3>;
template class MAGNUM_EXPORT CompressedImageView<1>;
template class MAGNUM_EXPORT CompressedImageView<2>;
template class MAGNUM_EXPORT CompressedImageView<3>;
template class MAGNUM_EXPORT ImageView<1, const char>;
template class MAGNUM_EXPORT ImageView<2, const char>;
template class MAGNUM_EXPORT ImageView<3, const char>;
template class MAGNUM_EXPORT ImageView<1, char>;
template class MAGNUM_EXPORT ImageView<2, char>;
template class MAGNUM_EXPORT ImageView<3, char>;
template class MAGNUM_EXPORT CompressedImageView<1, const char>;
template class MAGNUM_EXPORT CompressedImageView<2, const char>;
template class MAGNUM_EXPORT CompressedImageView<3, const char>;
template class MAGNUM_EXPORT CompressedImageView<1, char>;
template class MAGNUM_EXPORT CompressedImageView<2, char>;
template class MAGNUM_EXPORT CompressedImageView<3, char>;
#endif
}

294
src/Magnum/ImageView.h

@ -26,7 +26,7 @@
*/
/** @file
* @brief Class @ref Magnum::ImageView, @ref Magnum::CompressedImageView, typedef @ref Magnum::ImageView1D, @ref Magnum::ImageView2D, @ref Magnum::ImageView3D, @ref Magnum::CompressedImageView1D, @ref Magnum::CompressedImageView2D, @ref Magnum::CompressedImageView3D
* @brief Class @ref Magnum::ImageView, @ref Magnum::CompressedImageView, typedef @ref Magnum::ImageView1D, @ref Magnum::ImageView2D, @ref Magnum::ImageView3D, @ref Magnum::MutableImageView1D, @ref Magnum::MutableImageView2D, @ref Magnum::MutableImageView3D, @ref Magnum::CompressedImageView1D, @ref Magnum::CompressedImageView2D, @ref Magnum::CompressedImageView3D, @ref Magnum::MutableCompressedImageView1D, @ref Magnum::MutableCompressedImageView2D, @ref Magnum::MutableCompressedImageView3D
*/
#include <Corrade/Containers/ArrayView.h>
@ -78,6 +78,16 @@ sub-rectangle of a 75x75 8-bit RGB image , with rows aligned to four bytes:
@snippet Magnum.cpp ImageView-usage-storage
@section ImageView-mutable Data mutability
When using e.g. the @ref ImageView2D typedef, the viewed data are immutable.
This is the most common use case, in order to be able to mutate the underlying
data (for example in order to read into a pre-allocated memory), use
@ref MutableImageView2D and friends instead. @ref Image and
@ref Trade::ImageData are convertible to either of these. Similarly to
@ref Corrade::Containers::ArrayView etc., a mutable view is also implicitly
convertible to a const one.
@subsection ImageView-usage-implementation-specific Implementation-specific formats
For known graphics APIs, there's a set of utility functions converting from
@ -114,10 +124,35 @@ Metal-specific format identifier:
@snippet Magnum.cpp ImageView-usage-metal
@see @ref ImageView1D, @ref ImageView2D, @ref ImageView3D,
@ref MutableImageView1D, @ref MutableImageView2D, @ref MutableImageView3D,
@ref Image-pixel-views
*/
template<UnsignedInt dimensions> class ImageView {
template<UnsignedInt dimensions, class T> class ImageView {
public:
/* Pointer arithmetic relies on the type being a single byte */
static_assert(std::is_same<T, char>::value ||std::is_same<T, const char>::value,
"image view type can be either char or const char");
/**
* @brief Raw data type
*
* @cpp const char @ce for @ref ImageView1D / @ref ImageView2D /
* @ref ImageView3D and @cpp char @ce for @ref MutableImageView1D /
* @ref MutableImageView2D / @ref MutableImageView3D. See also
* @ref ErasedType.
*/
typedef T Type;
/**
* @brief Erased data type
*
* @cpp const void @ce for @ref ImageView1D / @ref ImageView2D /
* @ref ImageView3D and @cpp const void @ce for @ref MutableImageView1D
* / @ref MutableImageView2D / @ref MutableImageView3D. See also
* @ref Type.
*/
typedef typename std::conditional<std::is_const<T>::value, const void, void>::type ErasedType;
enum: UnsignedInt {
Dimensions = dimensions /**< Image dimension count */
};
@ -132,7 +167,7 @@ template<UnsignedInt dimensions> class ImageView {
* The @p data array is expected to be of proper size for given
* parameters.
*/
explicit ImageView(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
explicit ImageView(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
/**
* @brief Constructor
@ -140,10 +175,10 @@ template<UnsignedInt dimensions> class ImageView {
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* Equivalent to calling @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* with default-constructed @ref PixelStorage.
*/
explicit ImageView(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: ImageView{{}, format, size, data} {}
explicit ImageView(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: ImageView{{}, format, size, data} {}
/**
* @brief Construct an empty view
@ -175,7 +210,7 @@ template<UnsignedInt dimensions> class ImageView {
* @param size Image size
* @param data Image data
*
* Unlike with @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>),
* Unlike with @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>),
* where pixel size is calculated automatically using
* @ref pixelSize(PixelFormat), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
@ -185,14 +220,14 @@ template<UnsignedInt dimensions> class ImageView {
* The @p data array is expected to be of proper size for given
* parameters.
*/
explicit ImageView(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
explicit ImageView(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) 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<const void> data) noexcept;
explicit ImageView(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
/**
* @brief Construct an empty view with implementation-specific pixel format
@ -230,10 +265,10 @@ template<UnsignedInt dimensions> class ImageView {
* @param data Image data
*
* Uses ADL to find a corresponding @cpp pixelSize(T, U) @ce overload,
* then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* with calculated pixel size.
*/
template<class T, class U> explicit ImageView(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
template<class U, class V> explicit ImageView(PixelStorage storage, U format, V formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
/**
* @brief Construct an image view with implementation-specific pixel format
@ -243,10 +278,10 @@ template<UnsignedInt dimensions> class ImageView {
* @param data Image data
*
* Uses ADL to find a corresponding @cpp pixelSize(T) @ce overload,
* then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*/
template<class T> explicit ImageView(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
template<class U> explicit ImageView(PixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
/**
* @brief Construct an image view with implementation-specific pixel format
@ -255,10 +290,10 @@ template<UnsignedInt dimensions> class ImageView {
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref ImageView(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* Equivalent to calling @ref ImageView(PixelStorage, U, V, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* with default-constructed @ref PixelStorage.
*/
template<class T, class U> explicit ImageView(T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> 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) noexcept: ImageView{{}, format, formatExtra, size, data} {}
/**
* @brief Construct an image view with implementation-specific pixel format
@ -266,10 +301,10 @@ template<UnsignedInt dimensions> class ImageView {
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref ImageView(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* Equivalent to calling @ref ImageView(PixelStorage, U, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* with default-constructed @ref PixelStorage.
*/
template<class T> explicit ImageView(T format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: ImageView{{}, format, size, data} {}
template<class U> explicit ImageView(U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: ImageView{{}, format, size, data} {}
/**
* @brief Construct an empty view with implementation-specific pixel format
@ -285,7 +320,7 @@ template<UnsignedInt dimensions> class ImageView {
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
*/
template<class T, class U> explicit ImageView(PixelStorage storage, T format, U 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) noexcept;
/**
* @brief Construct an empty view with implementation-specific pixel format
@ -300,7 +335,7 @@ template<UnsignedInt dimensions> class ImageView {
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
*/
template<class T> explicit ImageView(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size) noexcept;
template<class U> explicit ImageView(PixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size) noexcept;
/**
* @brief Construct an empty view with implementation-specific pixel format
@ -308,20 +343,23 @@ template<UnsignedInt dimensions> class ImageView {
* @param formatExtra Additional pixel format specifier
* @param size Image size
*
* Equivalent to calling @ref ImageView(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* Equivalent to calling @ref ImageView(PixelStorage, U, V, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* with default-constructed @ref PixelStorage.
*/
template<class T, class U> explicit ImageView(T format, U 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) noexcept: ImageView{{}, format, formatExtra, size} {}
/**
* @brief Construct an empty view with implementation-specific pixel format
* @param format Format of pixel data
* @param size Image size
*
* Equivalent to calling @ref ImageView(PixelStorage, T, const VectorTypeFor<dimensions, Int>&)
* Equivalent to calling @ref ImageView(PixelStorage, U, const VectorTypeFor<dimensions, Int>&)
* with default-constructed @ref PixelStorage.
*/
template<class T> explicit ImageView(T format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, size} {}
template<class U> explicit ImageView(U format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, size} {}
/** @brief Convert a mutable view to a const one */
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 Storage of pixel data */
PixelStorage storage() const { return _storage; }
@ -371,7 +409,7 @@ template<UnsignedInt dimensions> class ImageView {
*
* @see @ref pixels()
*/
Containers::ArrayView<const char> data() const { return _data; }
Containers::ArrayView<Type> data() const { return _data; }
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@ -380,8 +418,8 @@ template<UnsignedInt dimensions> class ImageView {
* @ref Corrade::Containers::arrayCast() instead for properly
* bounds-checked type conversion.
*/
template<class T> CORRADE_DEPRECATED("use data() together with Containers::arrayCast() instead") const T* data() const {
return reinterpret_cast<const T*>(_data.data());
template<class U> CORRADE_DEPRECATED("use data() together with Containers::arrayCast() instead") const U* data() const {
return reinterpret_cast<const U*>(_data.data());
}
#endif
@ -391,7 +429,7 @@ template<UnsignedInt dimensions> class ImageView {
* The data array is expected to be of proper size for parameters
* specified in the constructor.
*/
void setData(Containers::ArrayView<const void> data);
void setData(Containers::ArrayView<ErasedType> data);
/**
* @brief View on pixel data
@ -399,7 +437,7 @@ template<UnsignedInt dimensions> class ImageView {
* Provides direct and easy-to-use access to image pixels. See
* @ref Image-pixel-views for more information.
*/
Containers::StridedArrayView<dimensions + 1, const char> pixels() const;
Containers::StridedArrayView<dimensions + 1, Type> pixels() const;
/**
* @brief View on pixel data with a concrete pixel type
@ -409,29 +447,65 @@ template<UnsignedInt dimensions> class ImageView {
* correct type for given @ref format() --- checking it on the library
* side is not possible for the general case.
*/
template<class T> Containers::StridedArrayView<dimensions, const T> pixels() const {
template<class U> Containers::StridedArrayView<dimensions, typename std::conditional<std::is_const<Type>::value, typename std::add_const<U>::type, U>::type> pixels() const {
/* Deliberately not adding a StridedArrayView include, it should
work without since this is a templated function */
return Containers::arrayCast<dimensions, const T>(pixels());
return Containers::arrayCast<dimensions, typename std::conditional<std::is_const<Type>::value, typename std::add_const<U>::type, U>::type>(pixels());
}
private:
/* Needed for mutable->const conversion */
template<UnsignedInt, class> friend class ImageView;
PixelStorage _storage;
PixelFormat _format;
UnsignedInt _formatExtra;
UnsignedInt _pixelSize;
Math::Vector<Dimensions, Int> _size;
Containers::ArrayView<const char> _data;
Containers::ArrayView<Type> _data;
};
/** @brief One-dimensional image view */
typedef ImageView<1> ImageView1D;
/**
@brief One-dimensional image view
@see @ref MutableImageView1D, @ref CompressedImageView1D
*/
typedef ImageView<1, const char> ImageView1D;
/**
@brief Two-dimensional image view
@see @ref MutableImageView2D, @ref CompressedImageView2D
*/
typedef ImageView<2, const char> ImageView2D;
/**
@brief Three-dimensional image view
@see @ref MutableImageView3D, @ref CompressedImageView3D
*/
typedef ImageView<3, const char> ImageView3D;
/**
@brief One-dimensional mutable image view
@see @ref ImageView1D, @ref MutableCompressedImageView1D
*/
typedef ImageView<1, char> MutableImageView1D;
/** @brief Two-dimensional image view */
typedef ImageView<2> ImageView2D;
/**
@brief Two-dimensional mutable image view
/** @brief Three-dimensional image view */
typedef ImageView<3> ImageView3D;
@see @ref ImageView2D, @ref MutableCompressedImageView2D
*/
typedef ImageView<2, char> MutableImageView2D;
/**
@brief Three-dimensional mutable image view
@see @ref ImageView3D, @ref MutableCompressedImageView3D
*/
typedef ImageView<3, char> MutableImageView3D;
/**
@brief Compressed image view
@ -469,6 +543,16 @@ as first parameter. In the following snippet, the view is the bottom-right
@snippet Magnum.cpp CompressedImageView-usage-storage
@section CompressedImageView-mutable Data mutability
When using e.g. the @ref CompressedImageView2D typedef, the viewed data are
immutable. This is the most common use case, in order to be able to mutate the
underlying data (for example in order to read into a pre-allocated memory), use
@ref MutableCompressedImageView2D and friends instead. @ref CompressedImage and
@ref Trade::ImageData are convertible to either of those. Similarly to
@ref Corrade::Containers::ArrayView etc., a mutable view is also implicitly
convertible to a const one.
@subsection CompressedImageView-usage-implementation-specific Implementation-specific formats
For known graphics APIs, there's a set of utility functions converting from
@ -494,10 +578,37 @@ extract the implementation-specific identifier using
@snippet Magnum.cpp CompressedImageView-usage-gl-extract
@see @ref CompressedImageView1D, @ref CompressedImageView2D,
@ref CompressedImageView3D
@ref CompressedImageView3D, @ref MutableCompressedImageView1D,
@ref MutableCompressedImageView2D, @ref MutableCompressedImageView3D
*/
template<UnsignedInt dimensions> class CompressedImageView {
template<UnsignedInt dimensions, class T> class CompressedImageView {
public:
/* Pointer arithmetic relies on the type being a single byte */
static_assert(std::is_same<T, char>::value ||std::is_same<T, const char>::value,
"image view type can be either char or const char");
/**
* @brief Raw data type
*
* @cpp const char @ce for @ref CompressedImageView1D /
* @ref CompressedImageView2D / @ref CompressedImageView3D and
* @cpp char @ce for @ref MutableCompressedImageView1D /
* @ref MutableCompressedImageView2D /
* @ref MutableCompressedImageView3D. See also @ref ErasedType.
*/
typedef T Type;
/**
* @brief Erased data type
*
* @cpp const void @ce for @ref CompressedImageView1D /
* @ref CompressedImageView2D / @ref CompressedImageView3D and
* @cpp const void @ce for @ref MutableCompressedImageView1D /
* @ref MutableCompressedImageView2D / @ref MutableCompressedImageView3D.
* See also @ref Type.
*/
typedef typename std::conditional<std::is_const<T>::value, const void, void>::type ErasedType;
enum: UnsignedInt {
Dimensions = dimensions /**< Image dimension count */
};
@ -509,7 +620,7 @@ template<UnsignedInt dimensions> class CompressedImageView {
* @param size Image size
* @param data Image data
*/
explicit CompressedImageView(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
explicit CompressedImageView(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
/**
* @brief Constructor
@ -517,10 +628,10 @@ template<UnsignedInt dimensions> class CompressedImageView {
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* with default-constructed @ref CompressedPixelStorage.
*/
explicit CompressedImageView(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: CompressedImageView{{}, format, size, data} {}
explicit CompressedImageView(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: CompressedImageView{{}, format, size, data} {}
/**
* @brief Construct an empty view
@ -553,7 +664,7 @@ template<UnsignedInt dimensions> class CompressedImageView {
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat.
*/
template<class T> explicit CompressedImageView(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
template<class U> explicit CompressedImageView(CompressedPixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept;
/**
* @brief Construct an image view with implementation-specific format
@ -561,10 +672,10 @@ template<UnsignedInt dimensions> class CompressedImageView {
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<ErasedType>)
* with default-constructed @ref CompressedPixelStorage.
*/
template<class T> explicit CompressedImageView(T format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: CompressedImageView{{}, format, size, data} {}
template<class U> explicit CompressedImageView(U format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<ErasedType> data) noexcept: CompressedImageView{{}, format, size, data} {}
/**
* @brief Construct an empty view with implementation-specific format
@ -577,7 +688,7 @@ template<UnsignedInt dimensions> class CompressedImageView {
* @cpp nullptr @ce, call @ref setData() to assign a memory view to the
* image.
*/
template<class T> explicit CompressedImageView(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size) noexcept;
template<class U> explicit CompressedImageView(CompressedPixelStorage storage, U format, const VectorTypeFor<dimensions, Int>& size) noexcept;
/**
* @brief Construct an empty view with implementation-specific format
@ -587,7 +698,10 @@ template<UnsignedInt dimensions> class CompressedImageView {
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&)
* with default-constructed @ref CompressedPixelStorage.
*/
template<class T> explicit CompressedImageView(T format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{{}, format, size} {}
template<class U> explicit CompressedImageView(U format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{{}, format, size} {}
/** @brief Convert a mutable view to a const one */
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 Storage of compressed pixel data */
CompressedPixelStorage storage() const { return _storage; }
@ -617,7 +731,7 @@ template<UnsignedInt dimensions> class CompressedImageView {
}
/** @brief Image data */
Containers::ArrayView<const char> data() const { return _data; }
Containers::ArrayView<Type> data() const { return _data; }
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@ -626,8 +740,8 @@ template<UnsignedInt dimensions> class CompressedImageView {
* @ref Corrade::Containers::arrayCast() instead for properly
* bounds-checked type conversion.
*/
template<class T> CORRADE_DEPRECATED("use data() together with Containers::arrayCast() instead") const T* data() const {
return reinterpret_cast<const T*>(_data.data());
template<class U> CORRADE_DEPRECATED("use data() together with Containers::arrayCast() instead") const U* data() const {
return reinterpret_cast<const U*>(_data.data());
}
#endif
@ -637,30 +751,66 @@ template<UnsignedInt dimensions> class CompressedImageView {
* The data array is expected to be of proper size for parameters
* specified in the constructor.
*/
void setData(Containers::ArrayView<const void> data) {
_data = {reinterpret_cast<const char*>(data.data()), data.size()};
void setData(Containers::ArrayView<ErasedType> data) {
_data = {reinterpret_cast<Type*>(data.data()), data.size()};
}
private:
/* Needed for mutable->const conversion */
template<UnsignedInt, class> friend 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<const void> data) noexcept;
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;
CompressedPixelStorage _storage;
CompressedPixelFormat _format;
Math::Vector<Dimensions, Int> _size;
Containers::ArrayView<const char> _data;
Containers::ArrayView<Type> _data;
};
/** @brief One-dimensional compressed image view */
typedef CompressedImageView<1> CompressedImageView1D;
/**
@brief One-dimensional compressed image view
/** @brief Two-dimensional compressed image view */
typedef CompressedImageView<2> CompressedImageView2D;
@see @ref MutableCompressedImageView1D, @ref ImageView1D
*/
typedef CompressedImageView<1, const char> CompressedImageView1D;
/** @brief Three-dimensional compressed image view */
typedef CompressedImageView<3> CompressedImageView3D;
/**
@brief Two-dimensional compressed image view
@see @ref MutableCompressedImageView2D, @ref ImageView2D
*/
typedef CompressedImageView<2, const char> CompressedImageView2D;
/**
@brief Three-dimensional compressed image view
@see @ref MutableCompressedImageView3D, @ref ImageView3D
*/
typedef CompressedImageView<3, const char> CompressedImageView3D;
/**
@brief One-dimensional mutable compressed image view
@see @ref CompressedImageView1D, @ref MutableImageView1D
*/
typedef CompressedImageView<1, char> MutableCompressedImageView1D;
/**
@brief Two-dimensional mutable compressed image view
@see @ref CompressedImageView2D, @ref MutableImageView2D
*/
typedef CompressedImageView<2, char> MutableCompressedImageView2D;
/**
@brief Three-dimensional mutable compressed image view
@see @ref CompressedImageView3D, @ref MutableImageView3D
*/
typedef CompressedImageView<3, char> MutableCompressedImageView3D;
namespace Implementation {
template<class T> inline UnsignedInt pixelSizeAdl(T format) {
@ -672,36 +822,40 @@ namespace Implementation {
}
}
template<UnsignedInt dimensions> template<class T, class U> inline ImageView<dimensions>::ImageView(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: ImageView{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelSizeAdl(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) noexcept: ImageView{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelSizeAdl(format, formatExtra), size, data} {
static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> inline ImageView<dimensions>::ImageView(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: ImageView{storage, UnsignedInt(format), {}, Implementation::pixelSizeAdl(format), size, data} {
static_assert(sizeof(T) <= 4,
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::pixelSizeAdl(format), size, data} {
static_assert(sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T, class U> inline ImageView<dimensions>::ImageView(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, UnsignedInt(format), UnsignedInt(formatExtra), Implementation::pixelSizeAdl(format, formatExtra), size} {
static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
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::pixelSizeAdl(format, formatExtra), size} {
static_assert(sizeof(U) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> inline ImageView<dimensions>::ImageView(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, UnsignedInt(format), {}, Implementation::pixelSizeAdl(format), size} {
static_assert(sizeof(T) <= 4,
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::pixelSizeAdl(format), size} {
static_assert(sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> inline CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: CompressedImageView{storage, UnsignedInt(format), size, data} {
static_assert(sizeof(T) <= 4,
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> 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} {
static_assert(sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> inline CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{storage, UnsignedInt(format), size} {
static_assert(sizeof(T) <= 4,
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} {
static_assert(sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
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} {}
}
#endif

24
src/Magnum/Magnum.h

@ -727,15 +727,21 @@ typedef CompressedImage<1> CompressedImage1D;
typedef CompressedImage<2> CompressedImage2D;
typedef CompressedImage<3> CompressedImage3D;
template<UnsignedInt> class ImageView;
typedef ImageView<1> ImageView1D;
typedef ImageView<2> ImageView2D;
typedef ImageView<3> ImageView3D;
template<UnsignedInt> class CompressedImageView;
typedef CompressedImageView<1> CompressedImageView1D;
typedef CompressedImageView<2> CompressedImageView2D;
typedef CompressedImageView<3> CompressedImageView3D;
template<UnsignedInt, class> class ImageView;
typedef ImageView<1, const char> ImageView1D;
typedef ImageView<2, const char> ImageView2D;
typedef ImageView<3, const char> ImageView3D;
typedef ImageView<1, char> MutableImageView1D;
typedef ImageView<2, char> MutableImageView2D;
typedef ImageView<3, char> MutableImageView3D;
template<UnsignedInt, class> class CompressedImageView;
typedef CompressedImageView<1, const char> CompressedImageView1D;
typedef CompressedImageView<2, const char> CompressedImageView2D;
typedef CompressedImageView<3, const char> CompressedImageView3D;
typedef CompressedImageView<1, char> MutableCompressedImageView1D;
typedef CompressedImageView<2, char> MutableCompressedImageView2D;
typedef CompressedImageView<3, char> MutableCompressedImageView3D;
enum class MeshPrimitive: UnsignedInt;
enum class MeshIndexType: UnsignedInt;

66
src/Magnum/Test/ImageTest.cpp

@ -56,10 +56,10 @@ struct ImageTest: TestSuite::Tester {
void constructMoveCompressedGeneric();
void constructMoveCompressedImplementationSpecific();
void toViewGeneric();
void toViewImplementationSpecific();
void toViewCompressedGeneric();
void toViewCompressedImplementationSpecific();
template<class T> void toViewGeneric();
template<class T> void toViewImplementationSpecific();
template<class T> void toViewCompressedGeneric();
template<class T> void toViewCompressedImplementationSpecific();
void data();
void dataCompressed();
@ -77,6 +77,20 @@ struct ImageTest: TestSuite::Tester {
void pixels3D();
};
template<class> struct MutabilityTraits;
template<> struct MutabilityTraits<const char> {
typedef const Image2D ImageType;
typedef const CompressedImage2D CompressedImageType;
static const char* name() { return "ImageView"; }
};
template<> struct MutabilityTraits<char> {
typedef Image2D ImageType;
typedef CompressedImage2D CompressedImageType;
static const char* name() { return "MutableImageView"; }
};
ImageTest::ImageTest() {
addTests({&ImageTest::constructGeneric,
&ImageTest::constructGenericPlaceholder,
@ -97,10 +111,14 @@ ImageTest::ImageTest() {
&ImageTest::constructMoveCompressedGeneric,
&ImageTest::constructMoveCompressedImplementationSpecific,
&ImageTest::toViewGeneric,
&ImageTest::toViewImplementationSpecific,
&ImageTest::toViewCompressedGeneric,
&ImageTest::toViewCompressedImplementationSpecific,
&ImageTest::toViewGeneric<const char>,
&ImageTest::toViewGeneric<char>,
&ImageTest::toViewImplementationSpecific<const char>,
&ImageTest::toViewImplementationSpecific<char>,
&ImageTest::toViewCompressedGeneric<const char>,
&ImageTest::toViewCompressedGeneric<char>,
&ImageTest::toViewCompressedImplementationSpecific<const char>,
&ImageTest::toViewCompressedImplementationSpecific<char>,
&ImageTest::data,
&ImageTest::dataCompressed,
@ -556,11 +574,13 @@ void ImageTest::constructMoveCompressedImplementationSpecific() {
CORRADE_COMPARE(c.data().size(), 8);
}
void ImageTest::toViewGeneric() {
template<class T> void ImageTest::toViewGeneric() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
auto data = new char[3*4];
const Image2D a{PixelStorage{}.setAlignment(1),
typename MutabilityTraits<T>::ImageType a{PixelStorage{}.setAlignment(1),
PixelFormat::RG16I, {1, 3}, Containers::Array<char>{data, 3*4}};
ImageView2D b = a;
ImageView<2, T> b = a;
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), PixelFormat::RG16I);
@ -570,11 +590,13 @@ void ImageTest::toViewGeneric() {
CORRADE_COMPARE(b.data(), data);
}
void ImageTest::toViewImplementationSpecific() {
template<class T> void ImageTest::toViewImplementationSpecific() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
auto data = new char[3*6];
const Image2D a{PixelStorage{}.setAlignment(1),
typename MutabilityTraits<T>::ImageType a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}};
ImageView2D b = a;
ImageView<2, T> b = a;
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
@ -584,12 +606,14 @@ void ImageTest::toViewImplementationSpecific() {
CORRADE_COMPARE(b.data(), data);
}
void ImageTest::toViewCompressedGeneric() {
template<class T> void ImageTest::toViewCompressedGeneric() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
auto data = new char[8];
const CompressedImage2D a{
typename MutabilityTraits<T>::CompressedImageType a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBUnorm, {4, 4}, Containers::Array<char>{data, 8}};
CompressedImageView2D b = a;
CompressedImageView<2, T> b = a;
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), CompressedPixelFormat::Bc1RGBUnorm);
@ -598,12 +622,14 @@ void ImageTest::toViewCompressedGeneric() {
CORRADE_COMPARE(b.data().size(), 8);
}
void ImageTest::toViewCompressedImplementationSpecific() {
template<class T> void ImageTest::toViewCompressedImplementationSpecific() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
auto data = new char[8];
const CompressedImage2D a{
typename MutabilityTraits<T>::CompressedImageType a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}};
CompressedImageView2D b = a;
CompressedImageView<2, T> b = a;
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));

328
src/Magnum/Test/ImageViewTest.cpp

@ -37,16 +37,19 @@ namespace Magnum { namespace Test { namespace {
struct ImageViewTest: TestSuite::Tester {
explicit ImageViewTest();
void constructGeneric();
void constructGenericEmpty();
void constructGenericEmptyNullptr();
void constructImplementationSpecific();
void constructImplementationSpecificEmpty();
void constructImplementationSpecificEmptyNullptr();
void constructCompressedGeneric();
void constructCompressedGenericEmpty();
void constructCompressedImplementationSpecific();
void constructCompressedImplementationSpecificEmpty();
template<class T> void constructGeneric();
template<class T> void constructGenericEmpty();
template<class T> void constructGenericEmptyNullptr();
template<class T> void constructImplementationSpecific();
template<class T> void constructImplementationSpecificEmpty();
template<class T> void constructImplementationSpecificEmptyNullptr();
template<class T> void constructCompressedGeneric();
template<class T> void constructCompressedGenericEmpty();
template<class T> void constructCompressedImplementationSpecific();
template<class T> void constructCompressedImplementationSpecificEmpty();
void constructFromMutable();
void constructCompressedFromMutable();
void constructInvalidSize();
void constructCompressedInvalidSize();
@ -54,28 +57,49 @@ struct ImageViewTest: TestSuite::Tester {
void dataProperties();
void dataPropertiesCompressed();
void setData();
void setDataCompressed();
template<class T> void setData();
template<class T> void setDataCompressed();
void setDataInvalidSize();
void setDataCompressedInvalidSize();
void pixels1D();
void pixels2D();
void pixels3D();
template<class T> void pixels1D();
template<class T> void pixels2D();
template<class T> void pixels3D();
};
template<class> struct MutabilityTraits;
template<> struct MutabilityTraits<const char> {
static const char* name() { return "ImageView"; }
};
template<> struct MutabilityTraits<char> {
static const char* name() { return "MutableImageView"; }
};
ImageViewTest::ImageViewTest() {
addTests({&ImageViewTest::constructGeneric,
&ImageViewTest::constructGenericEmpty,
&ImageViewTest::constructGenericEmptyNullptr,
&ImageViewTest::constructImplementationSpecific,
&ImageViewTest::constructImplementationSpecificEmpty,
&ImageViewTest::constructImplementationSpecificEmptyNullptr,
&ImageViewTest::constructCompressedGeneric,
&ImageViewTest::constructCompressedGenericEmpty,
&ImageViewTest::constructCompressedImplementationSpecific,
&ImageViewTest::constructCompressedImplementationSpecificEmpty,
addTests({&ImageViewTest::constructGeneric<const char>,
&ImageViewTest::constructGeneric<char>,
&ImageViewTest::constructGenericEmpty<const char>,
&ImageViewTest::constructGenericEmpty<char>,
&ImageViewTest::constructGenericEmptyNullptr<const char>,
&ImageViewTest::constructGenericEmptyNullptr<char>,
&ImageViewTest::constructImplementationSpecific<const char>,
&ImageViewTest::constructImplementationSpecific<char>,
&ImageViewTest::constructImplementationSpecificEmpty<const char>,
&ImageViewTest::constructImplementationSpecificEmpty<char>,
&ImageViewTest::constructImplementationSpecificEmptyNullptr<const char>,
&ImageViewTest::constructImplementationSpecificEmptyNullptr<char>,
&ImageViewTest::constructCompressedGeneric<const char>,
&ImageViewTest::constructCompressedGeneric<char>,
&ImageViewTest::constructCompressedGenericEmpty<const char>,
&ImageViewTest::constructCompressedGenericEmpty<char>,
&ImageViewTest::constructCompressedImplementationSpecific<const char>,
&ImageViewTest::constructCompressedImplementationSpecific<char>,
&ImageViewTest::constructCompressedImplementationSpecificEmpty<const char>,
&ImageViewTest::constructCompressedImplementationSpecificEmpty<char>,
&ImageViewTest::constructFromMutable,
&ImageViewTest::constructCompressedFromMutable,
&ImageViewTest::constructInvalidSize,
&ImageViewTest::constructCompressedInvalidSize,
@ -83,15 +107,20 @@ ImageViewTest::ImageViewTest() {
&ImageViewTest::dataProperties,
&ImageViewTest::dataPropertiesCompressed,
&ImageViewTest::setData,
&ImageViewTest::setDataCompressed,
&ImageViewTest::setData<const char>,
&ImageViewTest::setData<char>,
&ImageViewTest::setDataCompressed<const char>,
&ImageViewTest::setDataCompressed<char>,
&ImageViewTest::setDataInvalidSize,
&ImageViewTest::setDataCompressedInvalidSize,
&ImageViewTest::pixels1D,
&ImageViewTest::pixels2D,
&ImageViewTest::pixels3D});
&ImageViewTest::pixels1D<const char>,
&ImageViewTest::pixels1D<char>,
&ImageViewTest::pixels2D<const char>,
&ImageViewTest::pixels2D<char>,
&ImageViewTest::pixels3D<const char>,
&ImageViewTest::pixels3D<char>});
}
namespace GL {
@ -122,21 +151,23 @@ namespace Vk {
enum class CompressedPixelFormat { Bc1SRGBAlpha = 42 };
}
void ImageViewTest::constructGeneric() {
template<class T> void ImageViewTest::constructGeneric() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
{
const char data[4*4]{};
ImageView2D a{PixelFormat::RGBA8Unorm, {1, 3}, data};
T data[4*4]{};
ImageView<2, T> a{PixelFormat::RGBA8Unorm, {1, 3}, data};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RGBA8Unorm);
CORRADE_COMPARE(a.formatExtra(), 0);
CORRADE_COMPARE(a.pixelSize(), 4);
CORRADE_COMPARE(a.size(), (Vector2i{1, 3}));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 4*4);
} {
const char data[3*2]{};
ImageView2D a{PixelStorage{}.setAlignment(1),
T data[3*2]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
PixelFormat::R16UI, {1, 3}, data};
CORRADE_COMPARE(a.storage().alignment(), 1);
@ -144,14 +175,16 @@ void ImageViewTest::constructGeneric() {
CORRADE_COMPARE(a.formatExtra(), 0);
CORRADE_COMPARE(a.pixelSize(), 2);
CORRADE_COMPARE(a.size(), (Vector2i{1, 3}));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*2);
}
}
void ImageViewTest::constructGenericEmpty() {
template<class T> void ImageViewTest::constructGenericEmpty() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
{
ImageView2D a{PixelFormat::RG32F, {2, 6}};
ImageView<2, T> a{PixelFormat::RG32F, {2, 6}};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RG32F);
@ -160,7 +193,7 @@ void ImageViewTest::constructGenericEmpty() {
CORRADE_COMPARE(a.size(), (Vector2i{2, 6}));
CORRADE_COMPARE(a.data(), nullptr);
} {
ImageView2D a{PixelStorage{}.setAlignment(1),
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
PixelFormat::RGB16F, {8, 3}};
CORRADE_COMPARE(a.storage().alignment(), 1);
@ -172,12 +205,14 @@ void ImageViewTest::constructGenericEmpty() {
}
}
void ImageViewTest::constructGenericEmptyNullptr() {
template<class T> void ImageViewTest::constructGenericEmptyNullptr() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
/* This should be deprecated/removed, as it doesn't provide anything over
the above and can lead to silent errors */
{
ImageView2D a{PixelFormat::RG32F, {2, 6}, nullptr};
ImageView<2, T> a{PixelFormat::RG32F, {2, 6}, nullptr};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RG32F);
@ -186,7 +221,7 @@ void ImageViewTest::constructGenericEmptyNullptr() {
CORRADE_COMPARE(a.size(), (Vector2i{2, 6}));
CORRADE_COMPARE(a.data(), nullptr);
} {
ImageView2D a{PixelStorage{}.setAlignment(1),
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
PixelFormat::RGB16F, {8, 3}, nullptr};
CORRADE_COMPARE(a.storage().alignment(), 1);
@ -198,22 +233,24 @@ void ImageViewTest::constructGenericEmptyNullptr() {
}
}
void ImageViewTest::constructImplementationSpecific() {
template<class T> void ImageViewTest::constructImplementationSpecific() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
/* Single format */
{
const char data[3*12]{};
ImageView2D a{Vk::PixelFormat::R32G32B32F, {1, 3}, data};
T data[3*12]{};
ImageView<2, T> a{Vk::PixelFormat::R32G32B32F, {1, 3}, data};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
CORRADE_COMPARE(a.formatExtra(), 0);
CORRADE_COMPARE(a.pixelSize(), 12);
CORRADE_COMPARE(a.size(), (Vector2i{1, 3}));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*12);
} {
const char data[3*12]{};
ImageView2D a{PixelStorage{}.setAlignment(1),
T data[3*12]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F, {1, 3}, data};
CORRADE_COMPARE(a.storage().alignment(), 1);
@ -221,54 +258,56 @@ void ImageViewTest::constructImplementationSpecific() {
CORRADE_COMPARE(a.formatExtra(), 0);
CORRADE_COMPARE(a.pixelSize(), 12);
CORRADE_COMPARE(a.size(), (Vector2i{1, 3}));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*12);
}
/* Format + extra */
{
const char data[3*8]{};
ImageView2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data};
T data[3*8]{};
ImageView<2, T> a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
CORRADE_COMPARE(a.size(), Vector2i(1, 3));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*8);
} {
const char data[3*6]{};
ImageView2D a{PixelStorage{}.setAlignment(1),
T data[3*6]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data};
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
CORRADE_COMPARE(a.size(), Vector2i(1, 3));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*6);
}
/* Manual pixel size */
{
const char data[3*6]{};
ImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data};
T data[3*6]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data};
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
CORRADE_COMPARE(a.size(), Vector2i(1, 3));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*6);
}
}
void ImageViewTest::constructImplementationSpecificEmpty() {
template<class T> void ImageViewTest::constructImplementationSpecificEmpty() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
/* Single format */
{
ImageView2D a{Vk::PixelFormat::R32G32B32F, {2, 16}};
ImageView<2, T> a{Vk::PixelFormat::R32G32B32F, {2, 16}};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
@ -277,7 +316,7 @@ void ImageViewTest::constructImplementationSpecificEmpty() {
CORRADE_COMPARE(a.size(), (Vector2i{2, 16}));
CORRADE_COMPARE(a.data(), nullptr);
} {
ImageView2D a{PixelStorage{}.setAlignment(1),
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F, {1, 2}};
CORRADE_COMPARE(a.storage().alignment(), 1);
@ -290,7 +329,7 @@ void ImageViewTest::constructImplementationSpecificEmpty() {
/* Format + extra */
{
ImageView2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}};
ImageView<2, T> a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
@ -299,7 +338,7 @@ void ImageViewTest::constructImplementationSpecificEmpty() {
CORRADE_COMPARE(a.size(), (Vector2i{1, 3}));
CORRADE_COMPARE(a.data(), nullptr);
} {
ImageView2D a{PixelStorage{}.setAlignment(1),
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {8, 2}};
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
@ -311,7 +350,7 @@ void ImageViewTest::constructImplementationSpecificEmpty() {
/* Manual pixel size */
{
ImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {3, 3}};
ImageView<2, T> a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {3, 3}};
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
@ -322,13 +361,15 @@ void ImageViewTest::constructImplementationSpecificEmpty() {
}
}
void ImageViewTest::constructImplementationSpecificEmptyNullptr() {
template<class T> void ImageViewTest::constructImplementationSpecificEmptyNullptr() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
/* This should be deprecated/removed, as it doesn't provide anything over
the above and can lead to silent errors */
/* Single format */
{
ImageView2D a{Vk::PixelFormat::R32G32B32F, {2, 16}, nullptr};
ImageView<2, T> a{Vk::PixelFormat::R32G32B32F, {2, 16}, nullptr};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F));
@ -337,7 +378,7 @@ void ImageViewTest::constructImplementationSpecificEmptyNullptr() {
CORRADE_COMPARE(a.size(), (Vector2i{2, 16}));
CORRADE_COMPARE(a.data(), nullptr);
} {
ImageView2D a{PixelStorage{}.setAlignment(1),
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
Vk::PixelFormat::R32G32B32F, {1, 2}, nullptr};
CORRADE_COMPARE(a.storage().alignment(), 1);
@ -350,7 +391,7 @@ void ImageViewTest::constructImplementationSpecificEmptyNullptr() {
/* Format + extra */
{
ImageView2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, nullptr};
ImageView<2, T> a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, nullptr};
CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
@ -359,7 +400,7 @@ void ImageViewTest::constructImplementationSpecificEmptyNullptr() {
CORRADE_COMPARE(a.size(), (Vector2i{1, 3}));
CORRADE_COMPARE(a.data(), nullptr);
} {
ImageView2D a{PixelStorage{}.setAlignment(1),
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {8, 2}, nullptr};
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
@ -371,7 +412,7 @@ void ImageViewTest::constructImplementationSpecificEmptyNullptr() {
/* Manual pixel size */
{
ImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {3, 3}, nullptr};
ImageView<2, T> a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {3, 3}, nullptr};
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
@ -382,40 +423,44 @@ void ImageViewTest::constructImplementationSpecificEmptyNullptr() {
}
}
void ImageViewTest::constructCompressedGeneric() {
template<class T> void ImageViewTest::constructCompressedGeneric() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
{
const char data[8]{};
CompressedImageView2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, data};
T data[8]{};
CompressedImageView<2, T> a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, data};
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 8);
} {
const char data[8]{};
CompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
T data[8]{};
CompressedImageView<2, T> a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBAUnorm, {4, 4},
data};
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 8);
}
}
void ImageViewTest::constructCompressedGenericEmpty() {
template<class T> void ImageViewTest::constructCompressedGenericEmpty() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
{
CompressedImageView2D a{CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}};
CompressedImageView<2, T> a{CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}};
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), (Vector2i{8, 16}));
CORRADE_COMPARE(a.data(), nullptr);
} {
CompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedImageView<2, T> a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}};
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
@ -425,44 +470,48 @@ void ImageViewTest::constructCompressedGenericEmpty() {
}
}
void ImageViewTest::constructCompressedImplementationSpecific() {
template<class T> void ImageViewTest::constructCompressedImplementationSpecific() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
/* Format with autodetection */
{
const char data[8]{};
CompressedImageView2D a{GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4},
T data[8]{};
CompressedImageView<2, T> a{GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4},
data};
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 8);
} {
const char data[8]{};
CompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
T data[8]{};
CompressedImageView<2, T> a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, data};
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
CORRADE_COMPARE(a.data(), data);
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 8);
}
/* Manual properties not implemented yet */
}
void ImageViewTest::constructCompressedImplementationSpecificEmpty() {
template<class T> void ImageViewTest::constructCompressedImplementationSpecificEmpty() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
/* Format with autodetection */
{
CompressedImageView2D a{GL::CompressedPixelFormat::RGBS3tcDxt1, {8, 16}};
CompressedImageView<2, T> a{GL::CompressedPixelFormat::RGBS3tcDxt1, {8, 16}};
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(), nullptr);
} {
CompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedImageView<2, T> a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 8}};
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
@ -474,6 +523,49 @@ void ImageViewTest::constructCompressedImplementationSpecificEmpty() {
/* Manual properties not implemented yet */
}
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};
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(a.pixelSize(), 6);
CORRADE_COMPARE(a.size(), Vector2i(1, 3));
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 3*6);
ImageView2D b = a;
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
CORRADE_COMPARE(b.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort));
CORRADE_COMPARE(b.pixelSize(), 6);
CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_COMPARE(b.data(), &data[0]);
CORRADE_COMPARE(b.data().size(), 3*6);
}
void ImageViewTest::constructCompressedFromMutable() {
/* Copied from constructCompressedImplementationSpecific(), as that exposes
most fields */
char data[8]{};
MutableCompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, data};
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(a.size(), (Vector2i{4, 4}));
CORRADE_COMPARE(a.data(), &data[0]);
CORRADE_COMPARE(a.data().size(), 8);
CompressedImageView2D b = a;
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));
CORRADE_COMPARE(b.size(), (Vector2i{4, 4}));
CORRADE_COMPARE(b.data(), &data[0]);
CORRADE_COMPARE(b.data().size(), 8);
}
void ImageViewTest::constructInvalidSize() {
std::ostringstream out;
Error redirectError{&out};
@ -531,31 +623,35 @@ void ImageViewTest::dataPropertiesCompressed() {
(std::pair<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>>{{2*16, 2*16, 9*16}, {1, 3, 3}}));
}
void ImageViewTest::setData() {
const char data[3*3]{};
ImageView2D a{PixelStorage{}.setAlignment(1),
template<class T> void ImageViewTest::setData() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
T data[3*3]{};
ImageView<2, T> a{PixelStorage{}.setAlignment(1),
PixelFormat::RGB8Snorm, {1, 3}, data};
const char data2[3*3]{};
T data2[3*3]{};
a.setData(data2);
CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::RGB8Snorm);
CORRADE_COMPARE(a.size(), Vector2i(1, 3));
CORRADE_COMPARE(a.data(), data2);
CORRADE_COMPARE(a.data(), &data2[0]);
}
void ImageViewTest::setDataCompressed() {
const char data[8]{};
CompressedImageView2D a{
template<class T> void ImageViewTest::setDataCompressed() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
T data[8]{};
CompressedImageView<2, T> a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, data};
const char data2[16]{};
T data2[16]{};
a.setData(data2);
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(a.size(), Vector2i(4, 4));
CORRADE_COMPARE(a.data(), data2);
CORRADE_COMPARE(a.data(), &data2[0]);
}
void ImageViewTest::setDataInvalidSize() {
@ -591,8 +687,10 @@ void ImageViewTest::setDataCompressedInvalidSize() {
}
}
void ImageViewTest::pixels1D() {
ImageView1D image{
template<class T> void ImageViewTest::pixels1D() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
ImageView<1, T> image{
PixelStorage{}
.setAlignment(1) /** @todo alignment 4 expects 17 bytes. what */
.setSkip({3, 0, 0}),
@ -601,14 +699,18 @@ void ImageViewTest::pixels1D() {
/* Full test is in ImageTest, this is just a sanity check */
Containers::StridedArrayView1D<const Color3ub> pixels = image.pixels<Color3ub>();
auto pixels = image.template pixels<Color3ub>();
CORRADE_COMPARE(decltype(pixels)::Dimensions, 1);
CORRADE_COMPARE(std::is_const<typename decltype(pixels)::Type>::value, std::is_const<T>::value);
CORRADE_COMPARE(pixels.size(), 2);
CORRADE_COMPARE(pixels.stride(), 3);
CORRADE_COMPARE(pixels.data(), image.data() + 3*3);
}
void ImageViewTest::pixels2D() {
ImageView2D image{
template<class T> void ImageViewTest::pixels2D() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
ImageView<2, T> image{
PixelStorage{}
.setAlignment(4)
.setSkip({3, 2, 0})
@ -618,14 +720,18 @@ void ImageViewTest::pixels2D() {
/* Full test is in ImageTest, this is just a sanity check */
Containers::StridedArrayView2D<const Color3ub> pixels = image.pixels<Color3ub>();
auto pixels = image.template pixels<Color3ub>();
CORRADE_COMPARE(decltype(pixels)::Dimensions, 2);
CORRADE_COMPARE(std::is_const<typename decltype(pixels)::Type>::value, std::is_const<T>::value);
CORRADE_COMPARE(pixels.size(), (Containers::StridedArrayView2D<Color3ub>::Size{4, 2}));
CORRADE_COMPARE(pixels.stride(), (Containers::StridedArrayView2D<Color3ub>::Stride{20, 3}));
CORRADE_COMPARE(pixels.data(), image.data() + 2*20 + 3*3);
}
void ImageViewTest::pixels3D() {
ImageView3D image{
template<class T> void ImageViewTest::pixels3D() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
ImageView<3, T> image{
PixelStorage{}
.setAlignment(4)
.setSkip({3, 2, 1})
@ -636,7 +742,9 @@ void ImageViewTest::pixels3D() {
/* Full test is in ImageTest, this is just a sanity check */
Containers::StridedArrayView3D<const Color3ub> pixels = image.pixels<Color3ub>();
auto pixels = image.template pixels<Color3ub>();
CORRADE_COMPARE(decltype(pixels)::Dimensions, 3);
CORRADE_COMPARE(std::is_const<typename decltype(pixels)::Type>::value, std::is_const<T>::value);
CORRADE_COMPARE(pixels.size(), (Containers::StridedArrayView3D<Color3ub>::Size{3, 4, 2}));
CORRADE_COMPARE(pixels.stride(), (Containers::StridedArrayView3D<Color3ub>::Stride{140, 20, 3}));
CORRADE_COMPARE(pixels.data(), image.data() + 140 + 2*20 + 3*3);

26
src/Magnum/Trade/ImageData.cpp

@ -93,16 +93,26 @@ template<UnsignedInt dimensions> Containers::StridedArrayView<dimensions + 1, co
return Implementation::imagePixelView<dimensions, const char>(*this);
}
template<UnsignedInt dimensions> ImageData<dimensions>::operator ImageView<dimensions>() const
{
CORRADE_ASSERT(!_compressed, "Trade::ImageData::type(): the image is compressed", (ImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size}));
return ImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
template<UnsignedInt dimensions> ImageData<dimensions>::operator ImageView<dimensions, char>() {
CORRADE_ASSERT(!_compressed, "Trade::ImageData: the image is compressed", (ImageView<dimensions, char>{_storage, _format, _formatExtra, _pixelSize, _size}));
return ImageView<dimensions, char>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
}
template<UnsignedInt dimensions> ImageData<dimensions>::operator CompressedImageView<dimensions>() const
{
CORRADE_ASSERT(_compressed, "Trade::ImageData::type(): the image is not compressed", (CompressedImageView<dimensions>{_compressedStorage, _compressedFormat, _size}));
return CompressedImageView<dimensions>{
template<UnsignedInt dimensions> ImageData<dimensions>::operator ImageView<dimensions, const char>() const {
CORRADE_ASSERT(!_compressed, "Trade::ImageData: the image is compressed", (ImageView<dimensions, const char>{_storage, _format, _formatExtra, _pixelSize, _size}));
return ImageView<dimensions, const char>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
}
template<UnsignedInt dimensions> ImageData<dimensions>::operator CompressedImageView<dimensions, char>() {
CORRADE_ASSERT(_compressed, "Trade::ImageData: the image is not compressed", (CompressedImageView<dimensions, char>{_compressedStorage, _compressedFormat, _size}));
return CompressedImageView<dimensions, char>{
_compressedStorage,
_compressedFormat, _size, _data};
}
template<UnsignedInt dimensions> ImageData<dimensions>::operator CompressedImageView<dimensions, const char>() const {
CORRADE_ASSERT(_compressed, "Trade::ImageData: the image is not compressed", (CompressedImageView<dimensions, const char>{_compressedStorage, _compressedFormat, _size}));
return CompressedImageView<dimensions, const char>{
_compressedStorage,
_compressedFormat, _size, _data};
}

8
src/Magnum/Trade/ImageData.h

@ -235,7 +235,9 @@ template<UnsignedInt dimensions> class ImageData {
*/
/* Not restricted to const&, because we might want to pass the view to
another function in an oneliner (e.g. saving screenshot) */
/*implicit*/ operator ImageView<dimensions>() const;
/*implicit*/ operator ImageView<dimensions, char>();
/** @overload */
/*implicit*/ operator ImageView<dimensions, const char>() const;
/**
* @brief Conversion to compressed view
@ -245,7 +247,9 @@ template<UnsignedInt dimensions> class ImageData {
*/
/* Not restricted to const&, because we might want to pass the view to
another function in an oneliner (e.g. saving screenshot) */
/*implicit*/ operator CompressedImageView<dimensions>() const;
/*implicit*/ operator CompressedImageView<dimensions, char>();
/** @overload */
/*implicit*/ operator CompressedImageView<dimensions, const char>() const;
/**
* @brief Storage of pixel data

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

@ -55,10 +55,10 @@ struct ImageDataTest: TestSuite::Tester {
void constructMoveAttachState();
void constructMoveCompressedAttachState();
void toViewGeneric();
void toViewImplementationSpecific();
void toViewCompressedGeneric();
void toViewCompressedImplementationSpecific();
template<class T> void toViewGeneric();
template<class T> void toViewImplementationSpecific();
template<class T> void toViewCompressedGeneric();
template<class T> void toViewCompressedImplementationSpecific();
void data();
void dataRvalue();
@ -74,6 +74,18 @@ struct ImageDataTest: TestSuite::Tester {
void pixelsCompressed();
};
template<class> struct MutabilityTraits;
template<> struct MutabilityTraits<const char> {
typedef const ImageData2D ImageType;
static const char* name() { return "ImageView"; }
};
template<> struct MutabilityTraits<char> {
typedef ImageData2D ImageType;
static const char* name() { return "MutableImageView"; }
};
ImageDataTest::ImageDataTest() {
addTests({&ImageDataTest::constructGeneric,
&ImageDataTest::constructImplementationSpecific,
@ -93,10 +105,14 @@ ImageDataTest::ImageDataTest() {
&ImageDataTest::constructMoveAttachState,
&ImageDataTest::constructMoveCompressedAttachState,
&ImageDataTest::toViewGeneric,
&ImageDataTest::toViewImplementationSpecific,
&ImageDataTest::toViewCompressedGeneric,
&ImageDataTest::toViewCompressedImplementationSpecific,
&ImageDataTest::toViewGeneric<const char>,
&ImageDataTest::toViewGeneric<char>,
&ImageDataTest::toViewImplementationSpecific<const char>,
&ImageDataTest::toViewImplementationSpecific<char>,
&ImageDataTest::toViewCompressedGeneric<const char>,
&ImageDataTest::toViewCompressedGeneric<char>,
&ImageDataTest::toViewCompressedImplementationSpecific<const char>,
&ImageDataTest::toViewCompressedImplementationSpecific<char>,
&ImageDataTest::data,
&ImageDataTest::dataRvalue,
@ -500,11 +516,13 @@ void ImageDataTest::constructMoveCompressedAttachState() {
CORRADE_COMPARE(b.importerState(), &stateNew);
}
void ImageDataTest::toViewGeneric() {
template<class T> void ImageDataTest::toViewGeneric() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
auto data = new char[3*4];
const ImageData2D a{PixelStorage{}.setAlignment(1),
typename MutabilityTraits<T>::ImageType a{PixelStorage{}.setAlignment(1),
PixelFormat::RG16I, {1, 3}, Containers::Array<char>{data, 3*4}};
ImageView2D b = a;
ImageView<2, T> b = a;
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), PixelFormat::RG16I);
@ -514,11 +532,13 @@ void ImageDataTest::toViewGeneric() {
CORRADE_COMPARE(b.data(), data);
}
void ImageDataTest::toViewImplementationSpecific() {
template<class T> void ImageDataTest::toViewImplementationSpecific() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
auto data = new char[3*6];
const ImageData2D a{PixelStorage{}.setAlignment(1),
typename MutabilityTraits<T>::ImageType a{PixelStorage{}.setAlignment(1),
GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array<char>{data, 3*6}};
ImageView2D b = a;
ImageView<2, T> b = a;
CORRADE_COMPARE(b.storage().alignment(), 1);
CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB));
@ -528,12 +548,14 @@ void ImageDataTest::toViewImplementationSpecific() {
CORRADE_COMPARE(b.data(), data);
}
void ImageDataTest::toViewCompressedGeneric() {
template<class T> void ImageDataTest::toViewCompressedGeneric() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
auto data = new char[8];
const ImageData2D a{
typename MutabilityTraits<T>::ImageType a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
CompressedPixelFormat::Bc1RGBUnorm, {4, 4}, Containers::Array<char>{data, 8}};
CompressedImageView2D b = a;
CompressedImageView<2, T> b = a;
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), CompressedPixelFormat::Bc1RGBUnorm);
@ -542,12 +564,14 @@ void ImageDataTest::toViewCompressedGeneric() {
CORRADE_COMPARE(b.data().size(), 8);
}
void ImageDataTest::toViewCompressedImplementationSpecific() {
template<class T> void ImageDataTest::toViewCompressedImplementationSpecific() {
setTestCaseTemplateName(MutabilityTraits<T>::name());
auto data = new char[8];
const ImageData2D a{
typename MutabilityTraits<T>::ImageType a{
CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}),
GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array<char>{data, 8}};
CompressedImageView2D b = a;
CompressedImageView<2, T> b = a;
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4});
CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1));

Loading…
Cancel
Save