From a5ed0292b110606df51f607427cdd17f86f10f04 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Fri, 20 May 2022 18:27:54 +0200 Subject: [PATCH] Reject colors with ambiguous alpha channel --- include/gfx/rgba.hpp | 11 +++++------ src/gfx/process.cpp | 16 ++++++++++++++-- src/gfx/rgba.cpp | 1 + 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/include/gfx/rgba.hpp b/include/gfx/rgba.hpp index 3f71fe19..427a1232 100644 --- a/include/gfx/rgba.hpp +++ b/include/gfx/rgba.hpp @@ -9,6 +9,7 @@ #ifndef RGBDS_GFX_RGBA_HPP #define RGBDS_GFX_RGBA_HPP +#include #include struct Rgba { @@ -50,12 +51,10 @@ struct Rgba { */ static constexpr uint16_t transparent = 0b1'00000'00000'00000; - /** - * All alpha values strictly below this will be considered transparent - */ - static constexpr uint8_t opacity_threshold = 0xF0; // TODO: adjust this - // TODO: also a transparency threshold, and error out on "middle" values - bool isTransparent() const { return alpha < opacity_threshold; } + static constexpr uint8_t transparency_threshold = 0x10; + bool isTransparent() const { return alpha < transparency_threshold; } + static constexpr uint8_t opacity_threshold = 0xF0; + bool isOpaque() const { return alpha >= opacity_threshold; } /** * Computes the equivalent CGB color, respects the color curve depending on options */ diff --git a/src/gfx/process.cpp b/src/gfx/process.cpp index f1f75688..26778baa 100644 --- a/src/gfx/process.cpp +++ b/src/gfx/process.cpp @@ -323,10 +323,22 @@ public: // assigned, and conflicts always occur between that and another color. // For the same reason, we don't need to worry about order, either. std::vector> conflicts; + // Holds colors whose alpha value is ambiguous + std::vector indeterminates; // Assign a color to the given position, and register it in the image palette as well - auto assignColor = [this, &conflicts](png_uint_32 x, png_uint_32 y, Rgba &&color) { - if (Rgba const *other = colors.registerColor(color); other) { + auto assignColor = [this, &conflicts, &indeterminates](png_uint_32 x, png_uint_32 y, + Rgba &&color) { + if (!color.isTransparent() && !color.isOpaque()) { + uint32_t css = color.toCSS(); + if (std::find(indeterminates.begin(), indeterminates.end(), css) + == indeterminates.end()) { + error( + "Color #%08x is neither transparent (alpha < %u) nor opaque (alpha >= %u)", + css, Rgba::transparency_threshold, Rgba::opacity_threshold); + indeterminates.push_back(css); + } + } else if (Rgba const *other = colors.registerColor(color); other) { std::tuple conflicting{color.toCSS(), other->toCSS()}; // Do not report combinations twice if (std::find(conflicts.begin(), conflicts.end(), conflicting) == conflicts.end()) { diff --git a/src/gfx/rgba.cpp b/src/gfx/rgba.cpp index 20c78f93..1bea2b7a 100644 --- a/src/gfx/rgba.cpp +++ b/src/gfx/rgba.cpp @@ -33,6 +33,7 @@ uint16_t Rgba::cgbColor() const { if (isTransparent()) { return transparent; } + assert(isOpaque()); uint8_t r = red, g = green, b = blue; if (options.useColorCurve) {