]> git.draconx.ca Git - liblbx.git/blobdiff - src/lbximg.c
lbximg: Add support for Netpbm output.
[liblbx.git] / src / lbximg.c
index 6c54b0f3b659bbb79371d63efe88252f8053858b..ada16929a32cf400797b089e849c4bdb371eabf0 100644 (file)
@@ -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 <config.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <limits.h>
 #include <assert.h>
@@ -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;
        }