mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Add rgbgfx -r 0 to infer a width (#1437)
This commit is contained in:
@@ -13,9 +13,6 @@
|
|||||||
#include "gfx/rgba.hpp"
|
#include "gfx/rgba.hpp"
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
uint16_t reversedWidth = 0; // -r, in tiles
|
|
||||||
bool reverse() const { return reversedWidth != 0; }
|
|
||||||
|
|
||||||
bool useColorCurve = false; // -C
|
bool useColorCurve = false; // -C
|
||||||
bool allowMirroring = false; // -m
|
bool allowMirroring = false; // -m
|
||||||
bool allowDedup = false; // -u
|
bool allowDedup = false; // -u
|
||||||
@@ -42,6 +39,7 @@ struct Options {
|
|||||||
std::string output{}; // -o
|
std::string output{}; // -o
|
||||||
std::string palettes{}; // -p, -P
|
std::string palettes{}; // -p, -P
|
||||||
std::string palmap{}; // -q, -Q
|
std::string palmap{}; // -q, -Q
|
||||||
|
uint16_t reversedWidth = 0; // -r, in tiles
|
||||||
uint8_t nbColorsPerPal = 0; // -s; 0 means "auto" = 1 << bitDepth;
|
uint8_t nbColorsPerPal = 0; // -s; 0 means "auto" = 1 << bitDepth;
|
||||||
std::string tilemap{}; // -t, -T
|
std::string tilemap{}; // -t, -T
|
||||||
uint64_t trim = 0; // -x
|
uint64_t trim = 0; // -x
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
.Op Fl o Ar out_file
|
.Op Fl o Ar out_file
|
||||||
.Op Fl p Ar pal_file | Fl P
|
.Op Fl p Ar pal_file | Fl P
|
||||||
.Op Fl q Ar pal_map | Fl Q
|
.Op Fl q Ar pal_map | Fl Q
|
||||||
.Op Fl r Ar stride
|
.Op Fl r Ar width
|
||||||
.Op Fl s Ar nb_colors
|
.Op Fl s Ar nb_colors
|
||||||
.Op Fl t Ar tilemap | Fl T
|
.Op Fl t Ar tilemap | Fl T
|
||||||
.Op Fl x Ar quantity
|
.Op Fl x Ar quantity
|
||||||
@@ -246,6 +246,9 @@ below for details.
|
|||||||
.Pp
|
.Pp
|
||||||
.Ar width
|
.Ar width
|
||||||
is the width of the image to generate, in tiles.
|
is the width of the image to generate, in tiles.
|
||||||
|
.Fl r 0
|
||||||
|
chooses a width to make the image as square as possible.
|
||||||
|
This is useful if you do not know the original width.
|
||||||
.It Fl s Ar nb_colors , Fl \-palette-size Ar nb_colors
|
.It Fl s Ar nb_colors , Fl \-palette-size Ar nb_colors
|
||||||
Specify how many colors each palette contains, including the transparent one if any.
|
Specify how many colors each palette contains, including the transparent one if any.
|
||||||
.Ar nb_colors
|
.Ar nb_colors
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ static struct LocalOptions {
|
|||||||
bool autoPalettes;
|
bool autoPalettes;
|
||||||
bool autoPalmap;
|
bool autoPalmap;
|
||||||
bool groupOutputs;
|
bool groupOutputs;
|
||||||
|
bool reverse;
|
||||||
} localOptions;
|
} localOptions;
|
||||||
|
|
||||||
static uintmax_t nbErrors;
|
static uintmax_t nbErrors;
|
||||||
@@ -535,13 +536,11 @@ static char *parseArgv(int argc, char *argv[]) {
|
|||||||
options.palmap = musl_optarg;
|
options.palmap = musl_optarg;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
localOptions.reverse = true;
|
||||||
options.reversedWidth = parseNumber(arg, "Reversed image stride");
|
options.reversedWidth = parseNumber(arg, "Reversed image stride");
|
||||||
if (*arg != '\0') {
|
if (*arg != '\0') {
|
||||||
error("Reversed image stride (-r) must be a valid number, not \"%s\"", musl_optarg);
|
error("Reversed image stride (-r) must be a valid number, not \"%s\"", musl_optarg);
|
||||||
}
|
}
|
||||||
if (options.reversedWidth == 0) {
|
|
||||||
error("Reversed image stride (-r) may not be 0!");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
options.nbColorsPerPal = parseNumber(arg, "Number of colors per palette", 4);
|
options.nbColorsPerPal = parseNumber(arg, "Number of colors per palette", 4);
|
||||||
@@ -830,13 +829,13 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!options.input.empty()) {
|
if (!options.input.empty()) {
|
||||||
if (options.reverse()) {
|
if (localOptions.reverse) {
|
||||||
reverse();
|
reverse();
|
||||||
} else {
|
} else {
|
||||||
process();
|
process();
|
||||||
}
|
}
|
||||||
} else if (!options.palettes.empty() && options.palSpecType == Options::EXPLICIT
|
} else if (!options.palettes.empty() && options.palSpecType == Options::EXPLICIT
|
||||||
&& !options.reverse()) {
|
&& !localOptions.reverse) {
|
||||||
processPalettes();
|
processPalettes();
|
||||||
} else {
|
} else {
|
||||||
fputs("FATAL: No input image specified\n", stderr);
|
fputs("FATAL: No input image specified\n", stderr);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <math.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -159,6 +160,17 @@ void reverse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t width = options.reversedWidth, height; // In tiles
|
size_t width = options.reversedWidth, height; // In tiles
|
||||||
|
if (width == 0) {
|
||||||
|
// Pick the smallest width that will result in a landscape-aspect rectangular image.
|
||||||
|
// Thus a prime number of tiles will result in a horizontal row.
|
||||||
|
// This avoids redundancy with `-r 1` which results in a vertical column.
|
||||||
|
width = (size_t)ceil(sqrt(nbTileInstances));
|
||||||
|
for (; width < nbTileInstances; ++width) {
|
||||||
|
if (nbTileInstances % width == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
options.verbosePrint(Options::VERB_INTERM, "Picked reversing width of %zu tiles\n", width);
|
||||||
|
}
|
||||||
if (nbTileInstances % width != 0) {
|
if (nbTileInstances % width != 0) {
|
||||||
fatal(
|
fatal(
|
||||||
"Total number of tiles read (%zu) cannot be divided by image width (%zu tiles)",
|
"Total number of tiles read (%zu) cannot be divided by image width (%zu tiles)",
|
||||||
@@ -219,11 +231,9 @@ void reverse() {
|
|||||||
|
|
||||||
if (options.palSpecType == Options::EXPLICIT && palettes != options.palSpec) {
|
if (options.palSpecType == Options::EXPLICIT && palettes != options.palSpec) {
|
||||||
warning("Colors in the palette file do not match those specified with `-c`!");
|
warning("Colors in the palette file do not match those specified with `-c`!");
|
||||||
// [#111111ff, #222222ff, #333333ff, #444444ff] [#111111ff, #222222ff, #333333ff, #444444ff]
|
// This spacing aligns "...versus with `-c`" above the column of `-c` palettes
|
||||||
fputs("Colors specified in the palette file: ...versus with `-c`:\n", stderr);
|
fputs("Colors specified in the palette file: ...versus with `-c`:\n", stderr);
|
||||||
for (size_t i = 0;
|
for (size_t i = 0; i < palettes.size() && i < options.palSpec.size(); ++i) {
|
||||||
i < palettes.size() && i < options.palSpec.size();
|
|
||||||
++i) {
|
|
||||||
if (i < palettes.size()) {
|
if (i < palettes.size()) {
|
||||||
printPalette(palettes[i]);
|
printPalette(palettes[i]);
|
||||||
} else {
|
} else {
|
||||||
@@ -336,7 +346,7 @@ void reverse() {
|
|||||||
png_set_IHDR(
|
png_set_IHDR(
|
||||||
png,
|
png,
|
||||||
pngInfo,
|
pngInfo,
|
||||||
options.reversedWidth * 8,
|
width * 8,
|
||||||
height * 8,
|
height * 8,
|
||||||
8,
|
8,
|
||||||
PNG_COLOR_TYPE_RGB_ALPHA,
|
PNG_COLOR_TYPE_RGB_ALPHA,
|
||||||
@@ -353,8 +363,8 @@ void reverse() {
|
|||||||
sbitChunk.alpha = 1;
|
sbitChunk.alpha = 1;
|
||||||
png_set_sBIT(png, pngInfo, &sbitChunk);
|
png_set_sBIT(png, pngInfo, &sbitChunk);
|
||||||
|
|
||||||
constexpr uint8_t SIZEOF_PIXEL = 4; // Each pixel is 4 bytes (RGBA @ 8 bits/component)
|
constexpr uint8_t SIZEOF_TILE = 4 * 8; // 4 bytes/pixel (RGBA @ 8 bits/channel) * 8 pixels/tile
|
||||||
size_t const SIZEOF_ROW = options.reversedWidth * 8 * SIZEOF_PIXEL;
|
size_t const SIZEOF_ROW = width * SIZEOF_TILE;
|
||||||
std::vector<uint8_t> tileRow(8 * SIZEOF_ROW, 0xFF); // Data for 8 rows of pixels
|
std::vector<uint8_t> tileRow(8 * SIZEOF_ROW, 0xFF); // Data for 8 rows of pixels
|
||||||
uint8_t * const rowPtrs[8] = {
|
uint8_t * const rowPtrs[8] = {
|
||||||
&tileRow.data()[0 * SIZEOF_ROW],
|
&tileRow.data()[0 * SIZEOF_ROW],
|
||||||
@@ -415,7 +425,7 @@ void reverse() {
|
|||||||
bitplane0 = flipTable[bitplane0];
|
bitplane0 = flipTable[bitplane0];
|
||||||
bitplane1 = flipTable[bitplane1];
|
bitplane1 = flipTable[bitplane1];
|
||||||
}
|
}
|
||||||
uint8_t *ptr = &rowPtrs[y][tx * 8 * SIZEOF_PIXEL];
|
uint8_t *ptr = &rowPtrs[y][tx * SIZEOF_TILE];
|
||||||
for (uint8_t x = 0; x < 8; ++x) {
|
for (uint8_t x = 0; x < 8; ++x) {
|
||||||
uint8_t bit0 = bitplane0 & 0x80, bit1 = bitplane1 & 0x80;
|
uint8_t bit0 = bitplane0 & 0x80, bit1 = bitplane1 & 0x80;
|
||||||
Rgba const &pixel = *palette[bit0 >> 7 | bit1 >> 6];
|
Rgba const &pixel = *palette[bit0 >> 7 | bit1 >> 6];
|
||||||
|
|||||||
Reference in New Issue
Block a user