Add compatibility hack for unused colors in indexed PNGs

This commit is contained in:
ISSOtm
2022-03-09 00:00:07 +01:00
committed by Eldred Habert
parent b95c26c886
commit 20442c8a43
5 changed files with 43 additions and 25 deletions

View File

@@ -10,27 +10,56 @@
#include "gfx/convert.hpp"
#include "gfx/main.hpp"
using std::swap;
namespace sorting {
void indexed(std::vector<Palette> &palettes, int palSize, png_color const *palRGB,
png_byte *palAlpha) {
options.verbosePrint("Sorting palettes using embedded palette...\n");
auto pngToRgb = [&palRGB, &palAlpha](int index) {
auto const &c = palRGB[index];
return Rgba(c.red, c.green, c.blue, palAlpha ? palAlpha[index] : 0xFF);
};
// HACK: for compatibility with old versions, add unused colors if:
// - there is only one palette, and
// - only some of the first N colors are being used
if (palettes.size() == 1) {
Palette &palette = palettes[0];
// Build our candidate array of colors
decltype(palette.colors) colors{UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX};
for (int i = 0; i < options.maxPalSize(); ++i) {
colors[i] = pngToRgb(i).cgbColor();
}
// Check that the palette only uses those colors
if (std::all_of(palette.begin(), palette.end(), [&colors](uint16_t color) {
return std::find(colors.begin(), colors.end(), color) != colors.end();
})) {
if (palette.size() != options.maxPalSize()) {
warning("Unused color in PNG embedded palette was re-added; please use `-c embedded` to get this in future versions");
}
// Overwrite the palette, and return with that (it's already sorted)
palette.colors = colors;
return;
}
}
for (Palette &pal : palettes) {
std::sort(pal.begin(), pal.end(), [&](uint16_t lhs, uint16_t rhs) {
// Iterate through the PNG's palette, looking for either of the two
for (int i = 0; i < palSize; ++i) {
auto const &c = palRGB[i];
Rgba color(c.red, c.green, c.blue, palAlpha ? palAlpha[i] : 0xFF);
uint16_t cgbColor = color.cgbColor();
if (cgbColor == Rgba::transparent) {
uint16_t color = pngToRgb(i).cgbColor();
if (color == Rgba::transparent) {
continue;
}
// Return whether lhs < rhs
if (cgbColor == rhs) {
if (color == rhs) {
return false;
}
if (cgbColor == lhs) {
if (color == lhs) {
return true;
}
}