Browse Source

Compressed image support, part 1: generalized AbstractImage class.

When pixel pack/unpack parameter support is done, this class will
contain only stuff that's common to both compressed and uncompressed
images. Currently that's nothing, so the class is empty.

Note the hilarious bug in both GCC and Clang: if you remove the `_dummy`
member, both of them start complaining about weird completely unrelated
stuff.
pull/107/head
Vladimír Vondruš 11 years ago
parent
commit
da3cb5a8ad
  1. 16
      src/Magnum/AbstractImage.cpp
  2. 54
      src/Magnum/AbstractImage.h
  3. 4
      src/Magnum/BufferImage.cpp
  4. 17
      src/Magnum/BufferImage.h
  5. 23
      src/Magnum/Image.h
  6. 17
      src/Magnum/ImageReference.h
  7. 8
      src/Magnum/Test/AbstractImageTest.cpp
  8. 21
      src/Magnum/Trade/ImageData.h

16
src/Magnum/AbstractImage.cpp

@ -30,9 +30,9 @@
#include "Magnum/ColorFormat.h" #include "Magnum/ColorFormat.h"
#include "Magnum/Math/Vector.h" #include "Magnum/Math/Vector.h"
namespace Magnum { namespace Magnum { namespace Implementation {
std::size_t AbstractImage::pixelSize(ColorFormat format, ColorType type) { std::size_t imagePixelSize(ColorFormat format, ColorType type) {
std::size_t size = 0; std::size_t size = 0;
switch(type) { switch(type) {
case ColorType::UnsignedByte: case ColorType::UnsignedByte:
@ -151,18 +151,18 @@ std::size_t AbstractImage::pixelSize(ColorFormat format, ColorType type) {
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
} }
template<UnsignedInt dimensions> std::size_t AbstractImage::dataSize(Math::Vector<dimensions, Int> size) const { template<UnsignedInt dimensions> std::size_t imageDataSize(const AbstractImage&, const ColorFormat format, const ColorType type, Math::Vector<dimensions, Int> size) {
/** @todo Code this properly when all @fn_gl{PixelStore} parameters are implemented */ /** @todo Code this properly when all @fn_gl{PixelStore} parameters are implemented */
/* Row size, rounded to multiple of 4 bytes */ /* Row size, rounded to multiple of 4 bytes */
const std::size_t rowSize = ((size[0]*pixelSize() + 3)/4)*4; const std::size_t rowSize = ((size[0]*imagePixelSize(format, type) + 3)/4)*4;
/** @todo Can't this be done somewhat nicer? */ /** @todo Can't this be done somewhat nicer? */
size[0] = 1; size[0] = 1;
return rowSize*size.product(); return rowSize*size.product();
} }
template MAGNUM_EXPORT std::size_t AbstractImage::dataSize<1>(Math::Vector<1, Int>) const; template MAGNUM_EXPORT std::size_t imageDataSize<1>(const AbstractImage&, ColorFormat, ColorType, Math::Vector<1, Int>);
template MAGNUM_EXPORT std::size_t AbstractImage::dataSize<2>(Math::Vector<2, Int>) const; template MAGNUM_EXPORT std::size_t imageDataSize<2>(const AbstractImage&, ColorFormat, ColorType, Math::Vector<2, Int>);
template MAGNUM_EXPORT std::size_t AbstractImage::dataSize<3>(Math::Vector<3, Int>) const; template MAGNUM_EXPORT std::size_t imageDataSize<3>(const AbstractImage&, ColorFormat, ColorType, Math::Vector<3, Int>);
} }}

54
src/Magnum/AbstractImage.h

@ -36,60 +36,34 @@
namespace Magnum { namespace Magnum {
namespace Implementation {
std::size_t MAGNUM_EXPORT imagePixelSize(ColorFormat format, ColorType type);
template<UnsignedInt dimensions> std::size_t imageDataSize(const AbstractImage& image, ColorFormat format, ColorType type, Math::Vector<dimensions, Int> size);
}
/** /**
@brief Non-templated base for one-, two- or three-dimensional images @brief Non-templated base for one-, two- or three-dimensional images
See @ref Image, @ref ImageReference, @ref BufferImage, @ref Trade::ImageData See @ref Image, @ref ImageReference, @ref BufferImage and @ref Trade::ImageData
documentation for more information. documentation for more information.
@todo Where to put glClampColor() and glPixelStore() encapsulation? It is @todo Where to put glClampColor() and glPixelStore() encapsulation? It is
needed in AbstractFramebuffer::read(), Texture::setImage() etc (i.e. all needed in AbstractFramebuffer::read(), Texture::setImage() etc (i.e. all
functions operating with images). It also possibly needs to be "stackable" functions operating with images). It also possibly needs to be "stackable"
to easily revert the state back. to easily revert the state back.
*/ */
class MAGNUM_EXPORT AbstractImage { class AbstractImage {
public:
/**
* @brief Pixel size (in bytes)
* @param format Format of the pixel
* @param type Data type of the pixel
*
* @see @ref pixelSize()
*/
static std::size_t pixelSize(ColorFormat format, ColorType type);
/** @brief Format of pixel data */
constexpr ColorFormat format() const { return _format; }
/** @brief Data type of pixel data */
constexpr ColorType type() const { return _type; }
/**
* @brief Pixel size (in bytes)
*
* Convenience member alternative for
* @ref pixelSize(ColorFormat, ColorType).
*/
std::size_t pixelSize() const { return pixelSize(_format, _type); }
protected: protected:
/**
* @brief Constructor
* @param format Format of pixel data
* @param type Data type of pixel data
*/
constexpr explicit AbstractImage(ColorFormat format, ColorType type): _format(format), _type(type) {}
~AbstractImage() = default; ~AbstractImage() = default;
template<UnsignedInt dimensions> std::size_t dataSize(Math::Vector<dimensions, Int> size) const; #ifndef DOXYGEN_GENERATING_OUTPUT
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#else
protected: protected:
#else
private:
#endif #endif
ColorFormat _format; /** @todo remove this when the class has actual contents */
ColorType _type; /* Otherwise both (heh) GCC and Clang complain when move-constructing using {} */
Int _dummy;
}; };
} }

4
src/Magnum/BufferImage.cpp

@ -28,11 +28,11 @@
namespace Magnum { namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage): AbstractImage(format, type), _size(size), _buffer(Buffer::TargetHint::PixelPack) { template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage): _format{format}, _type{type}, _size{size}, _buffer{Buffer::TargetHint::PixelPack} {
_buffer.setData({data, dataSize(size)}, usage); _buffer.setData({data, dataSize(size)}, usage);
} }
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type): AbstractImage(format, type), _buffer(Buffer::TargetHint::PixelPack) {} template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type): _format{format}, _type{type}, _buffer{Buffer::TargetHint::PixelPack} {}
template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage) { template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage) {
_format = format; _format = format;

17
src/Magnum/BufferImage.h

@ -90,12 +90,21 @@ template<UnsignedInt dimensions> class BufferImage: public AbstractImage {
/** @brief Move assignment */ /** @brief Move assignment */
BufferImage<dimensions>& operator=(BufferImage<dimensions>&& other) noexcept; BufferImage<dimensions>& operator=(BufferImage<dimensions>&& other) noexcept;
/** @brief Format of pixel data */
ColorFormat format() const { return _format; }
/** @brief Data type of pixel data */
ColorType type() const { return _type; }
/** @brief Pixel size (in bytes) */
std::size_t pixelSize() const { return Implementation::imagePixelSize(_format, _type); }
/** @brief Image size */ /** @brief Image size */
VectorTypeFor<Dimensions, Int> size() const { return _size; } VectorTypeFor<Dimensions, Int> size() const { return _size; }
/** @copydoc Image::dataSize() */ /** @copydoc Image::dataSize() */
std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const { std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const {
return AbstractImage::dataSize<dimensions>(size); return Implementation::imageDataSize<dimensions>(*this, _format, _type, size);
} }
/** @brief Image buffer */ /** @brief Image buffer */
@ -118,6 +127,8 @@ template<UnsignedInt dimensions> class BufferImage: public AbstractImage {
void setData(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage); void setData(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage);
private: private:
ColorFormat _format;
ColorType _type;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
Buffer _buffer; Buffer _buffer;
}; };
@ -131,13 +142,15 @@ typedef BufferImage<2> BufferImage2D;
/** @brief Three-dimensional buffer image */ /** @brief Three-dimensional buffer image */
typedef BufferImage<3> BufferImage3D; typedef BufferImage<3> BufferImage3D;
template<UnsignedInt dimensions> inline BufferImage<dimensions>::BufferImage(BufferImage<dimensions>&& other) noexcept: AbstractImage(std::move(other)), _size(other._size), _buffer(std::move(other._buffer)) { template<UnsignedInt dimensions> inline BufferImage<dimensions>::BufferImage(BufferImage<dimensions>&& other) noexcept: AbstractImage{std::move(other)}, _format{std::move(other._format)}, _type{std::move(other._type)}, _size{std::move(other._size)}, _buffer{std::move(other._buffer)} {
other._size = {}; other._size = {};
} }
template<UnsignedInt dimensions> inline BufferImage<dimensions>& BufferImage<dimensions>::operator=(BufferImage<dimensions>&& other) noexcept { template<UnsignedInt dimensions> inline BufferImage<dimensions>& BufferImage<dimensions>::operator=(BufferImage<dimensions>&& other) noexcept {
AbstractImage::operator=(std::move(other)); AbstractImage::operator=(std::move(other));
using std::swap; using std::swap;
swap(_format, other._format);
swap(_type, other._type);
swap(_size, other._size); swap(_size, other._size);
swap(_buffer, other._buffer); swap(_buffer, other._buffer);
return *this; return *this;

23
src/Magnum/Image.h

@ -56,7 +56,7 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
* Note that the image data are not copied on construction, but they * Note that the image data are not copied on construction, but they
* are deleted on class destruction. * are deleted on class destruction.
*/ */
explicit Image(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, void* data): AbstractImage{format, type}, _size{size}, _data{reinterpret_cast<char*>(data)} {} explicit Image(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, void* data): _format{format}, _type{type}, _size{size}, _data{reinterpret_cast<char*>(data)} {}
/** /**
* @brief Constructor * @brief Constructor
@ -66,7 +66,7 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
* Dimensions are set to zero and data pointer to `nullptr`, call * Dimensions are set to zero and data pointer to `nullptr`, call
* @ref setData() to fill the image with data. * @ref setData() to fill the image with data.
*/ */
/*implicit*/ Image(ColorFormat format, ColorType type): AbstractImage(format, type), _data{} {} /*implicit*/ Image(ColorFormat format, ColorType type): _format{format}, _type{type}, _data{} {}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Image(const Image<dimensions>&) = delete; Image(const Image<dimensions>&) = delete;
@ -96,6 +96,15 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
/*implicit*/ operator ImageReference<dimensions>() const && = delete; /*implicit*/ operator ImageReference<dimensions>() const && = delete;
#endif #endif
/** @brief Format of pixel data */
ColorFormat format() const { return _format; }
/** @brief Data type of pixel data */
ColorType type() const { return _type; }
/** @brief Pixel size (in bytes) */
std::size_t pixelSize() const { return Implementation::imagePixelSize(_format, _type); }
/** @brief Image size */ /** @brief Image size */
VectorTypeFor<dimensions, Int> size() const { return _size; } VectorTypeFor<dimensions, Int> size() const { return _size; }
@ -107,7 +116,7 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
* @see @ref pixelSize() * @see @ref pixelSize()
*/ */
std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const { std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const {
return AbstractImage::dataSize<dimensions>(size); return Implementation::imageDataSize<dimensions>(*this, _format, _type, size);
} }
/** /**
@ -147,6 +156,8 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
char* release(); char* release();
private: private:
ColorFormat _format;
ColorType _type;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
char* _data; char* _data;
}; };
@ -160,7 +171,7 @@ typedef Image<2> Image2D;
/** @brief Three-dimensional image */ /** @brief Three-dimensional image */
typedef Image<3> Image3D; typedef Image<3> Image3D;
template<UnsignedInt dimensions> inline Image<dimensions>::Image(Image<dimensions>&& other) noexcept: AbstractImage(std::move(other)), _size(std::move(other._size)), _data(std::move(other._data)) { template<UnsignedInt dimensions> inline Image<dimensions>::Image(Image<dimensions>&& other) noexcept: AbstractImage{std::move(other)}, _format{std::move(other._format)}, _type{std::move(other._type)}, _size{std::move(other._size)}, _data{std::move(other._data)} {
other._size = {}; other._size = {};
other._data = nullptr; other._data = nullptr;
} }
@ -168,6 +179,8 @@ template<UnsignedInt dimensions> inline Image<dimensions>::Image(Image<dimension
template<UnsignedInt dimensions> inline Image<dimensions>& Image<dimensions>::operator=(Image<dimensions>&& other) noexcept { template<UnsignedInt dimensions> inline Image<dimensions>& Image<dimensions>::operator=(Image<dimensions>&& other) noexcept {
AbstractImage::operator=(std::move(other)); AbstractImage::operator=(std::move(other));
using std::swap; using std::swap;
swap(_format, other._format);
swap(_type, other._type);
swap(_size, other._size); swap(_size, other._size);
swap(_data, other._data); swap(_data, other._data);
return *this; return *this;
@ -180,7 +193,7 @@ const &
const const
#endif #endif
{ {
return ImageReference<dimensions>(AbstractImage::format(), AbstractImage::type(), _size, _data); return ImageReference<dimensions>{_format, _type, _size, _data};
} }
template<UnsignedInt dimensions> inline char* Image<dimensions>::release() { template<UnsignedInt dimensions> inline char* Image<dimensions>::release() {

17
src/Magnum/ImageReference.h

@ -63,7 +63,7 @@ template<UnsignedInt dimensions> class ImageReference: public AbstractImage {
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
*/ */
constexpr explicit ImageReference(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast<const char*>(data)) {} constexpr explicit ImageReference(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data): _format{format}, _type{type}, _size{size}, _data{reinterpret_cast<const char*>(data)} {}
/** /**
* @brief Constructor * @brief Constructor
@ -74,14 +74,23 @@ template<UnsignedInt dimensions> class ImageReference: public AbstractImage {
* Data pointer is set to `nullptr`, call @ref setData() to fill the * Data pointer is set to `nullptr`, call @ref setData() to fill the
* image with data. * image with data.
*/ */
constexpr explicit ImageReference(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size): AbstractImage(format, type), _size(size), _data(nullptr) {} constexpr explicit ImageReference(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size): _format{format}, _type{type}, _size{size}, _data{nullptr} {}
/** @brief Format of pixel data */
ColorFormat format() const { return _format; }
/** @brief Data type of pixel data */
ColorType type() const { return _type; }
/** @brief Pixel size (in bytes) */
std::size_t pixelSize() const { return Implementation::imagePixelSize(_format, _type); }
/** @brief Image size */ /** @brief Image size */
constexpr VectorTypeFor<dimensions, Int> size() const { return _size; } constexpr VectorTypeFor<dimensions, Int> size() const { return _size; }
/** @copydoc Image::dataSize() */ /** @copydoc Image::dataSize() */
std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const { std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const {
return AbstractImage::dataSize<dimensions>(size); return Implementation::imageDataSize<dimensions>(*this, _format, _type, size);
} }
/** @brief Pointer to raw data */ /** @brief Pointer to raw data */
@ -105,6 +114,8 @@ template<UnsignedInt dimensions> class ImageReference: public AbstractImage {
} }
private: private:
ColorFormat _format;
ColorType _type;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
const char* _data; const char* _data;
}; };

8
src/Magnum/Test/AbstractImageTest.cpp

@ -44,10 +44,10 @@ AbstractImageTest::AbstractImageTest() {
} }
void AbstractImageTest::pixelSize() { void AbstractImageTest::pixelSize() {
CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::RGBA, ColorType::UnsignedInt), 4*4); CORRADE_COMPARE(Implementation::imagePixelSize(ColorFormat::RGBA, ColorType::UnsignedInt), 4*4);
CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::DepthComponent, ColorType::UnsignedShort), 2); CORRADE_COMPARE(Implementation::imagePixelSize(ColorFormat::DepthComponent, ColorType::UnsignedShort), 2);
CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::StencilIndex, ColorType::UnsignedByte), 1); CORRADE_COMPARE(Implementation::imagePixelSize(ColorFormat::StencilIndex, ColorType::UnsignedByte), 1);
CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::DepthStencil, ColorType::UnsignedInt248), 4); CORRADE_COMPARE(Implementation::imagePixelSize(ColorFormat::DepthStencil, ColorType::UnsignedInt248), 4);
} }
void AbstractImageTest::dataSize() { void AbstractImageTest::dataSize() {

21
src/Magnum/Trade/ImageData.h

@ -56,7 +56,7 @@ template<UnsignedInt dimensions> class ImageData: public AbstractImage {
* Note that the image data are not copied on construction, but they * Note that the image data are not copied on construction, but they
* are deleted on class destruction. * are deleted on class destruction.
*/ */
explicit ImageData(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, void* data): AbstractImage{format, type}, _size{size}, _data{reinterpret_cast<char*>(data)} {} explicit ImageData(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, void* data): _format{format}, _type{type}, _size{size}, _data{reinterpret_cast<char*>(data)} {}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
ImageData(const ImageData<dimensions>&) = delete; ImageData(const ImageData<dimensions>&) = delete;
@ -86,12 +86,21 @@ template<UnsignedInt dimensions> class ImageData: public AbstractImage {
/*implicit*/ operator ImageReference<dimensions>() const && = delete; /*implicit*/ operator ImageReference<dimensions>() const && = delete;
#endif #endif
/** @brief Format of pixel data */
ColorFormat format() const { return _format; }
/** @brief Data type of pixel data */
ColorType type() const { return _type; }
/** @brief Pixel size (in bytes) */
std::size_t pixelSize() const { return Implementation::imagePixelSize(_format, _type); }
/** @brief Image size */ /** @brief Image size */
VectorTypeFor<dimensions, Int> size() const { return _size; } VectorTypeFor<dimensions, Int> size() const { return _size; }
/** @copydoc Image::dataSize() */ /** @copydoc Image::dataSize() */
std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const { std::size_t dataSize(const VectorTypeFor<dimensions, Int>& size) const {
return AbstractImage::dataSize<dimensions>(size); return Implementation::imageDataSize<dimensions>(*this, _format, _type, size);
} }
/** /**
@ -118,6 +127,8 @@ template<UnsignedInt dimensions> class ImageData: public AbstractImage {
char* release(); char* release();
private: private:
ColorFormat _format;
ColorType _type;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
char* _data; char* _data;
}; };
@ -131,7 +142,7 @@ typedef ImageData<2> ImageData2D;
/** @brief Three-dimensional image */ /** @brief Three-dimensional image */
typedef ImageData<3> ImageData3D; typedef ImageData<3> ImageData3D;
template<UnsignedInt dimensions> inline ImageData<dimensions>::ImageData(ImageData<dimensions>&& other) noexcept: AbstractImage(std::move(other)), _size(std::move(other._size)), _data(std::move(other._data)) { template<UnsignedInt dimensions> inline ImageData<dimensions>::ImageData(ImageData<dimensions>&& other) noexcept: AbstractImage{std::move(other)}, _format{std::move(other._format)}, _type{std::move(other._type)}, _size{std::move(other._size)}, _data{std::move(other._data)} {
other._size = {}; other._size = {};
other._data = nullptr; other._data = nullptr;
} }
@ -139,6 +150,8 @@ template<UnsignedInt dimensions> inline ImageData<dimensions>::ImageData(ImageDa
template<UnsignedInt dimensions> inline ImageData<dimensions>& ImageData<dimensions>::operator=(ImageData<dimensions>&& other) noexcept { template<UnsignedInt dimensions> inline ImageData<dimensions>& ImageData<dimensions>::operator=(ImageData<dimensions>&& other) noexcept {
AbstractImage::operator=(std::move(other)); AbstractImage::operator=(std::move(other));
using std::swap; using std::swap;
swap(_format, other._format);
swap(_type, other._type);
swap(_size, other._size); swap(_size, other._size);
swap(_data, other._data); swap(_data, other._data);
return *this; return *this;
@ -151,7 +164,7 @@ const &
const const
#endif #endif
{ {
return ImageReference<dimensions>(AbstractImage::format(), AbstractImage::type(), _size, _data); return ImageReference<dimensions>(_format, _type, _size, _data);
} }
template<UnsignedInt dimensions> inline char* ImageData<dimensions>::release() { template<UnsignedInt dimensions> inline char* ImageData<dimensions>::release() {

Loading…
Cancel
Save