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. Useful to force several images to share the same palette.
.It Cm gpl .It Cm gpl
.Lk https://docs.gimp.org/2.10/en/gimp-concepts-palettes.html GIMP palette . .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 .It Cm psp
.Lk https://www.selapa.net/swatches/colors/fileformats.php#psp_pal Paint Shop Pro palette . .Lk https://www.selapa.net/swatches/colors/fileformats.php#psp_pal Paint Shop Pro palette .
.El .El

View File

@@ -55,7 +55,7 @@ constexpr uint8_t singleToHex(char c) {
template<typename Str> // Should be std::string or std::string_view template<typename Str> // Should be std::string or std::string_view
static void skipWhitespace(Str const &str, typename Str::size_type &pos) { 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) { 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; std::string::size_type start = n;
uintmax_t value = 0; // Use a larger type to handle overflow more easily 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); 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) { static void parseACTFile(std::filebuf &file) {
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1070626 // https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1070626
@@ -536,6 +576,7 @@ void parseExternalPalSpec(char const *arg) {
static std::array parsers{ static std::array parsers{
std::tuple{"PSP", &parsePSPFile, std::ios::in }, std::tuple{"PSP", &parsePSPFile, std::ios::in },
std::tuple{"GPL", &parseGPLFile, 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{"ACT", &parseACTFile, std::ios::binary},
std::tuple{"ACO", &parseACOFile, std::ios::binary}, std::tuple{"ACO", &parseACOFile, std::ios::binary},
std::tuple{"GBC", &parseGBCFile, std::ios::binary}, std::tuple{"GBC", &parseGBCFile, std::ios::binary},