From f7fcc2633c03c1a5cfa2a548c11c6a0e076ba274 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 22 Oct 2020 13:05:41 +0200 Subject: [PATCH] Graphics/Image: dont store PixelFormat, instead define a new enum for number of channels. The image class has a strict internal representation so we dont need "format". PixelFormat enum can be passed to functions that modify the pixel data (like setPixels()) so that a proper convertion can be done. --- include/Spectre/Graphics/Image.h | 19 ++-- .../Graphics/Font/Engine/FreeTypeEngine.cpp | 5 +- source/Graphics/Image.cpp | 101 +++++++----------- source/Graphics/Texture.cpp | 14 +-- 4 files changed, 53 insertions(+), 86 deletions(-) diff --git a/include/Spectre/Graphics/Image.h b/include/Spectre/Graphics/Image.h index 11af7dc..51fd3ab 100644 --- a/include/Spectre/Graphics/Image.h +++ b/include/Spectre/Graphics/Image.h @@ -13,13 +13,16 @@ namespace sp { class Image { public : + enum Channels { + Alpha, + RGB, + RGBA + }; + Image(); - void create(unsigned width, unsigned height, const Color& color = Color::Black); - - void create(unsigned width, unsigned height, const void* pixels); - void create(PixelFormat format, unsigned width, unsigned height, const Color& color = Color::Black); - void create(PixelFormat format, unsigned width, unsigned height, const void* pixels); + void create(unsigned width, unsigned height, const Color& color = Color::Black, enum Channels comp = Channels::RGBA); + void create(unsigned width, unsigned height, const void* pixels, PixelFormat format = PixelFormat::PF_RGBA); const Vector2u& getSize() const; @@ -27,7 +30,7 @@ public : unsigned int getHeight() const; - unsigned int getBpp() const; + unsigned int getNumChannels() const; unsigned int getStride() const; @@ -46,7 +49,7 @@ public : Color getPixel(unsigned x, unsigned y) const; - void setPixels(const void* pixels); + void setPixels(const void* pixels, PixelFormat format = PixelFormat::PF_RGBA); const unsigned char* getPixels() const; @@ -56,7 +59,7 @@ private : Vector2u m_size; - PixelFormat m_format; + enum Channels m_channels; std::vector m_pixels; }; diff --git a/source/Graphics/Font/Engine/FreeTypeEngine.cpp b/source/Graphics/Font/Engine/FreeTypeEngine.cpp index e82e73b..2c546b9 100644 --- a/source/Graphics/Font/Engine/FreeTypeEngine.cpp +++ b/source/Graphics/Font/Engine/FreeTypeEngine.cpp @@ -99,10 +99,7 @@ Glyph FreeTypeEngine::loadGlyph(unsigned int codepoint, Image& img, unsigned int FT_Glyph_To_Bitmap(&glyph_info, FT_RENDER_MODE_NORMAL, 0, true); FT_Bitmap& bmp = reinterpret_cast(glyph_info)->bitmap; - img.create(PixelFormat::PF_Alpha, - bmp.width, - bmp.rows, - bmp.buffer); + img.create(bmp.width, bmp.rows, bmp.buffer, PixelFormat::PF_Alpha); glyph.offset.x = static_cast(metrics.horiBearingX / (1 << 6)); glyph.offset.y = static_cast(metrics.horiBearingY / (1 << 6)); diff --git a/source/Graphics/Image.cpp b/source/Graphics/Image.cpp index f04de34..f01c9c5 100644 --- a/source/Graphics/Image.cpp +++ b/source/Graphics/Image.cpp @@ -10,17 +10,17 @@ static ImageLoader _loader; Image::Image() : m_size (0, 0), -m_format (PF_Unknown) +m_channels (RGBA) { } -void Image::create(unsigned width, unsigned height, const Color& color) +void Image::create(unsigned width, unsigned height, const Color& color, enum Channels comp) { m_size.x = width; m_size.y = height; - m_format = PixelFormat::PF_RGBA; + m_channels = comp; - m_pixels.resize(m_size.x * m_size.y * (getBpp() / 8)); + m_pixels.resize(m_size.x * m_size.y * getNumChannels()); for(size_t i = 0; i < m_pixels.size(); i += 4) { @@ -31,48 +31,12 @@ void Image::create(unsigned width, unsigned height, const Color& color) } } -void Image::create(unsigned width, unsigned height, const void* pixels) -{ - create(PixelFormat::PF_RGBA, width, height, pixels); -} - -void Image::create(PixelFormat format, unsigned width, unsigned height, const Color& color) +void Image::create(unsigned width, unsigned height, const void* pixels, PixelFormat format) { m_size.x = width; m_size.y = height; - m_format = format; - m_pixels.resize(m_size.x * m_size.y * (getBpp() / 8)); - - if (getBpp() == 32) { - for(size_t i = 0; i < m_pixels.size(); i += 4) { - - m_pixels[i+0] = color.r; - m_pixels[i+1] = color.g; - m_pixels[i+2] = color.b; - m_pixels[i+3] = color.a; - } - } else if (getBpp() == 24) { - for(size_t i = 0; i < m_pixels.size(); i += 3) { - - m_pixels[i+0] = color.r; - m_pixels[i+1] = color.g; - m_pixels[i+2] = color.b; - } - } else { - for(size_t i = 0; i < m_pixels.size(); i += 1) { - m_pixels[i] = color.a; - } - } -} - -void Image::create(PixelFormat format, unsigned width, unsigned height, const void* pixels) -{ - m_size.x = width; - m_size.y = height; - m_format = format; - - setPixels(pixels); + setPixels(pixels, format); } const Vector2u& Image::getSize() const @@ -90,31 +54,36 @@ unsigned int Image::getHeight() const return m_size.y; } -unsigned int Image::getBpp() const +unsigned int Image::getNumChannels() const { - switch(m_format) { - case PixelFormat::PF_RGBA : return 32; - case PixelFormat::PF_RGB : return 24; - case PixelFormat::PF_Alpha : return 8; - case PixelFormat::PF_Unknown : + switch(m_channels) { + case Channels::RGBA : return 4; + case Channels::RGB : return 3; + case Channels::Alpha : default : break; } - return 0; + return 1; } unsigned int Image::getStride() const { - return m_size.x * (getBpp() / 8); + return m_size.x * getNumChannels(); } PixelFormat Image::getFormat() const { - return m_format; + switch(m_channels) { + case Channels::RGBA : return PixelFormat::PF_RGBA; + case Channels::RGB : return PixelFormat::PF_RGB; + case Channels::Alpha : + default : break; + } + return PixelFormat::PF_Alpha; } bool Image::hasAlpha() const { - return m_format == PixelFormat::PF_RGBA || m_format == PixelFormat::PF_Alpha; + return m_channels != Channels::RGB; } bool Image::loadFromFile(const std::string& filename) @@ -138,17 +107,17 @@ void Image::saveToFile(const std::string& filename) const void Image::setPixel(unsigned x, unsigned y, const Color& c) { - unsigned char *base = m_pixels.data() + ((getBpp() / 8) * ((y * m_size.x) + x)); + unsigned char *base = m_pixels.data() + (getNumChannels() * ((y * m_size.x) + x)); - if (m_format == PixelFormat::PF_RGB || m_format == PixelFormat::PF_RGBA) { + if (m_channels == RGB || m_channels == RGBA) { base[0] = c.r; base[1] = c.g; base[2] = c.b; - if (m_format == PixelFormat::PF_RGBA) { + if (m_channels == RGBA) { base[3] = c.a; } } - else if (m_format == PixelFormat::PF_Alpha) { + else if (m_channels == Alpha) { base[0] = c.a; } } @@ -156,21 +125,21 @@ void Image::setPixel(unsigned x, unsigned y, const Color& c) Color Image::getPixel(unsigned x, unsigned y) const { Color c; - const unsigned char *base = m_pixels.data() + ((getBpp() / 8) * ((y * m_size.x) + x)); + const unsigned char *base = m_pixels.data() + (getNumChannels() * ((y * m_size.x) + x)); // RGB / RGBA formats. - if (m_format == PixelFormat::PF_RGB || m_format == PixelFormat::PF_RGBA) { + if (m_channels == RGB || m_channels == RGBA) { c.r = base[0]; c.g = base[1]; c.b = base[2]; - if (m_format == PixelFormat::PF_RGBA) { + if (m_channels == RGBA) { c.a = base[3]; } else { c.a = 255; } } // Alpha, single channel format. - else if (m_format == PixelFormat::PF_Alpha) { + else if (m_channels == Alpha) { c = Color(0, 0, 0, base[0]); } return c; @@ -194,11 +163,17 @@ void Image::flipY() } } -void Image::setPixels(const void *pixels) +void Image::setPixels(const void *pixels, PixelFormat format) { - unsigned int size = m_size.y * getStride(); + if (format == PixelFormat::PF_RGB) { + m_channels = RGB; + } else if (format == PixelFormat::PF_RGBA) { + m_channels = RGBA; + } else if (format == PixelFormat::PF_Alpha) { + m_channels = Alpha; + } - m_pixels.resize(size); + m_pixels.resize(m_size.y * getStride()); memcpy(&m_pixels[0], pixels, m_pixels.size()); } diff --git a/source/Graphics/Texture.cpp b/source/Graphics/Texture.cpp index ddf8397..b9afffe 100644 --- a/source/Graphics/Texture.cpp +++ b/source/Graphics/Texture.cpp @@ -89,11 +89,7 @@ void Texture::create(const Image& image) enable(); - if (image.getBpp() == 32) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - } + glPixelStorei(GL_UNPACK_ALIGNMENT, image.getNumChannels()); srcFormat = pixelFormatToGL(image.getFormat()); glFormat = pixelFormatToInternal(image.getFormat()); @@ -149,11 +145,7 @@ void Texture::update(vec2u pos, const Image& image) enable(); - if (image.getFormat() == PixelFormat::PF_RGBA) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - } + glPixelStorei(GL_UNPACK_ALIGNMENT, image.getNumChannels()); format = pixelFormatToGL(image.getFormat()); @@ -185,7 +177,7 @@ Image Texture::copyToImage() const GL_UNSIGNED_BYTE, &pixels[0]); - img.create(m_format, m_size.x, m_size.y, &pixels[0]); + img.create(m_size.x, m_size.y, &pixels[0], m_format); disable(); }