shithub: rgbds

Download patch

ref: a5ed0292b110606df51f607427cdd17f86f10f04
parent: 05e36767b0d3dcf64e9a37bbd0a2cc93771dfbfd
author: ISSOtm <[email protected]>
date: Fri May 20 14:27:54 EDT 2022

Reject colors with ambiguous alpha channel

--- 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 <cstdint>
 #include <stdint.h>
 
 struct Rgba {
@@ -50,12 +51,10 @@
 	 */
 	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
 	 */
--- a/src/gfx/process.cpp
+++ b/src/gfx/process.cpp
@@ -323,10 +323,22 @@
 		// 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<std::tuple<uint32_t, uint32_t>> conflicts;
+		// Holds colors whose alpha value is ambiguous
+		std::vector<uint32_t> 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()) {
--- a/src/gfx/rgba.cpp
+++ b/src/gfx/rgba.cpp
@@ -33,6 +33,7 @@
 	if (isTransparent()) {
 		return transparent;
 	}
+	assert(isOpaque());
 
 	uint8_t r = red, g = green, b = blue;
 	if (options.useColorCurve) {