From c731cda1a2ec83fa03fb3d5e01fb55c655c1a620 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 3 Nov 2020 14:20:36 +0100 Subject: [PATCH] Spectre/Graphics/PixelFormat: Rework source/Graphics/Image/IcoFormat.cpp: use new PixelFormat. source/Graphics/Image.cpp: update to confirm with new PixelFormat Spectre/Graphics/PixelFormat: add PF_getNumChannels() Spectre/Graphics/PixelFormat: Rework the enum with proper naming convention and documentation. --- engine.build.lua | 1 + include/Spectre/Graphics/PixelFormat.h | 41 ++++++++++++++++++++++---- source/Graphics/Image.cpp | 17 +++++------ source/Graphics/Image/IcoFormat.cpp | 4 +-- source/Graphics/PixelFormat.cpp | 26 ++++++++++++++++ 5 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 source/Graphics/PixelFormat.cpp diff --git a/engine.build.lua b/engine.build.lua index 64a7ecb..9d3f97b 100644 --- a/engine.build.lua +++ b/engine.build.lua @@ -100,6 +100,7 @@ local graphics_module = Module("source/Graphics", { "Image.cpp", "ImageLoader.cpp", "Image/IcoFormat.cpp", + "PixelFormat.cpp", "OpenGL.cpp", "GL/glad.c", diff --git a/include/Spectre/Graphics/PixelFormat.h b/include/Spectre/Graphics/PixelFormat.h index b2a1ac4..c39e311 100644 --- a/include/Spectre/Graphics/PixelFormat.h +++ b/include/Spectre/Graphics/PixelFormat.h @@ -1,18 +1,49 @@ #ifndef SPECTRE_GRAPHICS_PIXELFORMAT_H #define SPECTRE_GRAPHICS_PIXELFORMAT_H +#include + namespace sp { enum PixelFormat { PF_Unknown = 0, - PF_RGB = 1, // Standard RGB: 24 bits per pixel, 8 bits are used for red, green, blue. - PF_RGBA = 2, // Standard RGBA: 32 bits per pixel, 8 bits are used for red, green, blue, alpha. - PF_32BGR = 3, // 32 bits per pixel, 8 bits are used for blue, green, red. Last 8 bits are unused. - PF_32BGRA = 4, // 32 bits per pixel, 8 bits are used for blue, green, red, alpha. - PF_Alpha = 5, // 8 bit alpha channel. + PF_Alpha = 1, // 8 bit alpha channel. + + // Byte-order formats. + // Pixels are always ordered with the first channel at the first byte, second channel at the second byte. + // --------------------------- + + PF_RGB = 2, // Standard RGB: 24 bits per pixel, 8 bits are used for red, green, blue. + PF_RGBX = 3, // 32 bits per pixel, 8 bits are used for red, green, Last 8 bits are unused. + PF_RGBA = 4, // Standard RGBA: 32 bits per pixel, 8 bits are used for red, green, blue, alpha. + PF_BGR = 5, // 24 bits per pixel, 8 bits are used for blue, green, red. + PF_BGRX = 6, // 32 bits per pixel, 8 bits are used for blue, green, red. Last 8 bits are unused. + PF_BGRA = 7, // 32 bits per pixel, 8 bits are used for blue, green, red, alpha. + + // Packed formats. + // --------------------------- + + // 32-bit: Pixels are in ordered in 32-bit words. where the first channel is stored at the most significant byte (MSB). + // these formats are architecture dependant (litte/big-endian). + // (MSB) | byte 0 | byte 1 | byte 2 | byte 3 | (LSB) + PF_RGBX32 = 8, // | rrrr rrrr | gggg gggg | bbbb bbbb | xxxx xxxx | + PF_RGBA32 = 9, // | rrrr rrrr | gggg gggg | bbbb bbbb | aaaa aaaa | + PF_BGRX32 = 10, // | bbbb bbbb | gggg gggg | rrrr rrrr | xxxx xxxx | + PF_BGRA32 = 11, // | bbbb bbbb | gggg gggg | rrrr rrrr | aaaa aaaa | + + // 24-bit (unsuppored for now) + //PF_RGB24 = 12, // | rrrr rrrr | gggg gggg | bbbb bbbb | + //PF_BGR24 = 13, // | bbbb bbbb | gggg gggg | rrrr rrrr | + + // 16-bit (unsuppored for now) + //PF_RGB565 = 14, // | rrrr rggg | gggb bbbb | + //PF_RGBA5551 = 15 // | rrrr rggg | ggb bbbba | + //PF_RGBX5551 = 16 // | rrrr rggg | ggb bbbbx | }; +uint8_t PF_getNumChannels(enum PixelFormat format); + } // namespace #endif /* SPECTRE_GRAPHICS_PIXELFORMAT_H */ diff --git a/source/Graphics/Image.cpp b/source/Graphics/Image.cpp index 6228e5f..cb469b1 100644 --- a/source/Graphics/Image.cpp +++ b/source/Graphics/Image.cpp @@ -165,29 +165,28 @@ void Image::flipY() void Image::setPixels(const void *pixels, PixelFormat format) { - switch(format) { - case PixelFormat::PF_RGB : - case PixelFormat::PF_32BGR : - m_channels = RGB; - break; - case PixelFormat::PF_RGBA : - case PixelFormat::PF_32BGRA : + switch(PF_getNumChannels(format)) { + case 4: m_channels = RGBA; break; + case 3: + m_channels = RGB; + break; default : m_channels = Alpha; } m_pixels.resize(m_size.y * getStride()); - if (format == PixelFormat::PF_32BGR || format == PixelFormat::PF_32BGRA) { + // TODO: Move pixel format convertion to it's own function(s) + if (format == PixelFormat::PF_BGR || format == PixelFormat::PF_BGRA) { const uint8_t *ptr = (const uint8_t *) pixels; for(int i = 0; i < m_pixels.size(); i += 4) { m_pixels[i+0] = ptr[2]; m_pixels[i+1] = ptr[1]; m_pixels[i+2] = ptr[0]; - if (format == PixelFormat::PF_32BGRA) { + if (format == PixelFormat::PF_BGRA) { m_pixels[i+3] = ptr[3]; } ptr += 4; diff --git a/source/Graphics/Image/IcoFormat.cpp b/source/Graphics/Image/IcoFormat.cpp index 721a106..14ec25b 100644 --- a/source/Graphics/Image/IcoFormat.cpp +++ b/source/Graphics/Image/IcoFormat.cpp @@ -61,9 +61,9 @@ bool IcoFormat::decode(Image& img, const unsigned char *data, unsigned size) largest = findLargestImage(ent, num_ent); if (largest->bpp == 32) { - format = PixelFormat::PF_32BGRA; + format = PixelFormat::PF_BGRA; } else { - format = PixelFormat::PF_32BGR; + format = PixelFormat::PF_BGR; } // NOTE: plus 40 bytes here to skip over the DIB header. diff --git a/source/Graphics/PixelFormat.cpp b/source/Graphics/PixelFormat.cpp new file mode 100644 index 0000000..1bdee3f --- /dev/null +++ b/source/Graphics/PixelFormat.cpp @@ -0,0 +1,26 @@ + +#include + +namespace sp { + +uint8_t PF_getNumChannels(enum PixelFormat format) +{ + switch(format) { + case PixelFormat::PF_RGBA : + case PixelFormat::PF_RGBA32 : + case PixelFormat::PF_BGRA : + case PixelFormat::PF_BGRA32 : + return 4; + case PixelFormat::PF_RGB : + case PixelFormat::PF_RGBX : + case PixelFormat::PF_RGBX32 : + case PixelFormat::PF_BGR : + case PixelFormat::PF_BGRX : + case PixelFormat::PF_BGRX32 : + return 3; + default : + return 1; + } +} + +} // namespace sp