Skip to content

Commit

Permalink
pcx2clx: Add an option to crop sprite widths
Browse files Browse the repository at this point in the history
  • Loading branch information
glebm committed Jul 14, 2023
1 parent abe63ae commit 7ea2b69
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 11 deletions.
15 changes: 11 additions & 4 deletions src/internal/pcx2clx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace dvl_gfx {
std::optional<IoError> PcxToClx(const uint8_t *data, size_t size,
int numFramesOrFrameHeight,
std::optional<uint8_t> transparentColor,
const std::vector<uint16_t> &cropWidths,
std::vector<uint8_t> &clxData,
uint8_t *paletteData)
{
Expand Down Expand Up @@ -68,8 +69,12 @@ std::optional<IoError> PcxToClx(const uint8_t *data, size_t size,
clxData.resize(clxData.size() + FrameHeaderSize);

// Frame header:
const uint16_t frameWidth = cropWidths.empty()
? width
: cropWidths[std::min<size_t>(cropWidths.size(), frame) - 1];

WriteLE16(&clxData[frameHeaderPos], FrameHeaderSize);
WriteLE16(&clxData[frameHeaderPos + 2], static_cast<uint16_t>(width));
WriteLE16(&clxData[frameHeaderPos + 2], static_cast<uint16_t>(frameWidth));
WriteLE16(&clxData[frameHeaderPos + 4], static_cast<uint16_t>(frameHeight));
memset(&clxData[frameHeaderPos + 6], 0, 4);

Expand Down Expand Up @@ -99,7 +104,7 @@ std::optional<IoError> PcxToClx(const uint8_t *data, size_t size,
const uint8_t *src = &frameBuffer[(frameHeight - (line + 1)) * width];
if (transparentColor) {
unsigned solidRunWidth = 0;
for (const uint8_t *srcEnd = src + width; src != srcEnd; ++src) {
for (const uint8_t *srcEnd = src + frameWidth; src != srcEnd; ++src) {
if (*src == *transparentColor) {
if (solidRunWidth != 0) {
AppendClxPixelsOrFillRun(
Expand Down Expand Up @@ -145,6 +150,7 @@ std::optional<IoError> PcxToClx(const uint8_t *data, size_t size,
std::optional<IoError> PcxToClx(const char *inputPath, const char *outputPath,
int numFramesOrFrameHeight,
std::optional<uint8_t> transparentColor,
const std::vector<uint16_t> &cropWidths,
bool exportPalette,
uintmax_t *inputFileSize,
uintmax_t *outputFileSize)
Expand Down Expand Up @@ -173,8 +179,9 @@ std::optional<IoError> PcxToClx(const char *inputPath, const char *outputPath,

std::vector<uint8_t> clxData;
std::array<uint8_t, 256 * 3> paletteData;
if (const std::optional<IoError> error = PcxToClx(fileBuffer.get(), pixelDataSize, numFramesOrFrameHeight, transparentColor,
clxData, exportPalette ? paletteData.data() : nullptr);
if (const std::optional<IoError> error = PcxToClx(
fileBuffer.get(), pixelDataSize, numFramesOrFrameHeight, transparentColor,
cropWidths, clxData, exportPalette ? paletteData.data() : nullptr);
error.has_value()) {
return error;
}
Expand Down
21 changes: 14 additions & 7 deletions src/internal/pcx2clx_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,21 @@ constexpr char KHelp[] = R"(Usage: pcx2clx [options] files...
Converts PCX sprite(s) to a CLX file.
Options:
--output-dir <arg> Output directory. Default: input file directory.
--transparent-color <arg> Transparent color index. Default: none.
--num-sprites <arg> The number of vertically-stacked sprites. Default: 1.
--export-palette Export the palette as a .pal file.
--remove Remove the input files.
-q, --quiet Do not log anything.
--output-dir <arg> Output directory. Default: input file directory.
--transparent-color <arg> Transparent color index. Default: none.
--num-sprites <arg> The number of vertically-stacked sprites. Default: 1.
--crop-widths <arg>[,<arg>...] Crop sprites to the given width(s) by removing the right side of the sprite. Default: none.
--export-palette Export the palette as a .pal file.
--remove Remove the input files.
-q, --quiet Do not log anything.
)";

struct Options {
std::vector<const char *> inputPaths;
std::optional<std::string_view> outputDir;
uint16_t numSprites = 1;
std::optional<uint8_t> transparentColor;
std::vector<uint16_t> cropWidths;
bool exportPalette = false;
bool remove = false;
bool quiet = false;
Expand Down Expand Up @@ -72,6 +74,11 @@ tl::expected<Options, ArgumentError> ParseArguments(int argc, char *argv[])
if (!value.has_value())
return tl::unexpected { std::move(value).error() };
options.transparentColor = *value;
} else if (arg == "--crop-widths") {
tl::expected<std::vector<uint16_t>, ArgumentError> value = ParseIntListArgument<uint16_t>(state);
if (!value.has_value())
return tl::unexpected { std::move(value).error() };
options.cropWidths = *std::move(value);
} else if (arg == "--export-palette") {
options.exportPalette = true;
} else if (arg == "--remove") {
Expand Down Expand Up @@ -111,7 +118,7 @@ std::optional<IoError> Run(const Options &options)
uintmax_t inputFileSize;
uintmax_t outputFileSize;
if (std::optional<dvl_gfx::IoError> error = PcxToClx(inputPath, outputPath.string().c_str(), options.numSprites,
options.transparentColor, options.exportPalette, &inputFileSize, &outputFileSize);
options.transparentColor, options.cropWidths, options.exportPalette, &inputFileSize, &outputFileSize);
error.has_value()) {
error->message.append(": ").append(inputPath);
return error;
Expand Down
3 changes: 3 additions & 0 deletions src/public/include/pcx2clx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@ namespace dvl_gfx {
* @param size PCX buffer size.
* @param numFramesOrFrameHeight Number of vertically-stacked frames if positive, frame height if negative.
* @param transparentColor Palette index of the transparent color.
* @param cropWidths If non-empty, the sprites are cropped to the given width(s) by removing the right side of the sprite.
* @param paletteData If non-null, PCX palette data (256 * 3 bytes).
* @return std::optional<IoError>
*/
std::optional<IoError> PcxToClx(const uint8_t *data, size_t size,
int numFramesOrFrameHeight,
std::optional<uint8_t> transparentColor,
const std::vector<uint16_t> &cropWidths,
std::vector<uint8_t> &clxData,
uint8_t *paletteData = nullptr);

std::optional<IoError> PcxToClx(const char *inputPath, const char *outputPath,
int numFramesOrFrameHeight = 1,
std::optional<uint8_t> transparentColor = std::nullopt,
const std::vector<uint16_t> &cropWidths = {},
bool exportPalette = false,
uintmax_t *inputFileSize = nullptr,
uintmax_t *outputFileSize = nullptr);
Expand Down

0 comments on commit 7ea2b69

Please sign in to comment.