X-Git-Url: http://git.draconx.ca/gitweb/liblbx.git/blobdiff_plain/4e74df93acc6594cd8a212c30dc2b429520caef2..af13a143c8bfcd713216b1382448174e21b9f278:/src/lbximg.c diff --git a/src/lbximg.c b/src/lbximg.c index 6c54b0f..ada1692 100644 --- a/src/lbximg.c +++ b/src/lbximg.c @@ -1,6 +1,6 @@ /* * 2ooM: The Master of Orion II Reverse Engineering Project - * Simple command-line tool to convert an LBX image to a set of PNGs. + * Simple command-line tool to convert an LBX image to other formats. * Copyright © 2006-2011, 2013 Nick Bowler * * This program is free software: you can redistribute it and/or modify @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ static void printusage(void) { puts("usage: lbximg [-i|-d] [-v] [-p palette_file] [-O override_file]" " [-f path]"); - puts(" [frameno ...]"); + puts(" [-F format] [frameno ...]"); } static void printhelp(void) @@ -56,6 +57,52 @@ enum { MODE_IDENT, }; +static const struct img_format { + img_output_func *output; + char name[4]; + bool enabled; +} formats[] = { + { img_output_png, "png", 1 }, + { img_output_pam, "pam", 1 }, + { img_output_ppm, "ppm", 1 }, + { img_output_pbm, "pbm", 1 }, +}; + +static int lookup_format(const char *fmt) +{ + for (size_t i = 0; i < sizeof formats / sizeof formats[0]; i++) { + assert(!formats[i].name[sizeof formats[i].name - 1]); + + if (!fmt && formats[i].enabled) + return i; + + if (strcmp(formats[i].name, fmt)) + continue; + + if (!formats[i].enabled) { + tool_err(-1, "%s support disabled at build time", fmt); + return -1; + } + + return i; + } + + tool_err(-1, "unknown format %s", fmt); + return -1; +} + +bool img_is_masked(unsigned char **mask, unsigned width, unsigned height) +{ + unsigned x, y; + + for (x = y = 0; y < height; ++x < width || (x = 0, y++)) { + if (mask[y][x] == 0) + return true; + } + + return false; +} + int parserange(unsigned frames, char *str, unsigned char *bits) { unsigned long start, end; @@ -104,7 +151,7 @@ int parserange(unsigned frames, char *str, unsigned char *bits) return 0; } -int outpng(unsigned int frameno, +int output(unsigned int frameno, const struct img_format *fmt, unsigned char **framedata, unsigned char **mask, unsigned int width, unsigned int height, struct lbx_colour palette[static 256]) @@ -113,8 +160,9 @@ int outpng(unsigned int frameno, FILE *of; int rc; + assert(fmt->output != NULL); assert(frameno < 65536); - snprintf(name, sizeof name, "%s.%03d.png", outname, frameno); + snprintf(name, sizeof name, "%s.%03d.%s", outname, frameno, fmt->name); of = fopen(name, "wb"); if (!of) { @@ -122,7 +170,7 @@ int outpng(unsigned int frameno, return -1; } - rc = img_output_png(of, name, width, height, framedata, mask, palette); + rc = fmt->output(of, name, width, height, framedata, mask, palette); if (rc < 0) { fclose(of); return -1; @@ -203,7 +251,8 @@ static int loadpalette(struct lbx_image *img, struct lbx_imginfo *info, return 0; } -int decode(struct lbx_image *img, FILE *palf, FILE *override, char **argv) +static int +decode(struct lbx_image *img, FILE *palf, FILE *override, int fmt, char **argv) { unsigned char *framebits; struct lbx_colour palette[256]; @@ -211,6 +260,8 @@ int decode(struct lbx_image *img, FILE *palf, FILE *override, char **argv) int extracted = 0; unsigned int i; + assert(fmt >= 0 && fmt < sizeof formats / sizeof formats[0]); + lbx_img_getinfo(img, &info); framebits = calloc(1, img->frames / CHAR_BIT + 1); @@ -250,7 +301,8 @@ int decode(struct lbx_image *img, FILE *palf, FILE *override, char **argv) mask = lbx_img_getmask(img); - if (!outpng(i, data, mask, img->width, img->height, + if (!output(i, &formats[fmt], data, mask, + img->width, img->height, usepalette ? palette : NULL)) { extracted = 1; } @@ -270,18 +322,19 @@ err: int main(int argc, char **argv) { - int mode = MODE_NONE, opt, rc = EXIT_FAILURE; + int mode = MODE_NONE, fmt, opt, rc = EXIT_FAILURE; struct lbx_pipe_state stdin_handle = { .f = stdin }; + const char *file = NULL, *fmtstring = NULL; FILE *palf = NULL, *overf = NULL; - const char *file = NULL; struct lbx_image *img; - static const char *sopts = "idnvf:p:O:V"; + static const char sopts[] = "idnvF:f:p:O:VH"; static const struct option lopts[] = { { "ident", 0, NULL, 'i' }, { "decode", 0, NULL, 'd' }, { "verbose", 0, NULL, 'v' }, { "file", 1, NULL, 'f' }, + { "format", 1, NULL, 'F' }, { "palette", 1, NULL, 'p' }, { "override", 1, NULL, 'p' }, @@ -306,6 +359,9 @@ int main(int argc, char **argv) case 'v': verbose = 1; break; + case 'F': + fmtstring = optarg; + break; case 'f': file = optarg; break; @@ -336,8 +392,7 @@ int main(int argc, char **argv) case 'H': printhelp(); return EXIT_SUCCESS; - case '?': - case ':': + default: return EXIT_FAILURE; } } @@ -347,6 +402,10 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + fmt = lookup_format(fmtstring); + if (fmt < 0) + return EXIT_FAILURE; + if (file) img = lbx_img_fopen(file); else @@ -373,7 +432,7 @@ int main(int argc, char **argv) switch (mode) { case MODE_DECODE: - rc = decode(img, palf, overf, &argv[optind]); + rc = decode(img, palf, overf, fmt, &argv[optind]); break; }