2palpic: whitespace cleanup
[rofl0r-openDOW.git] / utils / 2palpic.c
blob5b360087e01b4a155c992c3e1da57ce0e944c411
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include "../palpic.h"
6 #include <leptonica/allheaders.h>
7 #define assert(x) if(!(x)) __asm__("int3");
9 #pragma RcB2 LINK "-llept"
10 /* leptonica:
11 enum {
12 COLOR_RED = 0,
13 COLOR_GREEN = 1,
14 COLOR_BLUE = 2,
15 L_ALPHA_CHANNEL = 3
18 static const l_int32 L_RED_SHIFT =
19 8 * (sizeof(l_uint32) - 1 - COLOR_RED); //24
20 static const l_int32 L_GREEN_SHIFT =
21 8 * (sizeof(l_uint32) - 1 - COLOR_GREEN); //16
22 static const l_int32 L_BLUE_SHIFT =
23 8 * (sizeof(l_uint32) - 1 - COLOR_BLUE); //8
24 static const l_int32 L_ALPHA_SHIFT =
25 8 * (sizeof(l_uint32) - 1 - L_ALPHA_CHANNEL); //0
27 composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
29 *ppixel = (rval << L_RED_SHIFT) | (gval << L_GREEN_SHIFT) | (bval << L_BLUE_SHIFT);
30 return 0;
31 } */
33 static unsigned get_sprite_start(unsigned sprite_nr, unsigned row_nr, unsigned sprite_w, unsigned sprite_h, unsigned sprites_per_row) {
34 unsigned sprite_row = sprite_nr / sprites_per_row;
35 unsigned row_off = (row_nr * sprite_w * sprites_per_row);
36 unsigned res = (sprite_row * sprite_w * sprite_h * sprites_per_row) + row_off + ((sprite_nr % sprites_per_row) * sprite_w);
37 //printf("sprite %.2u, row %.2u : %u\n", sprite_nr, row_nr, res);
38 return res;
41 #define STRSZ(lit) lit, sizeof(lit) - 1
42 #define LIT_SIZE(lit) ( sizeof(lit) - 1)
43 int main(int argc, char** argv) {
44 int w, h;
45 struct palpic pp = palpic_empty;
46 prgb pal[256];
48 struct Pix* infile;
49 struct Pix* pix32;
51 unsigned startarg = 1;
52 for(; startarg < (unsigned) argc; startarg++)
53 if(!memcmp(argv[startarg], STRSZ("-sprite="))) break;
54 if(startarg == argc) {
55 printf("syntax: %s [-t] -sprite=WxH infile outfile\n"
56 "where WxH denotes the dimensions of a single picture in the spritesheet\n"
57 "-t, if given, means the first color in the bitmap is the transparent color\n", argv[0]);
58 return 1;
60 if(startarg == 2 && argv[1][0] == '-' && argv[1][1] == 't' && argv[1][2] == 0)
61 pp.flags |= PPF_TRANSPARENT;
63 startarg++;
65 char *in_filename = argv[startarg];
66 if(access(in_filename, R_OK) == -1) {
67 perror(in_filename);
68 return 1;
70 char *out_filename = argv[startarg + 1];
71 char* cp;
72 unsigned sprite_w, sprite_h;
73 unsigned sprite_count;
74 int to_c = (cp = strrchr(out_filename, '.')) && cp == out_filename + strlen(out_filename) - 2 && cp[1] == 'c';
75 char struct_name[256];
76 if(to_c) {
77 char *st_start = strrchr(out_filename, '/');
78 if(st_start) st_start++;
79 else st_start = out_filename;
80 size_t l = snprintf(struct_name, sizeof struct_name, "%s", st_start);
81 struct_name[l-2] = 0;
85 infile = pixRead(in_filename);
87 pixGetDimensions(infile, &w, &h, NULL);
89 if(startarg > 1) {
90 char* str_w = argv[startarg -1] + LIT_SIZE("-sprite=");
91 char* str_h = strchr(str_w, 'x');
92 *(str_h++) = 0;
93 sprite_w = atoi(str_w);
94 sprite_h = atoi(str_h);
95 sprite_count = (h * w) / (sprite_h * sprite_w);
96 unsigned rest = (h * w) % (sprite_h * sprite_w);
97 if(rest) {
98 printf("error: the picture dimensions are no multiple of the sprite dimensions!\n");
99 return 1;
101 if(w % sprite_w) {
102 printf("error: the picture width is no multiple of the sprite width!\n");
103 return 1;
105 } else {
106 // no sprite support
107 sprite_w = w;
108 sprite_h = h;
109 sprite_count = 1;
112 unsigned sprites_per_row = w / sprite_w;
114 /* we always align sprites vertically */
115 pp.height = sprite_h * sprite_count;
116 pp.width = sprite_w;
118 pix32 = pixConvertTo32(infile);
119 prgb* bufptr = (prgb*) pix32->data;
121 unsigned x, y = 0, p;
122 for(y = 0; y < (unsigned) h; y++) {
123 for(x = 0; x < (unsigned) w; x++) {
124 for(p = 0; p < pp.palcount; p++)
125 if(pal[p].val == bufptr->val)
126 goto next_x;
127 pal[pp.palcount++] = *bufptr;
128 next_x:
129 bufptr++;
133 FILE* outfile = fopen(out_filename, "w");
136 unsigned sprite;
137 if(!to_c) {
138 palpic_fileformat(&pp);
139 fwrite(&pp, sizeof(pp), 1, outfile);
140 fwrite(pal, sizeof(prgb) * pp.palcount, 1, outfile);
142 for(sprite = 0; sprite < sprite_count; sprite++) {
143 for(y = 0; y < sprite_h; y++) {
144 unsigned sprite_start_y = get_sprite_start(sprite, y, sprite_w, sprite_h, sprites_per_row);
145 bufptr = &((prgb*) pix32->data)[sprite_start_y];
147 for(x = 0; x < sprite_w; x++) {
148 for(p = 0; p < pp.palcount; p++)
149 if(pal[p].val == bufptr->val) {
150 uint8_t val = p;
151 fwrite(&val, sizeof(val), 1, outfile);
152 goto success;
154 fprintf(stderr, "bug: could not find color in palette\n");
155 return 1;
156 success:
157 bufptr++;
161 } else {
162 char buf[1024];
163 snprintf(buf, sizeof(buf),
164 "#include \"palpic.h\"\n"
165 "#define PAL_COUNT %d\n"
166 "#define SPRITE_COUNT %d\n"
167 "#define WIDTH %d\n"
168 "#define HEIGHT %d\n"
169 "#define o 0\n"
171 "#define STRUCT_NAME %s\n\n"
172 "static const struct {\n"
173 "\tstruct palpic header;\n"
174 "\tprgb palette[PAL_COUNT];\n"
175 "\tuint8_t data[WIDTH * HEIGHT];\n"
176 "} STRUCT_NAME = { \n"
177 "\t{ {'p', 'P', 'i', 'C', }, 1, PAL_COUNT, SPRITE_COUNT, WIDTH, HEIGHT, %s, 0 },\n"
178 "\t{\n\t\t",
179 (int) pp.palcount,
180 (int) sprite_count,
181 (int) pp.width,
182 (int) pp.height,
183 struct_name,
184 (pp.flags & PPF_TRANSPARENT ? "PPF_TRANSPARENT" : "0")
186 fwrite(buf, strlen(buf), 1, outfile);
188 for(p = 0; p < pp.palcount; p++) {
189 if(p == 0 && pp.flags & PPF_TRANSPARENT)
190 snprintf(buf, sizeof(buf), "PRGB(%3u, %3u, %3u), ", (unsigned) 0,(unsigned) 0, (unsigned) 0);
191 else
192 snprintf(buf, sizeof(buf), "PRGB(%3u, %3u, %3u), ", (unsigned) pal[p].colors.r,(unsigned) pal[p].colors.g, (unsigned) pal[p].colors.b);
193 fwrite(buf, strlen(buf), 1, outfile);
194 //if(p % 8 == 7)
195 fwrite(STRSZ("\n\t\t"), 1, outfile);
198 snprintf(buf, sizeof(buf), "\n\t},\n\t{\n\t\t");
199 fwrite(buf, strlen(buf), 1, outfile);
200 unsigned counter = 0;
201 unsigned values_per_line = sprite_w;
202 const char *value_format = pp.palcount > 99 ? "%3u," : "%2u,";
203 const char *o_format = pp.palcount > 99 ? " o," : " o,";
204 for(sprite = 0; sprite < sprite_count; sprite++) {
205 fprintf(outfile, "/* sprite #%.3u */\n\t\t", sprite);
206 for(y = 0; y < sprite_h; y++) {
207 unsigned sprite_start_y = get_sprite_start(sprite, y, sprite_w, sprite_h, sprites_per_row);
208 assert(sprite_start_y + sprite_w <= h * w);
209 bufptr = &((prgb*) pix32->data)[sprite_start_y];
211 for(x = 0; x < sprite_w; x++) {
212 for(p = 0; p < pp.palcount; p++) {
213 if(pal[p].val == bufptr->val) {
214 if(p == 0)
215 snprintf(buf, sizeof(buf), o_format);
216 else
217 snprintf(buf, sizeof(buf), value_format, (unsigned) p);
218 fwrite(buf, strlen(buf), 1, outfile);
219 if(counter % values_per_line == values_per_line - 1)
220 fwrite(STRSZ("\n\t\t"), 1, outfile);
221 goto success2;
224 fprintf(stderr, "bug: could not find color in palette\n");
225 return 1;
226 success2:
227 bufptr++;
228 counter++;
233 fwrite(STRSZ("\n\t},\n"), 1, outfile);
235 snprintf(buf, sizeof(buf),
236 "};\n\n"
237 "#undef o\n"
238 "#undef PAL_COUNT\n"
239 "#undef SPRITE_COUNT\n"
240 "#undef WIDTH\n"
241 "#undef HEIGHT\n"
242 "#undef STRUCT_NAME\n\n");
243 fwrite(buf, strlen(buf), 1, outfile);
246 fclose(outfile);
247 pixDestroy(&pix32);
248 pixDestroy(&infile);
249 return 0;