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/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;
switch(type) {
case ColorType::UnsignedByte:
@ -151,18 +151,18 @@ std::size_t AbstractImage::pixelSize(ColorFormat format, ColorType type) {
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 */
/* 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? */
size[0] = 1;
return rowSize*size.product();
}
template MAGNUM_EXPORT std::size_t AbstractImage::dataSize<1>(Math::Vector<1, Int>) const;
template MAGNUM_EXPORT std::size_t AbstractImage::dataSize<2>(Math::Vector<2, Int>) const;
template MAGNUM_EXPORT std::size_t AbstractImage::dataSize<3>(Math::Vector<3, Int>) const;
template MAGNUM_EXPORT std::size_t imageDataSize<1>(const AbstractImage&, ColorFormat, ColorType, Math::Vector<1, Int>);
template MAGNUM_EXPORT std::size_t imageDataSize<2>(const AbstractImage&, ColorFormat, ColorType, Math::Vector<2, Int>);
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 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
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.
@todo Where to put glClampColor() and glPixelStore() encapsulation? It is
needed in AbstractFramebuffer::read(), Texture::setImage() etc (i.e. all
functions operating with images). It also possibly needs to be "stackable"
to easily revert the state back.
*/
class MAGNUM_EXPORT 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); }
class AbstractImage {
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;
template<UnsignedInt dimensions> std::size_t dataSize(Math::Vector<dimensions, Int> size) const;
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#else
#ifndef DOXYGEN_GENERATING_OUTPUT
protected:
#else
private:
#endif
ColorFormat _format;
ColorType _type;
/** @todo remove this when the class has actual contents */
/* Otherwise both (heh) GCC and Clang complain when move-constructing using {} */
Int _dummy;
};
}

4
src/Magnum/BufferImage.cpp

@ -28,11 +28,11 @@
namespace Magnum {
#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);
}
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) {
_format = format;

17
src/Magnum/BufferImage.h

@ -90,12 +90,21 @@ template<UnsignedInt dimensions> class BufferImage: public AbstractImage {
/** @brief Move assignment */
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 */
VectorTypeFor<Dimensions, Int> size() const { return _size; }
/** @copydoc Image::dataSize() */
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 */
@ -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);
private:
ColorFormat _format;
ColorType _type;
Math::Vector<Dimensions, Int> _size;
Buffer _buffer;
};
@ -131,13 +142,15 @@ typedef BufferImage<2> BufferImage2D;
/** @brief Three-dimensional buffer image */
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 = {};
}
template<UnsignedInt dimensions> inline BufferImage<dimensions>& BufferImage<dimensions>::operator=(BufferImage<dimensions>&& other) noexcept {
AbstractImage::operator=(std::move(other));
using std::swap;
swap(_format, other._format);
swap(_type, other._type);
swap(_size, other._size);
swap(_buffer, other._buffer);
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
* 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
@ -66,7 +66,7 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
* Dimensions are set to zero and data pointer to `nullptr`, call
* @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 */
Image(const Image<dimensions>&) = delete;
@ -96,6 +96,15 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
/*implicit*/ operator ImageReference<dimensions>() const && = delete;
#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 */
VectorTypeFor<dimensions, Int> size() const { return _size; }
@ -107,7 +116,7 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
* @see @ref pixelSize()
*/
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();
private:
ColorFormat _format;
ColorType _type;
Math::Vector<Dimensions, Int> _size;
char* _data;
};
@ -160,7 +171,7 @@ typedef Image<2> Image2D;
/** @brief Three-dimensional image */
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._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 {
AbstractImage::operator=(std::move(other));
using std::swap;
swap(_format, other._format);
swap(_type, other._type);
swap(_size, other._size);
swap(_data, other._data);
return *this;
@ -180,7 +193,7 @@ const &
const
#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() {

17
src/Magnum/ImageReference.h

@ -63,7 +63,7 @@ template<UnsignedInt dimensions> class ImageReference: public AbstractImage {
* @param size Image size
* @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
@ -74,14 +74,23 @@ template<UnsignedInt dimensions> class ImageReference: public AbstractImage {
* Data pointer is set to `nullptr`, call @ref setData() to fill the
* 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 */
constexpr VectorTypeFor<dimensions, Int> size() const { return _size; }
/** @copydoc Image::dataSize() */
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 */
@ -105,6 +114,8 @@ template<UnsignedInt dimensions> class ImageReference: public AbstractImage {
}
private:
ColorFormat _format;
ColorType _type;
Math::Vector<Dimensions, Int> _size;
const char* _data;
};

8
src/Magnum/Test/AbstractImageTest.cpp

@ -44,10 +44,10 @@ AbstractImageTest::AbstractImageTest() {
}
void AbstractImageTest::pixelSize() {
CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::RGBA, ColorType::UnsignedInt), 4*4);
CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::DepthComponent, ColorType::UnsignedShort), 2);
CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::StencilIndex, ColorType::UnsignedByte), 1);
CORRADE_COMPARE(AbstractImage::pixelSize(ColorFormat::DepthStencil, ColorType::UnsignedInt248), 4);
CORRADE_COMPARE(Implementation::imagePixelSize(ColorFormat::RGBA, ColorType::UnsignedInt), 4*4);
CORRADE_COMPARE(Implementation::imagePixelSize(ColorFormat::DepthComponent, ColorType::UnsignedShort), 2);
CORRADE_COMPARE(Implementation::imagePixelSize(ColorFormat::StencilIndex, ColorType::UnsignedByte), 1);
CORRADE_COMPARE(Implementation::imagePixelSize(ColorFormat::DepthStencil, ColorType::UnsignedInt248), 4);
}
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
* 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 */
ImageData(const ImageData<dimensions>&) = delete;
@ -86,12 +86,21 @@ template<UnsignedInt dimensions> class ImageData: public AbstractImage {
/*implicit*/ operator ImageReference<dimensions>() const && = delete;
#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 */
VectorTypeFor<dimensions, Int> size() const { return _size; }
/** @copydoc Image::dataSize() */
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();
private:
ColorFormat _format;
ColorType _type;
Math::Vector<Dimensions, Int> _size;
char* _data;
};
@ -131,7 +142,7 @@ typedef ImageData<2> ImageData2D;
/** @brief Three-dimensional image */
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._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 {
AbstractImage::operator=(std::move(other));
using std::swap;
swap(_format, other._format);
swap(_type, other._type);
swap(_size, other._size);
swap(_data, other._data);
return *this;
@ -151,7 +164,7 @@ const &
const
#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() {

Loading…
Cancel
Save