Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix detection of tiles with too many colors #1546

Merged
merged 1 commit into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions include/gfx/proto_palette.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ class ProtoPalette {
std::array<uint16_t, capacity> _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,
Expand Down
46 changes: 23 additions & 23 deletions src/gfx/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,33 +1115,44 @@ void process() {
DefaultInitVec<AttrmapEntry> attrmap{};

for (auto tile : png.visitAsTiles()) {
ProtoPalette tileColors;
AttrmapEntry &attrs = attrmap.emplace_back();
uint8_t nbColorsInTile = 0;

// Count the unique non-transparent colors for packing
std::unordered_set<uint16_t> 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;
}
if (Rgba color = tile.pixel(x, y); !color.isTransparent()) {
tileColors.insert(color.cgbColor());
}
}
}

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 (tileColors.empty()) {
// "Empty" proto-palettes screw with the packing process, so discard those
attrs.protoPaletteID = AttrmapEntry::transparent;
continue;
}

ProtoPalette protoPalette;
for (uint16_t cgbColor : tileColors) {
protoPalette.add(cgbColor);
}

// Insert the proto-palette, making sure to avoid overlaps
Rangi42 marked this conversation as resolved.
Show resolved Hide resolved
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))
/*
Expand All @@ -1151,7 +1162,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);
* }
* }
Expand All @@ -1168,25 +1179,14 @@ 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(
"Reached %zu proto-palettes... sorry, this image is too much for me to handle :(",
AttrmapEntry::transparent
);
}
protoPalettes.push_back(tileColors);
protoPalettes.push_back(protoPalette);
continue_visiting_tiles:;
}

Expand Down
9 changes: 4 additions & 5 deletions src/gfx/proto_palette.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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 {
Expand Down