10 #define MAGIC "RLESPRIT"
14 uint16_t width, height, bpp;
16 } __attribute__((packed));
28 unsigned char padding;
30 } __attribute__((packed));
37 int rlesprite(struct image *img, int x, int y, int xsz, int ysz);
38 int proc_sheet(const char *fname);
39 void print_usage(const char *argv0);
41 int tile_xsz, tile_ysz;
49 int main(int argc, char **argv)
55 for(i=1; i<argc; i++) {
56 if(argv[i][0] == '-') {
57 if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-size") == 0) {
58 if(sscanf(argv[++i], "%dx%d", &tile_xsz, &tile_ysz) != 2 ||
59 tile_xsz <= 0 || tile_ysz <= 0) {
60 fprintf(stderr, "%s must be followed by WIDTHxHEIGHT\n", argv[i - 1]);
64 } else if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "-rect") == 0) {
66 if(sscanf(argv[++i], "%dx%d+%d+%d", &rect.w, &rect.h, &rect.x, &rect.y) < 2 || rect.w <= 0 || rect.h <= 0) {
67 fprintf(stderr, "%s must be followed by WIDTHxHEIGHT+X+Y\n", argv[i - 1]);
71 } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-pad") == 0) {
72 padding = strtol(argv[++i], &endp, 10);
73 if(endp == argv[i] || padding < 0) {
74 fprintf(stderr, "%s must be followed by a positive number\n", argv[i - 1]);
78 } else if(strcmp(argv[i], "-coffset") == 0) {
79 cmap_offs = strtol(argv[++i], &endp, 10);
80 if(endp == argv[i] || cmap_offs < 0 || cmap_offs >= 256) {
81 fprintf(stderr, "-coffset must be followed by a valid colormap offset\n");
85 } else if(strcmp(argv[i], "-o") == 0) {
87 fprintf(stderr, "%s must be followed by an output filename\n", argv[i - 1]);
90 if(name && strcmp(name, argv[i]) != 0) {
98 } else if(strcmp(argv[i], "-k") == 0 || strcmp(argv[i], "-key") == 0) {
99 ckey = strtol(argv[++i], &endp, 10);
100 if(endp == argv[i] || ckey < 0) {
101 fprintf(stderr, "%s must be followed by a valid color key\n", argv[i - 1]);
105 } else if(strcmp(argv[i], "-conv565") == 0) {
108 } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
109 print_usage(argv[0]);
113 fprintf(stderr, "invalid option: %s\n", argv[i]);
114 print_usage(argv[0]);
121 if(!(outfp = fopen(name, "wb"))) {
122 fprintf(stderr, "failed to open output file: %s: %s\n", name, strerror(errno));
130 if(proc_sheet(argv[i]) == -1) {
139 int proc_sheet(const char *fname)
141 int i, j, x, y, num_xtiles, num_ytiles, xsz, ysz;
143 struct file_header hdr;
145 if(load_image(&img, fname) == -1) {
146 fprintf(stderr, "failed to load image: %s\n", fname);
151 if(conv_image_rgb565(&tmp, &img) == -1) {
152 fprintf(stderr, "failed to convert image to 16bpp 565: %s\n", fname);
166 num_xtiles = num_ytiles = 1;
167 xsz = rect.w - padding;
168 ysz = rect.h - padding;
171 num_xtiles = num_ytiles = 0;
175 i += tile_xsz + padding;
180 i += tile_ysz + padding;
183 num_xtiles = rect.w / tile_xsz;
184 num_ytiles = rect.h / tile_ysz;
190 memcpy(hdr.magic, MAGIC, sizeof hdr.magic);
194 hdr.count = num_xtiles * num_ytiles;
195 fwrite(&hdr, sizeof hdr, 1, outfp);
198 for(i=0; i<num_ytiles; i++) {
200 for(j=0; j<num_xtiles; j++) {
201 rlesprite(&img, x, y, xsz, ysz);
211 int rlesprite(struct image *img, int x, int y, int xsz, int ysz)
213 int i, j, numops, mode, new_mode, start, skip_acc, pixsz = img->bpp / 8;
214 unsigned char *scanptr, *pptr;
215 struct csop *ops, *optr, endop = {0};
217 pptr = img->pixels + y * img->scansz + x * pixsz;
219 ops = optr = alloca((xsz + 1) * ysz * sizeof *ops);
221 for(i=0; i<ysz; i++) {
226 optr++->op = CSOP_ENDL;
229 for(j=0; j<xsz; j++) {
230 if(memcmp(pptr, &ckey, pixsz) == 0) {
231 new_mode = CSOP_SKIP;
233 new_mode = CSOP_COPY;
236 if(new_mode != mode) {
240 optr->len = j - start;
248 pptr += img->scansz - xsz * pixsz;
253 optr->len = xsz - start;
259 scanptr = pptr = img->pixels + y * img->scansz + x * img->bpp / 8;
263 for(i=0; i<numops; i++) {
266 skip_acc += optr->len;
267 pptr += optr->len * pixsz;
271 /* maybe at some point combine multiple endl into yskips? meh */
272 fwrite(optr, sizeof *optr, 1, outfp);
274 scanptr += img->scansz;
280 struct csop skip = {0};
283 fwrite(&skip, sizeof skip, 1, outfp);
287 fwrite(optr, sizeof *optr, 1, outfp);
288 fwrite(pptr, pixsz, optr->len, outfp);
290 pptr += optr->len * pixsz;
294 fprintf(stderr, "invalid op\n");
300 fwrite(&endop, sizeof endop, 1, outfp);
304 void print_usage(const char *argv0)
306 printf("Usage: %s [options] <spritesheet>\n", argv0);
307 printf("Options:\n");
308 printf(" -o <filename>: output filename (default: stdout)\n");
309 printf(" -s,-size <WxH>: tile size (default: whole image)\n");
310 printf(" -r,-rect <WxH+X+Y>: use rectangle of the input image (default: whole image)\n");
311 printf(" -p,-pad <N>: how many pixels to skip between tiles in source image (default: 0)\n");
312 printf(" -coffset <offs>: colormap offset [0, 255] (default: 0)\n");
313 printf(" -k,-key <color>: color-key for transparency (default: 0)\n");
314 printf(" -conv565: convert image to 16bpp 565 before processing\n");
315 printf(" -h: print usage and exit\n");