7 void print_usage(const char *argv0);
8 int proc_image(const char *fname);
10 enum { OUT_IMG, OUT_C, OUT_ASM } outmode;
11 int tile_xsz = 8, tile_ysz = 8;
13 int main(int argc, char **argv)
17 for(i=1; i<argc; i++) {
18 if(argv[i][0] == '-') {
22 if(sscanf(argv[++i], "%dx%d", &tile_xsz, &tile_ysz) != 2) {
23 fprintf(stderr, "-t must be followed by the tile size (WxH)\n");
41 fprintf(stderr, "invalid option: %s\n", argv[i]);
46 fprintf(stderr, "invalid option: %s\n", argv[i]);
52 if(proc_image(argv[i]) == -1) {
61 void print_usage(const char *argv0)
63 printf("Usage: %s [options] <img1> [<img2> ... <imgN>]\n", argv0);
65 printf(" -t WxH: tile size (default 8x8)\n");
66 printf(" -c: output C array\n");
67 printf(" -s: output GNU assembler data\n");
68 printf(" -h: print usage and exit\n\n");
71 int find_tile(struct image *tile, struct image *tiles)
74 count = dynarr_size(tiles);
75 for(i=0; i<count; i++) {
76 if(cmp_image(tile, tiles + i) == 0) {
83 int proc_image(const char *fname)
85 int i, j, k, idx, xtiles, ytiles, ntiles, result = -1;
86 struct image img, tile;
87 struct image *tiles = 0;
88 unsigned char *tiles_pixels, *tptr;
90 int *tilemap = 0, *mapptr;
92 if(load_image(&img, fname) == -1) {
93 fprintf(stderr, "failed to load image: %s\n", fname);
97 xtiles = img.width / tile_xsz;
98 ytiles = img.height / tile_ysz;
99 if(img.width % tile_xsz != 0 || img.height % tile_ysz != 0) {
100 fprintf(stderr, "image size (%dx%d) not evenly divisible into %dx%d tiles\n",
101 img.width, img.height, tile_xsz, tile_ysz);
105 if(!(tilemap = malloc(xtiles * ytiles * sizeof *tilemap))) {
106 fprintf(stderr, "failed to allocate %dx%d tilemap\n", xtiles, ytiles);
111 if(!(tiles = dynarr_alloc(0, sizeof *tiles))) {
112 fprintf(stderr, "failed to allocate tile array\n");
115 /* alloc a contiguous buffer for the full tileset pixels, to make it easier to write it
116 * out as a single image in the end
118 if(!(tiles_pixels = dynarr_alloc(0, tile_xsz * tile_ysz * img.bpp / 8))) {
119 fprintf(stderr, "failed to allocate tile pixel buffer\n");
124 tile.width = tile_xsz;
125 tile.height = tile_ysz;
126 tile.scansz = tile_xsz * tile.bpp / 8;
129 for(i=0; i<ytiles; i++) {
130 for(j=0; j<xtiles; j++) {
133 if((idx = find_tile(&tile, tiles)) == -1) {
134 /* we don't have a duplicate of this tile */
135 idx = dynarr_size(tiles);
137 if(!(tiles = dynarr_push(tiles, 0))) {
140 if(!(tptr = dynarr_push(tiles_pixels, 0))) {
145 tiles[idx].scansz = tiles[idx].pitch = tile.scansz;
147 /* did the array get relocated? */
148 if(tptr != tiles_pixels) {
150 /* make each tile's pixels pointer point to the right place in the large pixelbuffer */
151 for(k=0; k<idx+1; k++) {
152 tiles[k].pixels = tptr;
153 tptr += tile_ysz * tiles[idx].pitch;
156 /* otherwise just set the new one */
157 tiles[idx].pixels = tiles_pixels + idx * tile_ysz * tiles[idx].pitch;
160 blit(&tile, 0, 0, tile_xsz, tile_ysz, tiles + idx, 0, 0);
167 sptr += (tile_ysz - 1) * tile.scansz;
170 ntiles = dynarr_size(tiles);
171 fprintf(stderr, "%s (%dx%d) -> %d tiles, %d unique\n", fname, img.width, img.height,
172 xtiles * ytiles, ntiles);
178 /* make a big image out of the tiles and write it out */
180 tile.height = ntiles * tile_ysz;
181 if(save_image(&tile, "test.png") == -1) {
182 fprintf(stderr, "failed to write output image\n");
191 dynarr_free(tiles_pixels);