mirror of
https://github.com/gbdev/rgbds.git
synced 2026-10-05 19:56:18 +00:00
Implement -c embedded:multiple (#2194)
This commit is contained in:
1 parent
c592d665a8
commit
ffa32a94e8
12 files changed
+66
-3
No files matched your search
@@ -28,6 +28,7 @@ struct Options {
|
|||||||
INLINE,
|
INLINE,
|
||||||
EXTERNAL,
|
EXTERNAL,
|
||||||
EMBEDDED,
|
EMBEDDED,
|
||||||
|
EMBEDDED_MULTIPLE,
|
||||||
DMG,
|
DMG,
|
||||||
} palSpecType = NO_SPEC; // -c
|
} palSpecType = NO_SPEC; // -c
|
||||||
std::vector<std::array<std::optional<Rgba>, 4>> palSpec{};
|
std::vector<std::array<std::optional<Rgba>, 4>> palSpec{};
|
||||||
@@ -61,6 +62,9 @@ struct Options {
|
|||||||
uint16_t maxNbColors() const { return nbColorsPerPal * nbPalettes; }
|
uint16_t maxNbColors() const { return nbColorsPerPal * nbPalettes; }
|
||||||
|
|
||||||
bool hasExplicitPalSpec() const { return palSpecType == INLINE || palSpecType == EXTERNAL; }
|
bool hasExplicitPalSpec() const { return palSpecType == INLINE || palSpecType == EXTERNAL; }
|
||||||
|
bool hasEmbeddedPalSpec() const {
|
||||||
|
return palSpecType == EMBEDDED || palSpecType == EMBEDDED_MULTIPLE;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t dmgColors[4] = {};
|
uint8_t dmgColors[4] = {};
|
||||||
uint8_t dmgValue(uint8_t i) const {
|
uint8_t dmgValue(uint8_t i) const {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
void parseInlinePalSpec(char const * const rawArg);
|
void parseInlinePalSpec(char const * const rawArg);
|
||||||
void parseEmbeddedPalSpec(Png const &png);
|
void parseEmbeddedPalSpec(Png const &png);
|
||||||
|
void parseEmbeddedMultiplePalSpec(Png const &png);
|
||||||
void parseExternalPalSpec(char const *arg);
|
void parseExternalPalSpec(char const *arg);
|
||||||
void parseDmgPalSpec(char const * const rawArg);
|
void parseDmgPalSpec(char const * const rawArg);
|
||||||
void parseBackgroundPalSpec(char const *arg);
|
void parseBackgroundPalSpec(char const *arg);
|
||||||
|
|||||||
@@ -189,6 +189,11 @@ is the case-insensitive word
|
|||||||
then the first four colors of the input PNG's embedded palette are used.
|
then the first four colors of the input PNG's embedded palette are used.
|
||||||
It is an error if the PNG is not indexed, or if colors other than these 4 are used.
|
It is an error if the PNG is not indexed, or if colors other than these 4 are used.
|
||||||
.Pq This is different from the default behavior of indexed PNGs, as then unused entries in the embedded palette are ignored, whereas they are not with Fl c Cm embedded .
|
.Pq This is different from the default behavior of indexed PNGs, as then unused entries in the embedded palette are ignored, whereas they are not with Fl c Cm embedded .
|
||||||
|
If
|
||||||
|
.Ar pal_spec
|
||||||
|
is case-insensitive
|
||||||
|
.Cm embedded:multiple ,
|
||||||
|
then every four colors of the input PNG's embedded palette are used for multiple palettes.
|
||||||
.It Sy DMG palette spec
|
.It Sy DMG palette spec
|
||||||
If
|
If
|
||||||
.Ar pal_spec
|
.Ar pal_spec
|
||||||
|
|||||||
@@ -200,6 +200,9 @@ static void parseArg(int ch, char *arg) {
|
|||||||
} else if (strcasecmp(arg, "embedded") == 0) {
|
} else if (strcasecmp(arg, "embedded") == 0) {
|
||||||
// Use PLTE, error out if missing
|
// Use PLTE, error out if missing
|
||||||
options.palSpecType = Options::EMBEDDED;
|
options.palSpecType = Options::EMBEDDED;
|
||||||
|
} else if (strcasecmp(arg, "embedded:multiple") == 0) {
|
||||||
|
// Use PLTE, error out if missing
|
||||||
|
options.palSpecType = Options::EMBEDDED_MULTIPLE;
|
||||||
} else if (strcasecmp(arg, "auto") == 0) {
|
} else if (strcasecmp(arg, "auto") == 0) {
|
||||||
options.palSpecType = Options::NO_SPEC;
|
options.palSpecType = Options::NO_SPEC;
|
||||||
} else if (strcasecmp(arg, "dmg") == 0) {
|
} else if (strcasecmp(arg, "dmg") == 0) {
|
||||||
@@ -526,7 +529,10 @@ static void verboseOutputConfig() {
|
|||||||
case Options::INLINE:
|
case Options::INLINE:
|
||||||
case Options::EXTERNAL:
|
case Options::EXTERNAL:
|
||||||
case Options::EMBEDDED:
|
case Options::EMBEDDED:
|
||||||
|
case Options::EMBEDDED_MULTIPLE:
|
||||||
if (options.palSpecType == Options::EMBEDDED) {
|
if (options.palSpecType == Options::EMBEDDED) {
|
||||||
|
fputs("\tEmbedded single palette spec from PNG indexed PLTE chunk\n", stderr);
|
||||||
|
} else if (options.palSpecType == Options::EMBEDDED_MULTIPLE) {
|
||||||
fputs("\tEmbedded palette spec from PNG indexed PLTE chunk\n", stderr);
|
fputs("\tEmbedded palette spec from PNG indexed PLTE chunk\n", stderr);
|
||||||
} else {
|
} else {
|
||||||
fputs("\tExplicit palette spec\n", stderr);
|
fputs("\tExplicit palette spec\n", stderr);
|
||||||
@@ -695,6 +701,12 @@ int main(int argc, char *argv[]) {
|
|||||||
parseEmbeddedPalSpec(png);
|
parseEmbeddedPalSpec(png);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Options::EMBEDDED_MULTIPLE:
|
||||||
|
assume(!localOptions.palSpec);
|
||||||
|
if (useInputImage) {
|
||||||
|
parseEmbeddedMultiplePalSpec(png);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Options::INLINE:
|
case Options::INLINE:
|
||||||
assume(localOptions.palSpec);
|
assume(localOptions.palSpec);
|
||||||
parseInlinePalSpec(localOptions.palSpec->c_str());
|
parseInlinePalSpec(localOptions.palSpec->c_str());
|
||||||
|
|||||||
+42
-2
@@ -185,8 +185,8 @@ void parseEmbeddedPalSpec(Png const &png) {
|
|||||||
|
|
||||||
// Ignore extraneous colors if they are unused
|
// Ignore extraneous colors if they are unused
|
||||||
size_t nbColors = png.palette.size();
|
size_t nbColors = png.palette.size();
|
||||||
if (nbColors > options.maxOpaqueColors()) {
|
if (nbColors > options.nbColorsPerPal) {
|
||||||
nbColors = options.maxOpaqueColors();
|
nbColors = options.nbColorsPerPal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in the palette spec
|
// Fill in the palette spec
|
||||||
@@ -198,6 +198,46 @@ void parseEmbeddedPalSpec(Png const &png) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parseEmbeddedMultiplePalSpec(Png const &png) {
|
||||||
|
// Generate a palette spec from N palettes' length of colors in the embedded palette
|
||||||
|
if (png.palette.empty()) {
|
||||||
|
error("\"-c embedded:multiple\" was given, but the PNG does not have an embedded palette");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use enough embedded colors to evenly divide into N palettes
|
||||||
|
size_t nbColors = png.palette.size();
|
||||||
|
size_t nbPalettes = nbColors / options.nbColorsPerPal;
|
||||||
|
if (uint16_t maxNbColors = options.maxNbColors(); nbColors > maxNbColors) {
|
||||||
|
warnx(
|
||||||
|
"PNG embedded palette contains %zu colors, but there can only be %" PRIu16
|
||||||
|
"; ignoring extra",
|
||||||
|
nbColors,
|
||||||
|
maxNbColors
|
||||||
|
);
|
||||||
|
nbColors = maxNbColors;
|
||||||
|
nbPalettes = options.nbPalettes;
|
||||||
|
}
|
||||||
|
if (size_t nbUsedColors = options.nbColorsPerPal * nbPalettes; nbColors > nbUsedColors) {
|
||||||
|
warnx(
|
||||||
|
"PNG embedded palette contains %zu colors, but only %zu can be used for %zu palettes; "
|
||||||
|
"ignoring extra",
|
||||||
|
nbColors,
|
||||||
|
nbUsedColors,
|
||||||
|
nbPalettes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in the palette spec
|
||||||
|
options.palSpec.clear();
|
||||||
|
for (size_t i = 0; i < nbPalettes; ++i) {
|
||||||
|
auto &palette = options.palSpec.emplace_back();
|
||||||
|
for (size_t j = 0; j < options.nbColorsPerPal; ++j) {
|
||||||
|
palette[j] = png.palette[i * options.nbColorsPerPal + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Appends the first line read from `file` to the end of the provided `buffer`.
|
// Appends the first line read from `file` to the end of the provided `buffer`.
|
||||||
// Returns true if a line was read.
|
// Returns true if a line was read.
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
|
|||||||
+1
-1
@@ -282,7 +282,7 @@ void reverse() {
|
|||||||
palettes[0][i] = grayColors[options.dmgValue(i)];
|
palettes[0][i] = grayColors[options.dmgValue(i)];
|
||||||
}
|
}
|
||||||
grayscale = true;
|
grayscale = true;
|
||||||
} else if (options.palSpecType == Options::EMBEDDED) {
|
} else if (options.hasEmbeddedPalSpec()) {
|
||||||
warnx("An embedded palette was requested, but no palette file was specified; ignoring "
|
warnx("An embedded palette was requested, but no palette file was specified; ignoring "
|
||||||
"request");
|
"request");
|
||||||
grayscale = true;
|
grayscale = true;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
-c embedded:multiple
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 209 B |
Reference in new issue
Block a user