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"
|
[O]="group-outputs:normal"
|
||||||
[u]="unique-tiles:normal"
|
[u]="unique-tiles:normal"
|
||||||
[v]="verbose:normal"
|
[v]="verbose:normal"
|
||||||
|
[X]="mirror-x:normal"
|
||||||
|
[Y]="mirror-y:normal"
|
||||||
[Z]="columns:normal"
|
[Z]="columns:normal"
|
||||||
[a]="attr-map:glob-*.attrmap"
|
[a]="attr-map:glob-*.attrmap"
|
||||||
[A]="auto-attr-map:normal"
|
[A]="auto-attr-map:normal"
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ local args=(
|
|||||||
'(-t --tilemap -T --auto-tilemap)'{-T,--auto-tilemap}'[Shortcut for -t <file>.tilemap]'
|
'(-t --tilemap -T --auto-tilemap)'{-T,--auto-tilemap}'[Shortcut for -t <file>.tilemap]'
|
||||||
'(-u --unique-tiles)'{-u,--unique-tiles}'[Eliminate redundant tiles]'
|
'(-u --unique-tiles)'{-u,--unique-tiles}'[Eliminate redundant tiles]'
|
||||||
{-v,--verbose}'[Enable verbose output]'
|
{-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]'
|
'(-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'
|
'(-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 {
|
struct Options {
|
||||||
bool useColorCurve = false; // -C
|
bool useColorCurve = false; // -C
|
||||||
bool allowMirroring = false; // -m
|
|
||||||
bool allowDedup = false; // -u
|
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
|
uint8_t verbosity = 0; // -v
|
||||||
|
|
||||||
std::string attrmap{}; // -a, -A
|
std::string attrmap{}; // -a, -A
|
||||||
|
|||||||
@@ -144,14 +144,16 @@ static option const longopts[] = {
|
|||||||
{"unique-tiles", no_argument, nullptr, 'u'},
|
{"unique-tiles", no_argument, nullptr, 'u'},
|
||||||
{"version", no_argument, nullptr, 'V'},
|
{"version", no_argument, nullptr, 'V'},
|
||||||
{"verbose", no_argument, nullptr, 'v'},
|
{"verbose", no_argument, nullptr, 'v'},
|
||||||
|
{"mirror-x", no_argument, nullptr, 'X'},
|
||||||
{"trim-end", required_argument, nullptr, 'x'},
|
{"trim-end", required_argument, nullptr, 'x'},
|
||||||
|
{"mirror-y", no_argument, nullptr, 'Y'},
|
||||||
{"columns", no_argument, nullptr, 'Z'},
|
{"columns", no_argument, nullptr, 'Z'},
|
||||||
{nullptr, no_argument, nullptr, 0 }
|
{nullptr, no_argument, nullptr, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void printUsage() {
|
static void printUsage() {
|
||||||
fputs(
|
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"
|
" [-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"
|
" [-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"
|
" [-s <nb_colors>] [-t <tile_map> | -T] [-x <nb_tiles>] <file>\n"
|
||||||
@@ -466,7 +468,8 @@ static char *parseArgv(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
options.allowMirroring = true;
|
options.allowMirroringX = true; // Imply `-X`
|
||||||
|
options.allowMirroringY = true; // Imply `-Y`
|
||||||
[[fallthrough]]; // Imply `-u`
|
[[fallthrough]]; // Imply `-u`
|
||||||
case 'u':
|
case 'u':
|
||||||
options.allowDedup = true;
|
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);
|
error("Tile trim (-x) argument must be a valid number, not \"%s\"", musl_optarg);
|
||||||
}
|
}
|
||||||
break;
|
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':
|
case 'Z':
|
||||||
options.columnMajor = true;
|
options.columnMajor = true;
|
||||||
break;
|
break;
|
||||||
@@ -757,10 +768,12 @@ int main(int argc, char *argv[]) {
|
|||||||
fputs("Options:\n", stderr);
|
fputs("Options:\n", stderr);
|
||||||
if (options.columnMajor)
|
if (options.columnMajor)
|
||||||
fputs("\tVisit image in column-major order\n", stderr);
|
fputs("\tVisit image in column-major order\n", stderr);
|
||||||
if (options.allowMirroring)
|
|
||||||
fputs("\tAllow mirroring tiles\n", stderr);
|
|
||||||
if (options.allowDedup)
|
if (options.allowDedup)
|
||||||
fputs("\tAllow deduplicating tiles\n", stderr);
|
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)
|
if (options.useColorCurve)
|
||||||
fputs("\tUse color curve\n", stderr);
|
fputs("\tUse color curve\n", stderr);
|
||||||
fprintf(stderr, "\tBit depth: %" PRIu8 "bpp\n", options.bitDepth);
|
fprintf(stderr, "\tBit depth: %" PRIu8 "bpp\n", options.bitDepth);
|
||||||
|
|||||||
@@ -747,10 +747,10 @@ public:
|
|||||||
|
|
||||||
// Update the hash
|
// Update the hash
|
||||||
_hash ^= bitplanes;
|
_hash ^= bitplanes;
|
||||||
if (options.allowMirroring) {
|
if (options.allowMirroringX) {
|
||||||
// Count the line itself as mirrorred; vertical mirroring is
|
// Count the line itself as mirrorred horizontally; vertical mirroring is already
|
||||||
// already taken care of because the symmetric line will be XOR'd
|
// taken care of because the symmetric line will be XOR'd the same way.
|
||||||
// the same way. (...which is a problem, but probably benign.)
|
// (...this reduces the hash's efficiency, but seems benign with most real-world data.)
|
||||||
_hash ^= flipTable[bitplanes >> 8] << 8 | flipTable[bitplanes & 0xFF];
|
_hash ^= flipTable[bitplanes >> 8] << 8 | flipTable[bitplanes & 0xFF];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -773,17 +773,19 @@ public:
|
|||||||
return MatchType::EXACT;
|
return MatchType::EXACT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.allowMirroring) {
|
|
||||||
return MatchType::NOPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have horizontal mirroring, which scans the array forward again
|
// 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 lhs == flipTable[rhs];
|
||||||
})) {
|
})) {
|
||||||
return MatchType::HFLIP;
|
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
|
// Check if we have vertical or vertical+horizontal mirroring, for which we have to read
|
||||||
// bitplane *pairs* backwards
|
// bitplane *pairs* backwards
|
||||||
bool hasVFlip = true, hasVHFlip = true;
|
bool hasVFlip = true, hasVHFlip = true;
|
||||||
@@ -803,8 +805,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we have both (i.e. we have symmetry), default to vflip only
|
// If we have both (i.e. we have symmetry), default to vflip only
|
||||||
assume(hasVFlip || hasVHFlip);
|
if (hasVFlip) {
|
||||||
return hasVFlip ? MatchType::VFLIP : MatchType::VHFLIP;
|
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) {
|
friend bool operator==(TileData const &lhs, TileData const &rhs) {
|
||||||
return lhs.tryMatching(rhs) != MatchType::NOPE;
|
return lhs.tryMatching(rhs) != MatchType::NOPE;
|
||||||
|
|||||||
Reference in New Issue
Block a user