Parse HEX palettes (#1081)

Addresses one item of #1065
This commit is contained in:
Rangi
2022-10-01 12:45:00 -04:00
committed by GitHub
parent c10345f26d
commit 969412af24
2 changed files with 47 additions and 2 deletions

View File

@@ -384,6 +384,10 @@ A GBC palette memory dump, as emitted by
Useful to force several images to share the same palette.
.It Cm gpl
.Lk https://docs.gimp.org/2.10/en/gimp-concepts-palettes.html GIMP palette .
.It Cm hex
Plaintext lines of hexadecimal colors in
.Ql rrggbb
format.
.It Cm psp
.Lk https://www.selapa.net/swatches/colors/fileformats.php#psp_pal Paint Shop Pro palette .
.El

View File

@@ -55,7 +55,7 @@ constexpr uint8_t singleToHex(char c) {
template<typename Str> // Should be std::string or std::string_view
static void skipWhitespace(Str const &str, typename Str::size_type &pos) {
pos = std::min(str.find_first_not_of(" \t", pos), str.length());
pos = std::min(str.find_first_not_of(" \t"sv, pos), str.length());
}
void parseInlinePalSpec(char const * const rawArg) {
@@ -233,7 +233,8 @@ static std::optional<U> parseDec(std::string const &str, std::string::size_type
std::string::size_type start = n;
uintmax_t value = 0; // Use a larger type to handle overflow more easily
for (auto end = std::min(str.length(), str.find_first_not_of("0123456789", n)); n < end; ++n) {
for (auto end = std::min(str.length(), str.find_first_not_of("0123456789"sv, n)); n < end;
++n) {
value = std::min(value * 10 + (str[n] - '0'), (uintmax_t)std::numeric_limits<U>::max);
}
@@ -382,6 +383,45 @@ static void parseGPLFile(std::filebuf &file) {
}
}
static void parseHEXFile(std::filebuf &file) {
// https://lospec.com/palette-list/tag/gbc
uint16_t nbColors = 0;
uint16_t maxNbColors = options.nbColorsPerPal * options.nbPalettes;
for (;;) {
std::string line;
readLine(file, line);
if (!line.length()) {
break;
}
if (line.length() != 6
|| line.find_first_not_of("0123456789ABCDEFabcdef"sv) != std::string::npos) {
error("Failed to parse color #%" PRIu16 " (\"%s\"): invalid \"rrggbb\" line",
nbColors + 1, line.c_str());
return;
}
Rgba color =
Rgba(toHex(line[0], line[1]), toHex(line[2], line[3]), toHex(line[4], line[5]), 0xFF);
++nbColors;
if (nbColors < maxNbColors) {
if (nbColors % options.nbColorsPerPal == 1) {
options.palSpec.emplace_back();
}
options.palSpec.back()[nbColors % options.nbColorsPerPal] = color;
}
}
if (nbColors > maxNbColors) {
warning("HEX file contains %" PRIu16 " colors, but there can only be %" PRIu16
"; ignoring extra",
nbColors, maxNbColors);
}
}
static void parseACTFile(std::filebuf &file) {
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1070626
@@ -536,6 +576,7 @@ void parseExternalPalSpec(char const *arg) {
static std::array parsers{
std::tuple{"PSP", &parsePSPFile, std::ios::in },
std::tuple{"GPL", &parseGPLFile, std::ios::in },
std::tuple{"HEX", &parseHEXFile, std::ios::in },
std::tuple{"ACT", &parseACTFile, std::ios::binary},
std::tuple{"ACO", &parseACOFile, std::ios::binary},
std::tuple{"GBC", &parseGBCFile, std::ios::binary},