From 8b9b161c5a813c3c6af7566f52f6b37a4b05a818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 2 Apr 2012 04:21:24 +0200 Subject: [PATCH] Rework of image classes, added missing image formats. * Framebuffer related functions moved to Framebuffer class, thus simplifying the data setting functions - removed setDimensions(), more flexible setData() function. * Allow to set data with explicit format specification, reorganized function parameters to make these two setData() more similar. * Now using new AbstractType::ComponentType enum instead of basic Type, updated TypeTraits to return the new enum from imageType() function. --- src/AbstractImage.cpp | 51 ++++++++++-- src/AbstractImage.h | 177 +++++++++++++++++++++++++++++++++++++----- src/AbstractTexture.h | 14 ++-- src/BufferedImage.cpp | 25 ------ src/BufferedImage.h | 78 ++++++++----------- src/CMakeLists.txt | 2 - src/Framebuffer.cpp | 16 ++++ src/Framebuffer.h | 23 ++++++ src/Image.cpp | 24 ------ src/Image.h | 95 +++++++++++------------ src/Trade/ImageData.h | 25 ++++-- src/TypeTraits.h | 18 ++--- 12 files changed, 352 insertions(+), 196 deletions(-) delete mode 100644 src/BufferedImage.cpp delete mode 100644 src/Image.cpp diff --git a/src/AbstractImage.cpp b/src/AbstractImage.cpp index 3406b3315..f67213542 100644 --- a/src/AbstractImage.cpp +++ b/src/AbstractImage.cpp @@ -14,21 +14,56 @@ */ #include "AbstractImage.h" +#include "TypeTraits.h" namespace Magnum { -size_t AbstractImage::pixelSize(ColorFormat format, Type type) { - size_t size = TypeInfo::sizeOf(type); +size_t AbstractImage::pixelSize(Components format, ComponentType type) { + size_t size; + switch(type) { + case ComponentType::RGB332: + case ComponentType::BGR233: + return 1; + case ComponentType::RGB565: + case ComponentType::BGR565: + case ComponentType::RGBA4: + case ComponentType::ABGR4: + case ComponentType::RGB5Alpha1: + case ComponentType::Alpha1BGR5: + return 2; + case ComponentType::RGBA8: + case ComponentType::ABGR8: + case ComponentType::RGB10Alpha2: + case ComponentType::Alpha2RGB10: + case ComponentType::Depth24Stencil8: + case ComponentType::B10GR11Float: + case ComponentType::Exponent5RGB9: + return 4; + case ComponentType::Depth32FloatStencil8: + return 8; + case ComponentType::UnsignedByte: + case ComponentType::Byte: + size = 1; break; + case ComponentType::UnsignedShort: + case ComponentType::Short: + case ComponentType::HalfFloat: + size = 2; break; + case ComponentType::UnsignedInt: + case ComponentType::Int: + case ComponentType::Float: + size = 4; break; + } + switch(format) { - case ColorFormat::Red: + case Components::Red: return 1*size; - case ColorFormat::RedGreen: + case Components::RedGreen: return 2*size; - case ColorFormat::RGB: - case ColorFormat::BGR: + case Components::RGB: + case Components::BGR: return 3*size; - case ColorFormat::RGBA: - case ColorFormat::BGRA: + case Components::RGBA: + case Components::BGRA: return 4*size; default: return 0; diff --git a/src/AbstractImage.h b/src/AbstractImage.h index c43604174..aeee55c2d 100644 --- a/src/AbstractImage.h +++ b/src/AbstractImage.h @@ -20,7 +20,6 @@ */ #include "Magnum.h" -#include "TypeTraits.h" namespace Magnum { @@ -36,42 +35,182 @@ class AbstractImage { AbstractImage& operator=(AbstractImage&& other) = delete; public: - /** @brief Color format */ - enum class ColorFormat: GLenum { - Red = GL_RED, /**< One-component (red channel) */ - RedGreen = GL_RG, /**< Two-component (red and green channel) */ - RGB = GL_RGB, /**< Three-component (RGB) */ - RGBA = GL_RGBA, /**< Four-component (RGBA) */ - BGR = GL_BGR, /**< Three-component (BGR) */ - BGRA = GL_BGRA /**< Four-component (BGRA) */ + /** + * @{ @name Image formats + * + * Note that some formats can be used only for framebuffer reading + * (using Framebuffer::read()) and some only for texture data (using + * Texture::setData() and others). + */ + + /** @brief Color components */ + enum class Components: GLenum { + Red = GL_RED, /**< One-component (red channel) */ + + /** One-component (green channel). For framebuffer reading only. */ + Green = GL_GREEN, + + /** One-component (green channel). For framebuffer reading only. */ + Blue = GL_BLUE, + + /** Two-component (red and green channel). For texture data only. */ + RedGreen = GL_RG, + + RGB = GL_RGB, /**< Three-component RGB */ + BGR = GL_BGR, /**< Three-component BGR */ + RGBA = GL_RGBA, /**< Four-component RGBA */ + BGRA = GL_BGRA, /**< Four-component BGRA */ + + /** Depth component. For framebuffer reading only. */ + Depth = GL_DEPTH_COMPONENT, + + /** Stencil index. For framebuffer reading only. */ + StencilIndex = GL_STENCIL_INDEX, + + /** Depth and stencil component. For framebuffer reading only. */ + DepthStencil = GL_DEPTH_STENCIL }; + /** @brief Data type */ + enum class ComponentType: GLenum { + UnsignedByte = GL_UNSIGNED_BYTE, /**< Each component unsigned byte */ + Byte = GL_BYTE, /**< Each component byte */ + UnsignedShort = GL_UNSIGNED_SHORT, /**< Each component unsigned short */ + Short = GL_SHORT, /**< Each component short */ + UnsignedInt = GL_UNSIGNED_INT, /**< Each component unsigned int */ + Int = GL_INT, /**< Each component int */ + + /** Each component half float (16bit). For framebuffer reading only. */ + HalfFloat = GL_HALF_FLOAT, + + Float = GL_FLOAT, /**< Each component float (32bit) */ + + /** + * Three-component RGB, unsigned normalized, red and green 3bit, + * blue 2bit, 8bit total. + */ + RGB332 = GL_UNSIGNED_BYTE_3_3_2, + + /** + * Three-component BGR, unsigned normalized, red and green 3bit, + * blue 2bit, 8bit total. + */ + BGR233 = GL_UNSIGNED_BYTE_2_3_3_REV, + + /** + * Three-component RGB, unsigned normalized, red and blue 5bit, + * green 6bit, 16bit total. + */ + RGB565 = GL_UNSIGNED_SHORT_5_6_5, + + /** + * Three-component BGR, unsigned normalized, red and blue 5bit, + * green 6bit, 16bit total. + */ + BGR565 = GL_UNSIGNED_SHORT_5_6_5_REV, + + /** + * Four-component RGBA, unsigned normalized, each component 4bit, + * 16bit total. + */ + RGBA4 = GL_UNSIGNED_SHORT_4_4_4_4, + + /** + * Four-component ABGR, unsigned normalized, each component 4bit, + * 16bit total. + */ + ABGR4 = GL_UNSIGNED_SHORT_4_4_4_4_REV, + + /** + * Four-component RGBA, unsigned normalized, each RGB component + * 5bit, alpha 1bit, 16bit total. + */ + RGB5Alpha1 = GL_UNSIGNED_SHORT_5_5_5_1, + + /** + * Four-component ABGR, unsigned normalized, each RGB component + * 5bit, alpha 1bit, 16bit total. + */ + Alpha1BGR5 = GL_UNSIGNED_SHORT_1_5_5_5_REV, + + /** + * Four-component RGBA, unsigned normalized, each component 8bit, + * 32bit total. + */ + RGBA8 = GL_UNSIGNED_INT_8_8_8_8, + + /** + * Four-component ABGR, unsigned normalized, each component 8bit, + * 32bit total. + */ + ABGR8 = GL_UNSIGNED_INT_8_8_8_8_REV, + + /** + * Four-component RGBA, unsigned normalized, each RGB component + * 10bit, alpha 2bit, 32bit total. + */ + RGB10Alpha2 = GL_UNSIGNED_INT_10_10_10_2, + + /** + * Four-component ABGR, unsigned normalized, each RGB component + * 10bit, alpha 2bit, 32bit total. + */ + Alpha2RGB10 = GL_UNSIGNED_INT_2_10_10_10_REV, + + /** + * Three-component BGR, float, red and green 11bit, blue 10bit, + * 32bit total. For framebuffer reading only. + */ + B10GR11Float = GL_UNSIGNED_INT_10F_11F_11F_REV, + + /** + * Three-component BGR, unsigned integers with exponent, each + * component 9bit, exponent 5bit, 32bit total. For framebuffer + * reading only. + */ + Exponent5RGB9 = GL_UNSIGNED_INT_5_9_9_9_REV, + + /** + * 24bit depth and 8bit stencil component, 32bit total. For + * framebuffer reading only. + */ + Depth24Stencil8 = GL_UNSIGNED_INT_24_8, + + /** + * 32bit float depth component and 8bit stencil component, 64bit + * total. For framebuffer reading only. + */ + Depth32FloatStencil8 = GL_FLOAT_32_UNSIGNED_INT_24_8_REV + }; + + /*@}*/ + /** * @brief Pixel size (in bytes) - * @param format Color format - * @param type Data type per color channel + * @param components Color components + * @param type Data type */ - static size_t pixelSize(ColorFormat format, Type type); + static size_t pixelSize(Components components, ComponentType type); /** * @brief Constructor - * @param colorFormat Color format of passed data + * @param components Color components of passed data * @param type %Image data type */ - inline AbstractImage(ColorFormat colorFormat, Type type): _colorFormat(colorFormat), _type(type) {} + inline AbstractImage(Components components, ComponentType type): _components(components), _type(type) {} /** @brief Destructor */ inline virtual ~AbstractImage() {} - /** @brief Color format */ - inline ColorFormat colorFormat() const { return _colorFormat; } + /** @brief Color components */ + inline Components components() const { return _components; } /** @brief Data type */ - inline Type type() const { return _type; } + inline ComponentType type() const { return _type; } protected: - ColorFormat _colorFormat; /**< @brief Color format */ - Type _type; /**< @brief Data type per color channel */ + Components _components; /**< @brief Color components */ + ComponentType _type; /**< @brief Data type */ }; } diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 536dc940b..e593b1023 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -94,7 +94,7 @@ class MAGNUM_EXPORT AbstractTexture { /** @{ @name Internal texture formats */ - /** @brief Number of components for each value */ + /** @brief Color components */ enum class Components { /** * Red component only. Green and blue are set to `0`, alpha is set @@ -536,11 +536,11 @@ template<> struct AbstractTexture::DataHelper<1> { } template inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, T* image) { - glTexImage1D(static_cast(target), mipLevel, internalFormat, image->dimensions().at(0), 0, static_cast(image->colorFormat()), static_cast(image->type()), image->data()); + glTexImage1D(static_cast(target), mipLevel, internalFormat, image->dimensions().at(0), 0, static_cast(image->components()), static_cast(image->type()), image->data()); } template inline static void setSub(Target target, GLint mipLevel, const Math::Vector& offset, T* image) { - glTexSubImage1D(static_cast(target), mipLevel, offset.at(0), image->dimensions().at(0), static_cast(image->colorFormat()), static_cast(image->type()), image->data()); + glTexSubImage1D(static_cast(target), mipLevel, offset.at(0), image->dimensions().at(0), static_cast(image->components()), static_cast(image->type()), image->data()); } }; template<> struct AbstractTexture::DataHelper<2> { @@ -565,11 +565,11 @@ template<> struct AbstractTexture::DataHelper<2> { } template inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, T* image) { - glTexImage2D(static_cast(target), mipLevel, internalFormat, image->dimensions().at(0), image->dimensions().at(1), 0, static_cast(image->colorFormat()), static_cast(image->type()), image->data()); + glTexImage2D(static_cast(target), mipLevel, internalFormat, image->dimensions().at(0), image->dimensions().at(1), 0, static_cast(image->components()), static_cast(image->type()), image->data()); } template inline static void setSub(Target target, GLint mipLevel, const Math::Vector& offset, T* image) { - glTexSubImage2D(static_cast(target), mipLevel, offset.at(0), offset.at(1), image->dimensions().at(0), image->dimensions().at(1), static_cast(image->colorFormat()), static_cast(image->type()), image->data()); + glTexSubImage2D(static_cast(target), mipLevel, offset.at(0), offset.at(1), image->dimensions().at(0), image->dimensions().at(1), static_cast(image->components()), static_cast(image->type()), image->data()); } }; template<> struct AbstractTexture::DataHelper<3> { @@ -587,11 +587,11 @@ template<> struct AbstractTexture::DataHelper<3> { } template inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, T* image) { - glTexImage3D(static_cast(target), mipLevel, internalFormat, image->dimensions().at(0), image->dimensions().at(1), image->dimensions().at(2), 0, static_cast(image->colorFormat()), static_cast(image->type()), image->data()); + glTexImage3D(static_cast(target), mipLevel, internalFormat, image->dimensions().at(0), image->dimensions().at(1), image->dimensions().at(2), 0, static_cast(image->components()), static_cast(image->type()), image->data()); } template inline static void setSub(Target target, GLint mipLevel, const Math::Vector& offset, T* image) { - glTexSubImage3D(static_cast(target), mipLevel, offset.at(0), offset.at(1), offset.at(2), image->dimensions().at(0), image->dimensions().at(1), image->dimensions().at(2), static_cast(image->colorFormat()), static_cast(image->type()), image->data()); + glTexSubImage3D(static_cast(target), mipLevel, offset.at(0), offset.at(1), offset.at(2), image->dimensions().at(0), image->dimensions().at(1), image->dimensions().at(2), static_cast(image->components()), static_cast(image->type()), image->data()); } }; #endif diff --git a/src/BufferedImage.cpp b/src/BufferedImage.cpp deleted file mode 100644 index ad9327744..000000000 --- a/src/BufferedImage.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright © 2010, 2011, 2012 Vladimír Vondruš - - This file is part of Magnum. - - Magnum is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License version 3 - only, as published by the Free Software Foundation. - - Magnum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License version 3 for more details. -*/ - -#include "BufferedImage.h" - -namespace Magnum { - -void BufferedImage2D::setDataFromFramebuffer(const Math::Vector2& offset) { - _buffer.bind(Buffer::Target::PixelPack); - glReadPixels(offset.at(0), offset.at(1), _dimensions.at(0), _dimensions.at(1), static_cast(_colorFormat), static_cast(_type), nullptr); -} - -} diff --git a/src/BufferedImage.h b/src/BufferedImage.h index fa6fa6505..aa6799165 100644 --- a/src/BufferedImage.h +++ b/src/BufferedImage.h @@ -21,6 +21,7 @@ #include "AbstractImage.h" #include "Buffer.h" +#include "TypeTraits.h" namespace Magnum { @@ -28,8 +29,7 @@ namespace Magnum { @brief %Buffered image Class for storing image data in GPU memory. Can be replaced with Image, which -stores image data in client memory, or for example with Trade::ImageData. See -also BufferedImage2D, which has additional data updating functions. +stores image data in client memory, or for example with Trade::ImageData. */ template class BufferedImage: public AbstractImage { public: @@ -37,27 +37,17 @@ template class BufferedImage: public AbstractImage { /** * @brief Constructor - * @param colorFormat Color format of the data. - * @param type Data type per color channel + * @param components Color components + * @param type Data type + * + * Dimensions and buffer are empty, call setData() to fill the image + * with data. */ - BufferedImage(ColorFormat colorFormat, Type type): AbstractImage(colorFormat, type), _buffer(Buffer::Target::PixelPack) {} + BufferedImage(Components components, ComponentType type): AbstractImage(components, type), _buffer(Buffer::Target::PixelPack) {} /** @brief %Image dimensions */ inline Math::Vector dimensions() const { return _dimensions; } - /** - * @brief Set image dimensions - * @param dimensions %Image dimensions - * @param usage %Image buffer usage - * - * Saves the dimensions and resizes the buffer to be able to hold - * given pixmap size. - */ - void setDimensions(const Math::Vector& dimensions, Buffer::Usage usage) { - _dimensions = dimensions; - _buffer.setData(Buffer::Target::PixelPack, pixelSize(_colorFormat, _type)*dimensions.product(), nullptr, usage); - } - /** * @brief Data * @@ -75,20 +65,35 @@ template class BufferedImage: public AbstractImage { /** * @brief Set image data + * @param dimensions %Image dimensions + * @param components Color components. Data type is detected + * from passed data array. * @param data %Image data + * @param usage %Image buffer usage * * Updates the image buffer with given data. The data are not deleted - * after filling the buffer. Note that the data must have the right - * size and type of passed data must be the same as data type passed - * in constructor. + * after filling the buffer. */ - template void setData(const T* data) { - if(TypeTraits::imageType() != _type) { - Corrade::Utility::Error() << "BufferedImage: Passed data have wrong type"; - return; - } + template inline void setData(const Math::Vector& dimensions, Components components, const T* data, Buffer::Usage usage) { + setData(dimensions, components, TypeTraits::imageType(), data, usage); + } - _buffer.setSubData(Buffer::Target::PixelPack, 0, pixelSize(_colorFormat, _type)*_dimensions.product(), data); + /** + * @brief Set image data + * @param dimensions %Image dimensions + * @param components Color components + * @param type Data type + * @param data %Image data + * @param usage %Image buffer usage + * + * Updates the image buffer with given data. The data are not deleted + * after filling the buffer. + */ + void setData(const Math::Vector& dimensions, Components components, ComponentType type, const GLvoid* data, Buffer::Usage usage) { + _components = components; + _type = type; + _dimensions = dimensions; + _buffer.setData(Buffer::Target::PixelPack, pixelSize(_components, _type)*dimensions.product(), data, usage); } protected: @@ -100,24 +105,7 @@ template class BufferedImage: public AbstractImage { typedef BufferedImage<1> BufferedImage1D; /** @brief Two-dimensional buffered image */ -class MAGNUM_EXPORT BufferedImage2D: public BufferedImage<2> { - public: - /** - * @brief Constructor - * @param colorFormat Color format of the data. - * @param type Data type per color channel - */ - /* doxygen: @copydoc BufferedImage::BufferedImage doesn't work */ - inline BufferedImage2D(ColorFormat colorFormat, Type type): BufferedImage(colorFormat, type) {} - - /** - * @brief Set image data from current framebuffer - * @param offset Offset of the pixamp to read - * - * Reads pixmap from given offset with already set dimensions. - */ - void setDataFromFramebuffer(const Math::Vector2& offset); -}; +typedef BufferedImage<2> BufferedImage2D; /** @brief Three-dimensional buffered image */ typedef BufferedImage<3> BufferedImage3D; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23a8e54ed..4aa2186b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,9 +12,7 @@ set(Magnum_SRCS AbstractImage.cpp AbstractTexture.cpp AbstractShaderProgram.cpp - BufferedImage.cpp Camera.cpp - Image.cpp Framebuffer.cpp IndexedMesh.cpp Light.cpp diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp index 0770dcd76..36da9af2c 100644 --- a/src/Framebuffer.cpp +++ b/src/Framebuffer.cpp @@ -37,4 +37,20 @@ void Framebuffer::mapForDraw(std::initializer_list colorAttachments) { delete[] attachments; } +void Framebuffer::read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, Image2D* image) { + char* data = new char[AbstractImage::pixelSize(components, type)*dimensions.product()]; + glReadPixels(offset.x(), offset.y(), dimensions.x(), dimensions.y(), static_cast(components), static_cast(type), data); + image->setData(dimensions, components, type, data); +} + +void Framebuffer::read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, BufferedImage2D* image, Buffer::Usage usage) { + /* If the buffer doesn't have sufficient size, resize it */ + /** @todo Explicitly reset also when buffer usage changes */ + if(image->dimensions() != dimensions || image->components() != components || image->type() != type) + image->setData(dimensions, components, type, nullptr, usage); + + image->buffer()->bind(Buffer::Target::PixelPack); + glReadPixels(offset.x(), offset.y(), dimensions.x(), dimensions.y(), static_cast(components), static_cast(type), nullptr); +} + } diff --git a/src/Framebuffer.h b/src/Framebuffer.h index b3690203b..d1e642578 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -19,7 +19,9 @@ * @brief Class Magnum::Framebuffer */ +#include "BufferedImage.h" #include "CubeMapTexture.h" +#include "Image.h" #include "Renderbuffer.h" namespace Magnum { @@ -167,6 +169,27 @@ class MAGNUM_EXPORT Framebuffer { glBlitFramebuffer(bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), static_cast(blitMask), static_cast(AbstractTexture::Filter::NearestNeighbor)); } + /** + * @brief Read block of pixels from framebuffer to image + * @param offset Offset in the framebuffer + * @param dimensions Image dimensions + * @param components Color components + * @param type Data type + * @param image %Image where to put the data + */ + static void read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, Image2D* image); + + /** + * @brief Read block of pixels from framebuffer to buffered image + * @param offset Offset in the framebuffer + * @param dimensions Image dimensions + * @param components Color components + * @param type Data type + * @param image Buffered image where to put the data + * @param usage %Buffer usage + */ + static void read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, BufferedImage2D* image, Buffer::Usage usage); + /** * @brief Constructor * diff --git a/src/Image.cpp b/src/Image.cpp deleted file mode 100644 index 3de3e738e..000000000 --- a/src/Image.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright © 2010, 2011, 2012 Vladimír Vondruš - - This file is part of Magnum. - - Magnum is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License version 3 - only, as published by the Free Software Foundation. - - Magnum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License version 3 for more details. -*/ - -#include "Image.h" - -namespace Magnum { - -void Image2D::setDataFromFramebuffer(const Math::Vector2& offset) { - glReadPixels(offset.at(0), offset.at(1), _dimensions.at(0), _dimensions.at(1), static_cast(_colorFormat), static_cast(_type), _data); -} - -} diff --git a/src/Image.h b/src/Image.h index cbc1694d3..bf75ae010 100644 --- a/src/Image.h +++ b/src/Image.h @@ -20,6 +20,7 @@ */ #include "AbstractImage.h" +#include "TypeTraits.h" namespace Magnum { @@ -28,8 +29,7 @@ namespace Magnum { Class for storing image data on client memory. Can be replaced with BufferedImage, which stores image data in GPU memory, or for example with -Trade::ImageData. See also Image2D, which has additional data updating -functions. +Trade::ImageData. */ template class Image: public AbstractImage { public: @@ -37,25 +37,37 @@ template class Image: public AbstractImage { /** * @brief Constructor - * @param colorFormat Color format of passed data. Data size - * per color channel is detected from format of passed data array. * @param dimensions %Image dimensions + * @param components Color components. Data type is detected + * from passed data array. * @param data %Image data with proper size * * Note that the image data are not copied on construction, but they * are deleted on class destruction. */ - template inline Image(ColorFormat colorFormat, const Math::Vector& dimensions, T* data): AbstractImage(colorFormat, TypeTraits::imageType()), _dimensions(dimensions), _data(data) {} + template inline Image(const Math::Vector& dimensions, Components components, T* data): AbstractImage(components, TypeTraits::imageType()), _dimensions(dimensions), _data(data) {} /** * @brief Constructor - * @param colorFormat Color format of passed data - * @param type Data type per color channel + * @param dimensions %Image dimensions + * @param components Color components + * @param type Data type + * @param data %Image data + * + * Note that the image data are not copied on construction, but they + * are deleted on class destruction. + */ + inline Image(const Math::Vector& dimensions, Components components, ComponentType type, GLvoid* data): AbstractImage(components, type), _dimensions(dimensions), _data(reinterpret_cast(data)) {} + + /** + * @brief Constructor + * @param components Color components + * @param type Data type * - * Dimensions and data pointer are set to zero, call - * setDimensions() and setData() to fill the image with data. + * Dimensions and data pointer are set to zero, call setData() to fill + * the image with data. */ - inline Image(ColorFormat colorFormat, Type type): AbstractImage(colorFormat, type), _data(nullptr) {} + inline Image(Components components, ComponentType type): AbstractImage(components, type), _data(nullptr) {} /** @brief Destructor */ inline ~Image() { delete[] _data; } @@ -63,38 +75,39 @@ template class Image: public AbstractImage { /** @brief %Image dimensions */ inline const Math::Vector& dimensions() const { return _dimensions; } + /** @brief Pointer to raw data */ + inline const void* data() const { return _data; } + /** - * @brief Set image dimensions - * @param dimensions %Image dimensions + * @brief Set image data + * @param dimensions %Image dimensions + * @param components Color components. Data type is detected + * from passed data array. + * @param data %Image data * - * Saves the dimensions and deletes the internal data array. + * Deletes previous data and replaces them with new. Note that the + * data are not copied, but they are deleted on destruction. */ - inline void setDimensions(const Math::Vector2& dimensions) { - _dimensions = dimensions; - delete _data; - _data = 0; + template inline void setData(const Math::Vector& dimensions, Components components, T* data) { + setData(dimensions, components, TypeTraits::imageType(), data); } - /** @brief Pointer to raw data */ - inline const void* data() const { return _data; } - /** * @brief Set image data + * @param dimensions %Image dimensions + * @param components Color components + * @param type Data type * @param data %Image data * * Deletes previous data and replaces them with new. Note that the - * data are not copied, but they are deleted on destruction. Also the - * type of passed data must be the same as data type passed in - * constructor. + * data are not copied, but they are deleted on destruction. */ - template void setData(const T* data) { - if(TypeTraits::imageType() != _type) { - Corrade::Utility::Error() << "Image: Passed data have wrong type"; - return; - } - + void setData(const Math::Vector& dimensions, Components components, ComponentType type, GLvoid* data) { delete _data; - _data = reinterpret_cast(data); + _components = components; + _type = type; + _dimensions = dimensions; + _data = reinterpret_cast(data); } protected: @@ -106,27 +119,7 @@ template class Image: public AbstractImage { typedef Image<1> Image1D; /** @brief Two-dimensional image */ -class MAGNUM_EXPORT Image2D: public Image<2> { - public: - /** - * @brief Constructor - * @param colorFormat Color format of passed data - * @param type Data type per color channel - * - * Dimensions and data pointer are are set to zero, call - * setDimensions() and setData() to fill the image with data. - */ - /* doxygen: @copydoc Image::Image doesn't work */ - inline Image2D(ColorFormat colorFormat, Type type): Image(colorFormat, type) {} - - /** - * @brief Set image data from current framebuffer - * @param offset Offset of the pixamp to read - * - * Reads pixmap from given offset with already set dimensions. - */ - void setDataFromFramebuffer(const Math::Vector2& offset); -}; +typedef Image<2> Image2D; /** @brief Three-dimensional image */ typedef Image<3> Image3D; diff --git a/src/Trade/ImageData.h b/src/Trade/ImageData.h index ad9ac4c55..cd4f8422f 100644 --- a/src/Trade/ImageData.h +++ b/src/Trade/ImageData.h @@ -20,6 +20,7 @@ */ #include "AbstractImage.h" +#include "TypeTraits.h" namespace Magnum { namespace Trade { @@ -35,15 +36,27 @@ template class ImageData: public AbstractImage { /** * @brief Constructor - * @param colorFormat Color format of passed data. Data size - * per color channel is detected from format of passed data array. * @param dimensions %Image dimensions + * @param components Color components. Data type is detected + * from passed data array. * @param data %Image data * - * @attention Note that the image data are not copied on construction, - * but they are deleted on class destruction. + * Note that the image data are not copied on construction, but they + * are deleted on class destruction. */ - template inline ImageData(ColorFormat colorFormat, const Math::Vector& dimensions, const T* data): AbstractImage(colorFormat, TypeTraits::imageType()), _dimensions(dimensions), _data(reinterpret_cast(data)) {} + template inline ImageData(const Math::Vector& dimensions, Components components, T* data): AbstractImage(components, TypeTraits::imageType()), _dimensions(dimensions), _data(reinterpret_cast(data)) {} + + /** + * @brief Constructor + * @param dimensions %Image dimensions + * @param components Color components + * @param type Data type + * @param data %Image data + * + * Note that the image data are not copied on construction, but they + * are deleted on class destruction. + */ + inline ImageData(const Math::Vector& dimensions, Components components, ComponentType type, GLvoid* data): AbstractImage(components, type), _dimensions(dimensions), _data(reinterpret_cast(data)) {} /** @brief Destructor */ inline virtual ~ImageData() { delete[] _data; } @@ -56,7 +69,7 @@ template class ImageData: public AbstractImage { private: Math::Vector _dimensions; - const char* _data; + char* _data; }; /** @brief One-dimensional image */ diff --git a/src/TypeTraits.h b/src/TypeTraits.h index d9859f91f..b50258d16 100644 --- a/src/TypeTraits.h +++ b/src/TypeTraits.h @@ -19,7 +19,7 @@ * @brief Enum Magnum::Type, class Magnum::TypeOf, Magnum::TypeInfo, Magnum::TypeTraits */ -#include "Magnum.h" +#include "AbstractImage.h" namespace Magnum { @@ -56,7 +56,7 @@ template struct TypeTraits: public Math::TypeTraits { * GLubyte. This function is not present for types unusable for image data, * like GLdouble and Matrix3. */ - constexpr inline static Type imageType(); + constexpr inline static AbstractImage::ComponentType imageType(); /** * @brief Size of plain OpenGL type @@ -149,7 +149,7 @@ template<> struct TypeOf { typedef GLdouble Type; }; template<> struct TypeTraits: public Math::TypeTraits { inline constexpr static Type type() { return Type::UnsignedByte; } inline constexpr static Type indexType() { return Type::UnsignedByte; } - inline constexpr static Type imageType() { return Type::UnsignedByte; } + inline constexpr static AbstractImage::ComponentType imageType() { return AbstractImage::ComponentType::UnsignedByte; } inline constexpr static size_t size() { return sizeof(GLubyte); } inline constexpr static size_t count() { return 1; } }; @@ -157,7 +157,7 @@ template<> struct TypeTraits: public Math::TypeTraits { template<> struct TypeTraits: public Math::TypeTraits { inline constexpr static Type type() { return Type::Byte; } /* Can not be used for indices */ - inline constexpr static Type imageType() { return Type::Byte; } + inline constexpr static AbstractImage::ComponentType imageType() { return AbstractImage::ComponentType::Byte; } inline constexpr static size_t size() { return sizeof(GLbyte); } inline constexpr static size_t count() { return 1; } }; @@ -165,7 +165,7 @@ template<> struct TypeTraits: public Math::TypeTraits { template<> struct TypeTraits: public Math::TypeTraits { inline constexpr static Type type() { return Type::UnsignedShort; } inline constexpr static Type indexType() { return Type::UnsignedShort; } - inline constexpr static Type imageType() { return Type::UnsignedShort; } + inline constexpr static AbstractImage::ComponentType imageType() { return AbstractImage::ComponentType::UnsignedShort; } inline constexpr static size_t size() { return sizeof(GLushort); } inline constexpr static size_t count() { return 1; } }; @@ -173,7 +173,7 @@ template<> struct TypeTraits: public Math::TypeTraits template<> struct TypeTraits: public Math::TypeTraits { inline constexpr static Type type() { return Type::Short; } /* Can not be used for indices */ - inline constexpr static Type imageType() { return Type::Short; } + inline constexpr static AbstractImage::ComponentType imageType() { return AbstractImage::ComponentType::Short; } inline constexpr static size_t size() { return sizeof(GLshort); } inline constexpr static size_t count() { return 1; } }; @@ -181,7 +181,7 @@ template<> struct TypeTraits: public Math::TypeTraits { template<> struct TypeTraits: public Math::TypeTraits { inline constexpr static Type type() { return Type::UnsignedInt; } inline constexpr static Type indexType() { return Type::UnsignedInt; } - inline constexpr static Type imageType() { return Type::UnsignedInt; } + inline constexpr static AbstractImage::ComponentType imageType() { return AbstractImage::ComponentType::UnsignedInt; } inline constexpr static size_t size() { return sizeof(GLuint); } inline constexpr static size_t count() { return 1; } }; @@ -189,7 +189,7 @@ template<> struct TypeTraits: public Math::TypeTraits { template<> struct TypeTraits: public Math::TypeTraits { inline constexpr static Type type() { return Type::Int; } /* Can not be used for indices */ - inline constexpr static Type imageType() { return Type::Int; } + inline constexpr static AbstractImage::ComponentType imageType() { return AbstractImage::ComponentType::Int; } inline constexpr static size_t size() { return sizeof(GLint); } inline constexpr static size_t count() { return 1; } }; @@ -197,7 +197,7 @@ template<> struct TypeTraits: public Math::TypeTraits { template<> struct TypeTraits: public Math::TypeTraits { inline constexpr static Type type() { return Type::Float; } /* Can not be used for indices */ - inline constexpr static Type imageType() { return Type::Float; } + inline constexpr static AbstractImage::ComponentType imageType() { return AbstractImage::ComponentType::Float; } inline constexpr static size_t size() { return sizeof(GLfloat); } inline constexpr static size_t count() { return 1; } };