tools: bmp2tiles with cmd line args
[swan-dev] / tools / bmp2tiles / bmp2tiles.c
1 /**
2  * File              : bmp2tiles.c
3  * Author            : Robin Krens <robin@robinkrens.nl>
4  * Date              : 04.06.2022
5  * Last Modified Date: 12.06.2022
6  * Last Modified By  : Robin Krens <robin@robinkrens.nl>
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <stdbool.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <getopt.h>
16 #include <SDL2/SDL_image.h>
17
18 #define TILE_SZ         32
19 #define FOURBBP_ROW     8
20 #define FOURBPP_COL     8
21
22 typedef struct {
23         unsigned width;
24         unsigned height;
25         unsigned bpp;
26 } swan_gfx_t;
27
28 void set_info(swan_gfx_t * gfx, SDL_Surface * img)
29 {
30         gfx->width = img->w;
31         gfx->height = img->h;
32         gfx->bpp = img->format->BitsPerPixel;
33         
34         /* set userdata to iterate */
35         SDL_LockSurface(img);
36         img->userdata = img->pixels;
37         SDL_UnlockSurface(img);
38 }
39
40 void generate_4bpp_tile(unsigned char *buf, void * userdata, 
41                 bool packed)
42 {
43         unsigned char * ptr = (unsigned char *) userdata;
44         for (int i = 0; i < TILE_SZ; i+=4) {
45                 for (int j = 0; j < 4; ++j) {
46                         if (packed) { /* packed format */
47                                 buf[i+j] = ptr[0] << 4;
48                                 buf[i+j] |= ptr[1];
49                                 ptr += 2;
50                         } else { /* planar format */
51                                 for (int x = 0; x < 8; ++x) {
52                                         buf[i + j] = ptr[x] << j; 
53                                 }
54                         }
55                 }
56                 if (!packed)
57                         ptr += 8;
58         }
59 }
60
61 int main(int argc, char *argv[])
62 {
63         SDL_Surface * rawbmp;
64         FILE * ostream;
65         int opt;
66         char * infile;
67         char outfile[256];
68         bool bout = false;
69
70         while ((opt = getopt(argc, argv, "po:sv:")) != -1) {
71                 switch (opt) {
72                         case 'p':
73                                 printf("include palette");
74                                 break;
75                         case 'o':
76                                 printf("output file %s\n", optarg);
77                                 strcpy(outfile, optarg);
78                                 bout = true;
79                                 break;
80                         case 's':
81                                 printf("generate gfx per 16x16 tile \n");
82                                 break;
83                         case 'v':
84                                 break;
85                         default: /* '?' */
86                                 fprintf(stderr, "Usage: %s [-s] [-o output] file \n", argv[0]);
87                                 exit(EXIT_FAILURE);
88                }
89         }
90
91         if (optind >= argc) {
92                 fprintf(stderr, "Expected infile\n");
93                 fprintf(stderr, "Usage: %s [-s] [-o output] [file]\n", argv[0]);
94                 exit(EXIT_FAILURE);
95         }
96
97         infile = argv[optind];
98
99         rawbmp = SDL_LoadBMP(infile);
100         if (!rawbmp) {
101                 fprintf(stderr, "can not load %s file\n", infile);
102                 exit(EXIT_FAILURE);
103         }
104
105         swan_gfx_t * gfx = malloc(sizeof(swan_gfx_t));
106         set_info(gfx, rawbmp);
107
108         unsigned char *tile_buf = malloc(sizeof(unsigned char) * TILE_SZ);
109         
110         if (gfx->bpp != 8) {
111                 fprintf(stderr, "warning: %d bpp format detected\n", rawbmp->format->BitsPerPixel);
112                 fprintf(stderr, "use --force in command to run\n");
113                 exit(EXIT_FAILURE);
114         }
115
116         if (!bout) 
117                 ostream = fopen("out.gfx", "w");
118         else { 
119                 printf("opening %s\n", outfile);
120                 ostream = fopen(outfile, "w");
121         }
122         
123         if (!ostream) {
124                 fprintf(stderr, "can not open file for writing!\n");
125                 exit(EXIT_FAILURE);
126         }
127
128         unsigned nr_tiles = 1;
129
130         for (int i = 0; i < nr_tiles; ++i) {
131                 generate_4bpp_tile(tile_buf, rawbmp->userdata, true);
132                 int ret = fwrite(tile_buf, sizeof(unsigned char), TILE_SZ, ostream);
133                 if (ret != TILE_SZ) {
134                         fprintf(stderr, "failed to convert, only write %d instead of %d\n", ret, TILE_SZ);
135                         goto cleanup;
136                 }
137         }
138
139 cleanup:
140         free(gfx);
141         SDL_FreeSurface(rawbmp);
142         fclose(ostream);
143 }