From 952ee02d3e5fe14094c8ee2e5757469ce6b632a6 Mon Sep 17 00:00:00 2001 From: Rangi42 Date: Sun, 20 Oct 2024 13:23:33 -0400 Subject: [PATCH] Fix detection of tiles with too many colors --- include/gfx/proto_palette.hpp | 8 ++----- src/gfx/process.cpp | 42 +++++++++++++++++------------------ src/gfx/proto_palette.cpp | 9 ++++---- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/include/gfx/proto_palette.hpp b/include/gfx/proto_palette.hpp index fc75e9bd8..88f5476e9 100644 --- a/include/gfx/proto_palette.hpp +++ b/include/gfx/proto_palette.hpp @@ -18,12 +18,8 @@ class ProtoPalette { std::array _colorIndices{UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX}; public: - /* - * Adds the specified color to the set, or **silently drops it** if the set is full. - * - * Returns whether the color was unique. - */ - bool add(uint16_t color); + // Adds the specified color to the set, or **silently drops it** if the set is full. + void add(uint16_t color); enum ComparisonResult { NEITHER, diff --git a/src/gfx/process.cpp b/src/gfx/process.cpp index 604ac1c84..b68bda977 100644 --- a/src/gfx/process.cpp +++ b/src/gfx/process.cpp @@ -1115,23 +1115,32 @@ void process() { DefaultInitVec attrmap{}; for (auto tile : png.visitAsTiles()) { - ProtoPalette tileColors; + ProtoPalette protoPalette; AttrmapEntry &attrs = attrmap.emplace_back(); - uint8_t nbColorsInTile = 0; + std::unordered_set tileColors; for (uint32_t y = 0; y < 8; ++y) { for (uint32_t x = 0; x < 8; ++x) { Rgba color = tile.pixel(x, y); if (!color.isTransparent()) { // Do not count transparency in for packing - // Add the color to the proto-pal (if not full), and count it if it was unique. - if (tileColors.add(color.cgbColor())) { - ++nbColorsInTile; - } + uint16_t cgbColor = color.cgbColor(); + protoPalette.add(cgbColor); + tileColors.insert(cgbColor); } } } - if (tileColors.empty()) { + if (tileColors.size() > options.maxOpaqueColors()) { + fatal( + "Tile at (%" PRIu32 ", %" PRIu32 ") has %zu colors, more than %" PRIu8 "!", + tile.x, + tile.y, + tileColors.size(), + options.maxOpaqueColors() + ); + } + + if (protoPalette.empty()) { // "Empty" proto-palettes screw with the packing process, so discard those attrs.protoPaletteID = AttrmapEntry::transparent; continue; @@ -1139,9 +1148,9 @@ void process() { // Insert the proto-palette, making sure to avoid overlaps for (size_t n = 0; n < protoPalettes.size(); ++n) { - switch (tileColors.compare(protoPalettes[n])) { + switch (protoPalette.compare(protoPalettes[n])) { case ProtoPalette::WE_BIGGER: - protoPalettes[n] = tileColors; // Override them + protoPalettes[n] = protoPalette; // Override them // Remove any other proto-palettes that we encompass // (Example [(0, 1), (0, 2)], inserting (0, 1, 2)) /* @@ -1151,7 +1160,7 @@ void process() { * Investigation is necessary, especially if pathological cases are found. * * for (size_t i = protoPalettes.size(); --i != n;) { - * if (tileColors.compare(protoPalettes[i]) == ProtoPalette::WE_BIGGER) { + * if (protoPalette.compare(protoPalettes[i]) == ProtoPalette::WE_BIGGER) { * protoPalettes.erase(protoPalettes.begin() + i); * } * } @@ -1168,17 +1177,6 @@ void process() { } } - if (nbColorsInTile > options.maxOpaqueColors()) { - fatal( - "Tile at (%" PRIu32 ", %" PRIu32 ") has %" PRIu8 " opaque colors, more than %" PRIu8 - "!", - tile.x, - tile.y, - nbColorsInTile, - options.maxOpaqueColors() - ); - } - attrs.protoPaletteID = protoPalettes.size(); if (protoPalettes.size() == AttrmapEntry::transparent) { // Check for overflow fatal( @@ -1186,7 +1184,7 @@ void process() { AttrmapEntry::transparent ); } - protoPalettes.push_back(tileColors); + protoPalettes.push_back(protoPalette); continue_visiting_tiles:; } diff --git a/src/gfx/proto_palette.cpp b/src/gfx/proto_palette.cpp index faa0bb5ca..be845bd01 100644 --- a/src/gfx/proto_palette.cpp +++ b/src/gfx/proto_palette.cpp @@ -6,7 +6,7 @@ #include "helpers.hpp" -bool ProtoPalette::add(uint16_t color) { +void ProtoPalette::add(uint16_t color) { size_t i = 0; // Seek the first slot greater than the new color @@ -16,12 +16,12 @@ bool ProtoPalette::add(uint16_t color) { ++i; if (i == _colorIndices.size()) { // We reached the end of the array without finding the color, so it's a new one. - return true; + return; } } // If we found it, great! Nothing else to do. if (_colorIndices[i] == color) { - return false; + return; } // Swap entries until the end @@ -30,12 +30,11 @@ bool ProtoPalette::add(uint16_t color) { ++i; if (i == _colorIndices.size()) { // The set is full, but doesn't include the new color. - return true; + return; } } // Write that last one into the new slot _colorIndices[i] = color; - return true; } ProtoPalette::ComparisonResult ProtoPalette::compare(ProtoPalette const &other) const {