fixed tilemap output and added -o option
[img2tiles] / src / main.c
index a2845ac..d4698cc 100644 (file)
@@ -1,14 +1,22 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
+#include <errno.h>
 #include "image.h"
 #include "dynarr.h"
 
 void print_usage(const char *argv0);
 int proc_image(const char *fname);
+void wrtiles_carr(FILE *fp, const char *name, struct image *timg, int ntiles);
+void wrtilemap_carr(FILE *fp, const char *name, int *tmap, int xtiles, int ytiles);
+void wrpalette_carr(FILE *fp, const char *name, struct cmapent *cmap, int ncol);
 
 enum { OUT_IMG, OUT_C, OUT_ASM } outmode;
+static const char *otype_suffix[] = {".png", ".c", ".s"};
+
 int tile_xsz = 8, tile_ysz = 8;
+const char *output_filename;
 
 int main(int argc, char **argv)
 {
@@ -18,6 +26,10 @@ int main(int argc, char **argv)
                if(argv[i][0] == '-') {
                        if(argv[i][2] == 0) {
                                switch(argv[i][1]) {
+                               case 'o':
+                                       output_filename = argv[++i];
+                                       break;
+
                                case 't':
                                        if(sscanf(argv[++i], "%dx%d", &tile_xsz, &tile_ysz) != 2) {
                                                fprintf(stderr, "-t must be followed by the tile size (WxH)\n");
@@ -62,6 +74,7 @@ void print_usage(const char *argv0)
 {
        printf("Usage: %s [options] <img1> [<img2> ... <imgN>]\n", argv0);
        printf("Options:\n");
+       printf(" -o <file>: output file\n");
        printf(" -t WxH: tile size (default 8x8)\n");
        printf(" -c: output C array\n");
        printf(" -s: output GNU assembler data\n");
@@ -83,16 +96,26 @@ int find_tile(struct image *tile, struct image *tiles)
 int proc_image(const char *fname)
 {
        int i, j, k, idx, xtiles, ytiles, ntiles, result = -1;
+       FILE *fp;
        struct image img, tile;
        struct image *tiles = 0;
        unsigned char *tiles_pixels, *tptr;
        unsigned char *sptr;
        int *tilemap = 0, *mapptr;
+       char *basename, *suffix, *outfile;
 
        if(load_image(&img, fname) == -1) {
                fprintf(stderr, "failed to load image: %s\n", fname);
                return -1;
        }
+       basename = alloca(strlen(fname) + 1);
+       strcpy(basename, fname);
+       if((suffix = strrchr(basename, '/'))) {
+               basename = suffix + 1;
+       }
+       if((suffix = strchr(basename, '.'))) {
+               *suffix = 0;
+       }
 
        xtiles = img.width / tile_xsz;
        ytiles = img.height / tile_ysz;
@@ -161,29 +184,54 @@ int proc_image(const char *fname)
                        }
 
                        *mapptr++ = idx;
+                       if(i < 2) {
+                               printf("%2dx%-2d: %d\n", j, i, idx);
+                       }
 
                        sptr += tile.scansz;
                }
-               sptr += (tile_ysz - 1) * tile.scansz;
+               sptr += (tile_ysz - 1) * tile.pitch;
        }
 
        ntiles = dynarr_size(tiles);
        fprintf(stderr, "%s (%dx%d) -> %d tiles, %d unique\n", fname, img.width, img.height,
                        xtiles * ytiles, ntiles);
 
+       assert(ntiles > 0);
+
+       /* make a big image out of the tiles and write it out */
+       tile = tiles[0];
+       tile.height = ntiles * tile_ysz;
 
-       if(ntiles > 0) {
-               FILE *fp;
+       if(output_filename) {
+               outfile = (char*)output_filename;
+       } else {
+               outfile = alloca(strlen(basename) + 5);
+               sprintf(outfile, "%s%s", basename, otype_suffix[outmode]);
+       }
 
-               /* make a big image out of the tiles and write it out */
-               tile = tiles[0];
-               tile.height = ntiles * tile_ysz;
-               if(save_image(&tile, "test.png") == -1) {
+       switch(outmode) {
+       case OUT_IMG:
+               if(save_image(&tile, outfile) == -1) {
                        fprintf(stderr, "failed to write output image\n");
                        goto err;
                }
+               break;
+
+       case OUT_C:
+               if(!(fp = fopen(outfile, "w"))) {
+                       fprintf(stderr, "failed to open output file: %s: %s\n", outfile, strerror(errno));
+                       goto err;
+               }
+               wrtiles_carr(fp, basename, &tile, ntiles);
+               wrtilemap_carr(fp, basename, tilemap, xtiles, ytiles);
+               wrpalette_carr(fp, basename, tile.cmap, tile.cmap_ncolors);
+               break;
+
+       case OUT_ASM:
+               /* TODO */
+               break;
        }
-       /* TODO cont. */
 
        result = 0;
 
@@ -194,3 +242,73 @@ err:
        free(img.pixels);
        return result;
 }
+
+void wrtiles_carr(FILE *fp, const char *name, struct image *timg, int ntiles)
+{
+       int i, j, curx = 0;
+       unsigned char *ptr = timg->pixels;
+
+       fprintf(fp, "\nint %s_num_tiles = %d;\n", name, ntiles);
+       fprintf(fp, "int %s_tiles_width = %d;\n", name, timg->width);
+       fprintf(fp, "int %s_tiles_height = %d;\n", name, timg->height);
+       fprintf(fp, "int %s_tiles_bpp = %d;\n", name, timg->bpp);
+       fprintf(fp, "unsigned char %s_tiles[] = {\n", name);
+
+       for(i=0; i<timg->height; i++) {
+               for(j=0; j<timg->scansz; j++) {
+                       if(curx == 0) {
+                               curx = 3 + fprintf(fp, "\t%u", (unsigned int)*ptr++);
+                       } else {
+                               curx += fprintf(fp, ", %u", (unsigned int)*ptr++);
+                       }
+                       if(curx >= 80) {
+                               fprintf(fp, ",\n");
+                               curx = 0;
+                       }
+               }
+               ptr += timg->pitch - timg->scansz;
+       }
+
+       fprintf(fp, "\n};\n\n");
+}
+
+void wrtilemap_carr(FILE *fp, const char *name, int *tmap, int xtiles, int ytiles)
+{
+       int i, sz, curx = 0;
+
+       fprintf(fp, "\nint %s_tilemap_cols = %d;\n", name, xtiles);
+       fprintf(fp, "int %s_tilemap_rows = %d;\n", name, ytiles);
+       fprintf(fp, "unsigned int %s_tilemap[] = {\n", name);
+
+       sz = xtiles * ytiles;
+       for(i=0; i<sz; i++) {
+               if(curx == 0) {
+                       curx = 3 + fprintf(fp, "\t%u", (unsigned int)tmap[i]);
+               } else {
+                       curx += fprintf(fp, ", %u", (unsigned int)tmap[i]);
+               }
+               if(curx >= 80) {
+                       fprintf(fp, ",\n");
+                       curx = 0;
+               }
+       }
+
+       fprintf(fp, "\n};\n\n");
+}
+
+void wrpalette_carr(FILE *fp, const char *name, struct cmapent *cmap, int ncol)
+{
+       int i;
+
+       fprintf(fp, "\nint %s_cmap_colors = %d;\n", name, ncol);
+       fprintf(fp, "unsigned char %s_cmap[][3] = {\n", name);
+       for(i=0; i<ncol; i++) {
+               fprintf(fp, "\t{%u, %u, %u}", cmap[i].r, cmap[i].g, cmap[i].b);
+               if(i < ncol - 1) {
+                       fputs(",\n", fp);
+               } else {
+                       fputc('\n', fp);
+               }
+       }
+       fprintf(fp, "};\n\n");
+}