92f404fe54dfebe4301006f2a099f06fe4ed830c
[mdlife] / tools / pngdump / tiles.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include "tiles.h"
6 #include "image.h"
7
8 static int matchtile(struct image *img, int toffs, int th);
9
10 int img2tiles(struct tilemap *tmap, struct image *img, int tw, int th, int dedup)
11 {
12         int i, j, x, y, tx, ty, tileoffs, xtiles, ytiles, ntiles, tileno, tid;
13         struct image orig;
14         unsigned int pix;
15
16         if(alloc_image(&orig, img->width, img->height, img->bpp) == -1) {
17                 fprintf(stderr, "img2tiles: failed to allocate temporary image\n");
18                 return -1;
19         }
20         memcpy(orig.pixels, img->pixels, img->scansz * img->height);
21
22         xtiles = (img->width + tw - 1) / tw;
23         ytiles = (img->height + th - 1) / th;
24         ntiles = xtiles * ytiles;
25
26         img->width = tw;
27         img->height = ntiles * th;
28         img->pitch = img->scansz = tw * img->bpp / 8;
29
30         if(tmap) {
31                 tmap->width = xtiles;
32                 tmap->height = ytiles;
33                 if(!(tmap->map = malloc(ntiles * sizeof *tmap->map))) {
34                         fprintf(stderr, "failed to allocate tilemap\n");
35                         free(orig.pixels);
36                         return -1;
37                 }
38         }
39
40         tileno = 0;
41         tileoffs = 0;
42         y = 0;
43         for(i=0; i<ytiles; i++) {
44                 x = 0;
45                 for(j=0; j<xtiles; j++) {
46                         for(ty=0; ty<th; ty++) {
47                                 for(tx=0; tx<tw; tx++) {
48                                         pix = get_pixel(&orig, x + tx, y + ty);
49                                         put_pixel(img, tx, ty + tileoffs, pix);
50                                 }
51                         }
52
53                         if(!dedup || (tid = matchtile(img, tileoffs, th)) == -1) {
54                                 tmap->map[tileno] = tileno;
55                                 tileoffs += th; /* destination Y offset, inc by th for every tile */
56                         } else {
57                                 tmap->map[tileno] = tid;
58                         }
59                         tileno++;
60                         x += tw;
61                 }
62                 y += th;
63         }
64
65         free(orig.pixels);
66         return 0;
67 }
68
69 static int matchtile(struct image *img, int toffs, int th)
70 {
71         int i, tilesz;
72         int ntiles = toffs / th;
73         unsigned char *pa, *pb;
74
75         tilesz = img->pitch * th;
76         pa = (unsigned char*)img->pixels;
77         pb = (unsigned char*)img->pixels + toffs * tilesz;
78
79         for(i=0; i<ntiles; i++) {
80                 if(memcmp(pa, pb, tilesz) == 0) {
81                         return i;
82                 }
83                 pa += tilesz;
84         }
85
86         return -1;
87 }
88
89 int dump_tilemap(struct tilemap *tmap, const char *fname)
90 {
91         FILE *fp;
92         int i, sz = tmap->width * tmap->height;
93         uint16_t id;
94
95         if(sz <= 0) return -1;
96
97         if(!(fp = fopen(fname, "wb"))) {
98                 fprintf(stderr, "dump_tilemap: failed to open %s for writing\n", fname);
99                 return -1;
100         }
101
102         for(i=0; i<sz; i++) {
103                 /* XXX dump in 16bit big endian for the megadrive */
104                 id = (tmap->map[i] << 8) | (tmap->map[i] >> 8);
105                 fwrite(&id, sizeof id, 1, fp);
106         }
107
108         fclose(fp);
109         return 0;
110 }