diff --git a/include/pixel/RgbaColor.h b/include/pixel/RgbaColor.h index 6fc0755..659e7d2 100644 --- a/include/pixel/RgbaColor.h +++ b/include/pixel/RgbaColor.h @@ -26,6 +26,15 @@ namespace pixel { public: // maybe provide ctors? + constexpr RgbaColor() = default; + + constexpr RgbaColor(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a) + : r(r), + g(g), + b(b), + a(a) { + } + struct { std::uint8_t r; std::uint8_t g; @@ -39,8 +48,8 @@ namespace pixel { // TODO: Maybe: // - // RgbaColor ColorFrom16Bpp(uint16_t, endian); - // unique_ptr PaletteFrom16Bpp(span, endian); + static RgbaColor ColorFrom16Bpp(std::uint16_t); + static void PaletteFrom16Bpp(RgbaColor* dest, const std::uint8_t* src, std::size_t colorCount); }; } // namespace pixel diff --git a/include/pixel/RgbaImage.h b/include/pixel/RgbaImage.h index 1a30f1b..1b900fe 100644 --- a/include/pixel/RgbaImage.h +++ b/include/pixel/RgbaImage.h @@ -82,10 +82,14 @@ namespace pixel { */ [[nodiscard]] ImageSize GetSize() const; - // TODO: Add these methods, to make sampling data a bit nicer. - // - // static RgbaImage From4Bpp(span data, span palette, ImageSize size); - // static RgbaImage From8Bpp(span data, span palette, ImageSize size); + // Methods for easy sampling/conversion. + // Note: + // Palette for all palletized formats is expected to have + // been converted via RgbaColor::PaletteFrom*Bpp() or + // already in RgbaColor format. + + static RgbaImage From4Bpp(const std::uint8_t* data, const RgbaColor* palette, ImageSize size); + static RgbaImage From8Bpp(const std::uint8_t* data, const RgbaColor* palette, ImageSize size); // static RgbaImage From16Bpp(span data, ImageSize size); // static RgbaImage From32Bpp(span data, ImageSize size); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b21ebe..d86b7c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(pixel_libpixel stb_impl.cpp + RgbaColor.cpp RgbaImage.cpp ImageWriter.cpp ) diff --git a/src/RgbaColor.cpp b/src/RgbaColor.cpp new file mode 100644 index 0000000..e4c0ec3 --- /dev/null +++ b/src/RgbaColor.cpp @@ -0,0 +1,32 @@ +// +// libpixel +// +// (C) 2021-2022 modeco80 +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +#include + +namespace pixel { + + // could be made constexpr probably.. + + RgbaColor RgbaColor::ColorFrom16Bpp(std::uint16_t color) { + return { + static_cast((color & 0x001F) << 3), + static_cast((color & 0x03E0) >> 2), + static_cast((color & 0x7C00) >> 7), + 255 + }; + } + + void RgbaColor::PaletteFrom16Bpp(RgbaColor* dest, const std::uint8_t* src, std::size_t colorCount) { + for(int i = 0; i < colorCount; ++i) { + const auto colorIndex = i * sizeof(std::uint16_t); + const std::uint16_t colorWord = (src[colorIndex + 1] << 8) | src[colorIndex]; + dest[i] = RgbaColor::ColorFrom16Bpp(colorWord); + } + } + +} // namespace pixel \ No newline at end of file diff --git a/src/RgbaImage.cpp b/src/RgbaImage.cpp index 962c854..168dc48 100644 --- a/src/RgbaImage.cpp +++ b/src/RgbaImage.cpp @@ -55,4 +55,25 @@ namespace pixel { return size; } + RgbaImage RgbaImage::From4Bpp(const std::uint8_t* data, const RgbaColor* palette, ImageSize size) { + RgbaImage image(size); + auto* buffer = image.GetBuffer(); + + for(std::size_t i = 0; i < (size.width * size.height / 2); ++i) + for(std::size_t b = 0; b < 2; b++) + *(buffer++) = palette[static_cast(((data[i] & (0x0F << (b * 4))) >> (b * 4)))]; + + return image; + } + + RgbaImage RgbaImage::From8Bpp(const std::uint8_t* data, const RgbaColor* palette, ImageSize size) { + RgbaImage image(size); + auto* buffer = image.GetBuffer(); + + for(std::size_t i = 0; i < size.width * size.height; ++i) + *(buffer++) = palette[data[i]]; + + return image; + } + } // namespace pixel \ No newline at end of file