mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Allow mirroring only the X or Y axes (#1468)
This commit is contained in:
@@ -13,6 +13,8 @@ _rgbgfx_completions() {
|
||||
[O]="group-outputs:normal"
|
||||
[u]="unique-tiles:normal"
|
||||
[v]="verbose:normal"
|
||||
[X]="mirror-x:normal"
|
||||
[Y]="mirror-y:normal"
|
||||
[Z]="columns:normal"
|
||||
[a]="attr-map:glob-*.attrmap"
|
||||
[A]="auto-attr-map:normal"
|
||||
|
||||
@@ -22,6 +22,8 @@ local args=(
|
||||
'(-t --tilemap -T --auto-tilemap)'{-T,--auto-tilemap}'[Shortcut for -t <file>.tilemap]'
|
||||
'(-u --unique-tiles)'{-u,--unique-tiles}'[Eliminate redundant tiles]'
|
||||
{-v,--verbose}'[Enable verbose output]'
|
||||
'(-X --mirror-x)'{-X,--mirror-x}'[Eliminate horizontally mirrored tiles from output]'
|
||||
'(-Y --mirror-y)'{-Y,--mirror-y}'[Eliminate vertically mirrored tiles from output]'
|
||||
'(-Z --columns)'{-Z,--columns}'[Read the image in column-major order]'
|
||||
|
||||
'(-a --attr-map -A --auto-attr-map)'{-a,--attr-map}'+[Generate a map of tile attributes (mirroring)]:attrmap file:_files'
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
|
||||
struct Options {
|
||||
bool useColorCurve = false; // -C
|
||||
bool allowMirroring = false; // -m
|
||||
bool allowDedup = false; // -u
|
||||
bool columnMajor = false; // -Z, previously -h
|
||||
bool allowMirroringX = false; // -X, -m
|
||||
bool allowMirroringY = false; // -Y, -m
|
||||
bool columnMajor = false; // -Z
|
||||
uint8_t verbosity = 0; // -v
|
||||
|
||||
std::string attrmap{}; // -a, -A
|
||||
|
||||
@@ -144,14 +144,16 @@ static option const longopts[] = {
|
||||
{"unique-tiles", no_argument, nullptr, 'u'},
|
||||
{"version", no_argument, nullptr, 'V'},
|
||||
{"verbose", no_argument, nullptr, 'v'},
|
||||
{"mirror-x", no_argument, nullptr, 'X'},
|
||||
{"trim-end", required_argument, nullptr, 'x'},
|
||||
{"mirror-y", no_argument, nullptr, 'Y'},
|
||||
{"columns", no_argument, nullptr, 'Z'},
|
||||
{nullptr, no_argument, nullptr, 0 }
|
||||
};
|
||||
|
||||
static void printUsage() {
|
||||
fputs(
|
||||
"Usage: rgbgfx [-r stride] [-CmOuVZ] [-v [-v ...]] [-a <attr_map> | -A]\n"
|
||||
"Usage: rgbgfx [-r stride] [-CmOuVXYZ] [-v [-v ...]] [-a <attr_map> | -A]\n"
|
||||
" [-b <base_ids>] [-c <colors>] [-d <depth>] [-L <slice>] [-N <nb_tiles>]\n"
|
||||
" [-n <nb_pals>] [-o <out_file>] [-p <pal_file> | -P] [-q <pal_map> | -Q]\n"
|
||||
" [-s <nb_colors>] [-t <tile_map> | -T] [-x <nb_tiles>] <file>\n"
|
||||
@@ -466,7 +468,8 @@ static char *parseArgv(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
options.allowMirroring = true;
|
||||
options.allowMirroringX = true; // Imply `-X`
|
||||
options.allowMirroringY = true; // Imply `-Y`
|
||||
[[fallthrough]]; // Imply `-u`
|
||||
case 'u':
|
||||
options.allowDedup = true;
|
||||
@@ -582,6 +585,14 @@ static char *parseArgv(int argc, char *argv[]) {
|
||||
error("Tile trim (-x) argument must be a valid number, not \"%s\"", musl_optarg);
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
options.allowMirroringX = true;
|
||||
options.allowDedup = true; // Imply `-u`
|
||||
break;
|
||||
case 'Y':
|
||||
options.allowMirroringY = true;
|
||||
options.allowDedup = true; // Imply `-u`
|
||||
break;
|
||||
case 'Z':
|
||||
options.columnMajor = true;
|
||||
break;
|
||||
@@ -757,10 +768,12 @@ int main(int argc, char *argv[]) {
|
||||
fputs("Options:\n", stderr);
|
||||
if (options.columnMajor)
|
||||
fputs("\tVisit image in column-major order\n", stderr);
|
||||
if (options.allowMirroring)
|
||||
fputs("\tAllow mirroring tiles\n", stderr);
|
||||
if (options.allowDedup)
|
||||
fputs("\tAllow deduplicating tiles\n", stderr);
|
||||
if (options.allowMirroringX)
|
||||
fputs("\tAllow deduplicating horizontally mirrored tiles\n", stderr);
|
||||
if (options.allowMirroringY)
|
||||
fputs("\tAllow deduplicating vertically mirrored tiles\n", stderr);
|
||||
if (options.useColorCurve)
|
||||
fputs("\tUse color curve\n", stderr);
|
||||
fprintf(stderr, "\tBit depth: %" PRIu8 "bpp\n", options.bitDepth);
|
||||
|
||||
@@ -747,10 +747,10 @@ public:
|
||||
|
||||
// Update the hash
|
||||
_hash ^= bitplanes;
|
||||
if (options.allowMirroring) {
|
||||
// Count the line itself as mirrorred; vertical mirroring is
|
||||
// already taken care of because the symmetric line will be XOR'd
|
||||
// the same way. (...which is a problem, but probably benign.)
|
||||
if (options.allowMirroringX) {
|
||||
// Count the line itself as mirrorred horizontally; vertical mirroring is already
|
||||
// taken care of because the symmetric line will be XOR'd the same way.
|
||||
// (...this reduces the hash's efficiency, but seems benign with most real-world data.)
|
||||
_hash ^= flipTable[bitplanes >> 8] << 8 | flipTable[bitplanes & 0xFF];
|
||||
}
|
||||
}
|
||||
@@ -773,17 +773,19 @@ public:
|
||||
return MatchType::EXACT;
|
||||
}
|
||||
|
||||
if (!options.allowMirroring) {
|
||||
return MatchType::NOPE;
|
||||
}
|
||||
|
||||
// Check if we have horizontal mirroring, which scans the array forward again
|
||||
if (std::equal(RANGE(_data), other._data.begin(), [](uint8_t lhs, uint8_t rhs) {
|
||||
if (options.allowMirroringX
|
||||
&& std::equal(RANGE(_data), other._data.begin(), [](uint8_t lhs, uint8_t rhs) {
|
||||
return lhs == flipTable[rhs];
|
||||
})) {
|
||||
return MatchType::HFLIP;
|
||||
}
|
||||
|
||||
// The remaining possibilities for matching all require vertical mirroring
|
||||
if (!options.allowMirroringY) {
|
||||
return MatchType::NOPE;
|
||||
}
|
||||
|
||||
// Check if we have vertical or vertical+horizontal mirroring, for which we have to read
|
||||
// bitplane *pairs* backwards
|
||||
bool hasVFlip = true, hasVHFlip = true;
|
||||
@@ -803,8 +805,16 @@ public:
|
||||
}
|
||||
|
||||
// If we have both (i.e. we have symmetry), default to vflip only
|
||||
assume(hasVFlip || hasVHFlip);
|
||||
return hasVFlip ? MatchType::VFLIP : MatchType::VHFLIP;
|
||||
if (hasVFlip) {
|
||||
return MatchType::VFLIP;
|
||||
}
|
||||
|
||||
// If we allow both and have both, then use both
|
||||
if (options.allowMirroringX && hasVHFlip) {
|
||||
return MatchType::VHFLIP;
|
||||
}
|
||||
|
||||
return MatchType::NOPE;
|
||||
}
|
||||
friend bool operator==(TileData const &lhs, TileData const &rhs) {
|
||||
return lhs.tryMatching(rhs) != MatchType::NOPE;
|
||||
|
||||
Reference in New Issue
Block a user