]>
Commit | Line | Data |
---|---|---|
1 | #include <stdio.h> | |
2 | ||
3 | #define MAXCOLORS 256 | |
4 | #define COLS_PER_LINE 7 | |
5 | #define NUMS_PER_LINE 16 | |
6 | ||
7 | extern unsigned char *ReadGifBitmap(); | |
8 | ||
9 | struct ebmhdr { | |
10 | char magic[12]; | |
11 | unsigned int width, height; | |
12 | int num_colors; | |
13 | }; | |
14 | struct rgb_color { | |
15 | unsigned int red, green, blue; | |
16 | int pix_len; | |
17 | }; | |
18 | ||
19 | ||
20 | ||
21 | /* | |
22 | * dscan is a quick replacement for: | |
23 | * | |
24 | * fscanf (fp, "%d", &ip); | |
25 | */ | |
26 | dscan(fp, ip) | |
27 | FILE *fp; | |
28 | int *ip; | |
29 | { | |
30 | ||
31 | register int v = 0; | |
32 | register int n = 0; | |
33 | int done = 0; | |
34 | static int nerrors; | |
35 | ||
36 | while (!done) { | |
37 | register int i; | |
38 | i = getc(fp); | |
39 | if (i < 0) { | |
40 | *ip = v; | |
41 | fprintf(stderr, "dscanf: EOF"); | |
42 | if (nerrors++ > 2) | |
43 | return (-1); | |
44 | else if (nerrors++ > 4) | |
45 | exit(-1); | |
46 | return (n); | |
47 | } | |
48 | i &= 0xFF; | |
49 | switch (i) { | |
50 | case '0': | |
51 | case '1': | |
52 | case '2': | |
53 | case '3': | |
54 | case '4': | |
55 | case '5': | |
56 | case '6': | |
57 | case '7': | |
58 | case '8': | |
59 | case '9': | |
60 | v = i - '0' + (v * 10); | |
61 | n++; | |
62 | break; | |
63 | case '\n': | |
64 | case '\r': | |
65 | case ' ': | |
66 | case '\t': | |
67 | if (n) { | |
68 | *ip = v; | |
69 | done = 1; | |
70 | } | |
71 | break; | |
72 | default: | |
73 | fprintf(stderr, "dscanf: non numeric character (0x%x) '%c'\n", i, i); | |
74 | if (nerrors++ > 4) | |
75 | exit(-1); | |
76 | return (-1); | |
77 | ||
78 | } | |
79 | } | |
80 | return (n); | |
81 | } | |
82 | ||
83 | ||
84 | ||
85 | unsigned char * | |
86 | ReadEbmBitmap(fp, w, h, colrs) | |
87 | FILE *fp; | |
88 | int *w, *h; | |
89 | struct rgb_color *colrs; | |
90 | { | |
91 | int i, temp, scale; | |
92 | unsigned int bmap_size; | |
93 | int *ptr[3]; | |
94 | int red, green, blue; | |
95 | char line[1024]; | |
96 | unsigned char *bit_data; | |
97 | unsigned char *bitp; | |
98 | ||
99 | bit_data = NULL; | |
100 | *w = 0; | |
101 | *h = 0; | |
102 | ||
103 | if ((fscanf(fp, "%12s %d %d %d\n", line, w, h, &scale) == 4) && | |
104 | (strcmp(line, "xstitch_data") == 0)) { | |
105 | for (i = 0; i < 3; i++) { | |
106 | fscanf(fp, "%s", line); | |
107 | if (strcmp(line, "red") == 0) { | |
108 | ptr[i] = &red; | |
109 | } else if (strcmp(line, "green") == 0) { | |
110 | ptr[i] = &green; | |
111 | } else if (strcmp(line, "blue") == 0) { | |
112 | ptr[i] = &blue; | |
113 | } else { | |
114 | fprintf(stderr, "File has improper format\n"); | |
115 | return ((unsigned char *) NULL); | |
116 | } | |
117 | } | |
118 | fscanf(fp, "[^\n]\n"); | |
119 | for (i = 0; i < scale; i++) { | |
120 | line[0] = '\0'; | |
121 | if (fscanf(fp, "%d %d %d%[^\n]\n", ptr[0], ptr[1], ptr[2], line) < 3) { | |
122 | fprintf(stderr, "Bad color data #%d\n", i); | |
123 | } | |
124 | colrs[i].red = red; | |
125 | colrs[i].green = green; | |
126 | colrs[i].blue = blue; | |
127 | } | |
128 | ||
129 | bmap_size = (*w) * (*h); | |
130 | bit_data = (unsigned char *) malloc(bmap_size); | |
131 | if (bit_data == NULL) { | |
132 | fprintf(stderr, "Cannot allocate space for bitmap\n"); | |
133 | } | |
134 | bitp = bit_data; | |
135 | for (i = 0; i < bmap_size; i++) { | |
136 | if (dscan(fp, &temp) == -1) | |
137 | break; | |
138 | if (temp > (scale - 1)) | |
139 | temp = 0; | |
140 | *bitp = (unsigned char) temp; | |
141 | bitp++; | |
142 | } | |
143 | } else { | |
144 | return ((unsigned char *) NULL); | |
145 | } | |
146 | return (bit_data); | |
147 | } | |
148 | ||
149 | ||
150 | ||
151 | int | |
152 | swapint(in) | |
153 | int in; | |
154 | { | |
155 | int out; | |
156 | ||
157 | out = 0; | |
158 | out = out | ((in >> 24) & 0xff); | |
159 | out = out | ((in >> 8) & 0xff00); | |
160 | out = out | ((in << 8) & 0xff0000); | |
161 | out = out | ((in << 24) & 0xff000000); | |
162 | return (out); | |
163 | } | |
164 | ||
165 | ||
166 | ||
167 | unsigned char * | |
168 | ReadCompactEbmBitmap(fp, w, h, colrs) | |
169 | FILE *fp; | |
170 | int *w, *h; | |
171 | struct rgb_color *colrs; | |
172 | { | |
173 | int i, scale; | |
174 | unsigned int bmap_size; | |
175 | char pix_file[1024]; | |
176 | unsigned char *bit_data; | |
177 | unsigned char *bitp; | |
178 | struct ebmhdr Hdr; | |
179 | struct rgb_color color_data; | |
180 | int doswap; | |
181 | ||
182 | doswap = 0; | |
183 | bit_data = NULL; | |
184 | *w = 0; | |
185 | *h = 0; | |
186 | ||
187 | fread(&Hdr, sizeof(struct ebmhdr), 1, fp); | |
188 | if (strcmp(Hdr.magic, "xstitch") == 0) { | |
189 | /* | |
190 | * a horrible hack to deal with different byte ordering on | |
191 | * different machines. Is based on assumption of only 2 | |
192 | * possible byte orderings, and never more than 256 colors. | |
193 | */ | |
194 | if (Hdr.num_colors > 256) { | |
195 | doswap = 1; | |
196 | Hdr.width = swapint(Hdr.width); | |
197 | Hdr.height = swapint(Hdr.height); | |
198 | Hdr.num_colors = swapint(Hdr.num_colors); | |
199 | } | |
200 | *w = Hdr.width; | |
201 | *h = Hdr.height; | |
202 | scale = Hdr.num_colors; | |
203 | for (i = 0; i < Hdr.num_colors; i++) { | |
204 | fread(&colrs[i], sizeof(struct rgb_color), 1, fp); | |
205 | if (doswap) { | |
206 | colrs[i].red = swapint(colrs[i].red); | |
207 | colrs[i].green = swapint(colrs[i].green); | |
208 | colrs[i].blue = swapint(colrs[i].blue); | |
209 | colrs[i].pix_len = swapint(colrs[i].pix_len); | |
210 | } | |
211 | if (colrs[i].pix_len != 0) { | |
212 | if (colrs[i].pix_len > 1023) { | |
213 | fprintf(stderr, "bad pattern\n"); | |
214 | return ((unsigned char *) NULL); | |
215 | } | |
216 | fread(pix_file, sizeof(char), colrs[i].pix_len, fp); | |
217 | } | |
218 | } | |
219 | ||
220 | bmap_size = (*w) * (*h); | |
221 | bit_data = (unsigned char *) malloc(bmap_size); | |
222 | if (bit_data == NULL) { | |
223 | fprintf(stderr, "Cannot allocate space for bitmap\n"); | |
224 | } | |
225 | fread(bit_data, sizeof(unsigned char), ((*w) * (*h)), fp); | |
226 | ||
227 | bitp = bit_data; | |
228 | for (i = 0; i < bmap_size; i++) { | |
229 | if ((int) *bitp > (scale - 1)) | |
230 | *bitp = (unsigned char) 0; | |
231 | bitp++; | |
232 | } | |
233 | } else { | |
234 | return ((unsigned char *) NULL); | |
235 | } | |
236 | return (bit_data); | |
237 | } | |
238 | ||
239 | ||
240 | struct rgb_color | |
241 | * | |
242 | MapColors(data1, colrs1, data2, colrs2, width, height, Cnt) | |
243 | unsigned char *data1; | |
244 | struct rgb_color *colrs1; | |
245 | unsigned char *data2; | |
246 | struct rgb_color *colrs2; | |
247 | int width, height; | |
248 | int *Cnt; | |
249 | { | |
250 | int i, j; | |
251 | int fcnt, indx; | |
252 | int Mapping[MAXCOLORS]; | |
253 | unsigned char *ptr; | |
254 | struct rgb_color *fcolrs; | |
255 | ||
256 | fcolrs = (struct rgb_color *) malloc((MAXCOLORS + 1) * sizeof(struct rgb_color)); | |
257 | ||
258 | fcnt = 0; | |
259 | ptr = data1; | |
260 | for (i = 0; i < (width * height); i++) { | |
261 | indx = (int) *ptr; | |
262 | for (j = 0; j < fcnt; j++) { | |
263 | if ((fcolrs[j].red == colrs1[indx].red) && | |
264 | (fcolrs[j].green == colrs1[indx].green) && | |
265 | (fcolrs[j].blue == colrs1[indx].blue)) { | |
266 | break; | |
267 | } | |
268 | } | |
269 | if (j == fcnt) { | |
270 | fcolrs[j].red = colrs1[indx].red; | |
271 | fcolrs[j].green = colrs1[indx].green; | |
272 | fcolrs[j].blue = colrs1[indx].blue; | |
273 | Mapping[indx] = j; | |
274 | fcnt++; | |
275 | if (fcnt > MAXCOLORS) { | |
276 | fprintf(stderr, "Error: cannot use more than %d colors in your fish\n", | |
277 | MAXCOLORS); | |
278 | exit(1); | |
279 | } | |
280 | } | |
281 | ptr++; | |
282 | } | |
283 | ptr = data1; | |
284 | for (i = 0; i < (width * height); i++) { | |
285 | indx = (int) *ptr; | |
286 | *ptr = (unsigned char) (Mapping[indx]); | |
287 | ptr++; | |
288 | } | |
289 | ||
290 | ptr = data2; | |
291 | for (i = 0; i < (width * height); i++) { | |
292 | indx = (int) *ptr; | |
293 | for (j = 0; j < fcnt; j++) { | |
294 | if ((fcolrs[j].red == colrs2[indx].red) && | |
295 | (fcolrs[j].green == colrs2[indx].green) && | |
296 | (fcolrs[j].blue == colrs2[indx].blue)) { | |
297 | break; | |
298 | } | |
299 | } | |
300 | if (j == fcnt) { | |
301 | fcolrs[j].red = colrs2[indx].red; | |
302 | fcolrs[j].green = colrs2[indx].green; | |
303 | fcolrs[j].blue = colrs2[indx].blue; | |
304 | Mapping[indx] = j; | |
305 | fcnt++; | |
306 | if (fcnt > MAXCOLORS) { | |
307 | fprintf(stderr, "Error: cannot use more than %d colors in your fish\n", | |
308 | MAXCOLORS); | |
309 | exit(1); | |
310 | } | |
311 | } | |
312 | ptr++; | |
313 | } | |
314 | ptr = data2; | |
315 | for (i = 0; i < (width * height); i++) { | |
316 | indx = (int) *ptr; | |
317 | *ptr = (unsigned char) (Mapping[indx]); | |
318 | ptr++; | |
319 | } | |
320 | ||
321 | for (i = 0; i < fcnt; i++) { | |
322 | fcolrs[i].red = fcolrs[i].red * 256; | |
323 | fcolrs[i].green = fcolrs[i].green * 256; | |
324 | fcolrs[i].blue = fcolrs[i].blue * 256; | |
325 | } | |
326 | for (i = fcnt; i < 16; i++) { | |
327 | fcolrs[i].red = 0; | |
328 | fcolrs[i].green = 0; | |
329 | fcolrs[i].blue = 0; | |
330 | } | |
331 | ||
332 | if (fcnt < 16) { | |
333 | fcnt = 16; | |
334 | } | |
335 | *Cnt = fcnt; | |
336 | return (fcolrs); | |
337 | } | |
338 | ||
339 | ||
340 | ||
341 | main(argc, argv) | |
342 | int argc; | |
343 | char *argv[]; | |
344 | { | |
345 | FILE *ifd; | |
346 | FILE *ofd; | |
347 | int i, cnt, fcnt; | |
348 | struct rgb_color colrs1[MAXCOLORS]; | |
349 | struct rgb_color colrs2[MAXCOLORS]; | |
350 | struct rgb_color *fcolrs; | |
351 | unsigned char *data1, *data2; | |
352 | int width1, height1, width2, height2; | |
353 | char outfile[256]; | |
354 | char *outname; | |
355 | int num_cnt; | |
356 | ||
357 | if (argc < 3) { | |
358 | fprintf(stderr, "Usage: %s <fish1> <fish2> [<outprefix>]\n", argv[0]); | |
359 | exit(1); | |
360 | } | |
361 | ||
362 | ifd = fopen(argv[1], "r"); | |
363 | if (ifd == NULL) { | |
364 | fprintf(stderr, "Error: cannot open (%s) for read\n", argv[1]); | |
365 | exit(1); | |
366 | } | |
367 | ||
368 | data1 = ReadCompactEbmBitmap(ifd, &width1, &height1, colrs1); | |
369 | if (data1 == NULL) { | |
370 | rewind(ifd); | |
371 | data1 = ReadEbmBitmap(ifd, &width1, &height1, colrs1); | |
372 | } | |
373 | if (data1 == NULL) { | |
374 | rewind(ifd); | |
375 | data1 = ReadGifBitmap(ifd, &width1, &height1, colrs1); | |
376 | } | |
377 | fclose(ifd); | |
378 | ||
379 | if (data1 == NULL) { | |
380 | fprintf(stderr, "Error: (%s) has unknown format\n", argv[1]); | |
381 | exit(1); | |
382 | } | |
383 | ||
384 | ifd = fopen(argv[2], "r"); | |
385 | if (ifd == NULL) { | |
386 | fprintf(stderr, "Error: cannot open (%s) for read\n", argv[2]); | |
387 | exit(1); | |
388 | } | |
389 | ||
390 | data2 = ReadCompactEbmBitmap(ifd, &width2, &height2, colrs2); | |
391 | if (data2 == NULL) { | |
392 | rewind(ifd); | |
393 | data2 = ReadEbmBitmap(ifd, &width2, &height2, colrs2); | |
394 | } | |
395 | if (data2 == NULL) { | |
396 | rewind(ifd); | |
397 | data2 = ReadGifBitmap(ifd, &width2, &height2, colrs2); | |
398 | } | |
399 | fclose(ifd); | |
400 | ||
401 | if (data2 == NULL) { | |
402 | fprintf(stderr, "Error: (%s) has unknown format\n", argv[2]); | |
403 | exit(1); | |
404 | } | |
405 | ||
406 | ||
407 | if ((width1 != width2) || (height1 != height2)) { | |
408 | fprintf(stderr, "Error: fish must have same dimensions\n"); | |
409 | exit(1); | |
410 | } | |
411 | ||
412 | fcolrs = MapColors(data1, colrs1, data2, colrs2, width1, height1, &fcnt); | |
413 | ||
414 | if (data1[0] != data2[0]) { | |
415 | fprintf(stderr, "Error: fish must have same backgrounds\n"); | |
416 | exit(1); | |
417 | } | |
418 | ||
419 | if (argc >= 4) { | |
420 | outname = argv[3]; | |
421 | } else { | |
422 | cnt = 0; | |
423 | while ((argv[1][cnt] == argv[2][cnt]) && (argv[1][cnt] != '.') && (argv[2][cnt] != '.')) { | |
424 | cnt++; | |
425 | } | |
426 | if (cnt == 0) { | |
427 | fprintf(stderr, "Error: files need common prefix\n"); | |
428 | exit(1); | |
429 | } | |
430 | outname = (char *) malloc(cnt + 1); | |
431 | strncpy(outname, argv[1], cnt); | |
432 | outname[cnt] = '\0'; | |
433 | } | |
434 | sprintf(outfile, "%s.h", outname); | |
435 | ||
436 | ofd = fopen(outfile, "w"); | |
437 | if (ofd == NULL) { | |
438 | fprintf(stderr, "Error: cannot open (%s) for writing\n", outfile); | |
439 | exit(1); | |
440 | } | |
441 | ||
442 | fprintf(ofd, "#define %s_width\t\t%d\n", outname, width1); | |
443 | fprintf(ofd, "#define %s_height\t\t%d\n", outname, height1); | |
444 | fprintf(ofd, "#define %s_colors\t\t%d\n", outname, fcnt); | |
445 | fprintf(ofd, "#define %s_back\t\t%d\n", outname, (int) data1[0]); | |
446 | fprintf(ofd, "int\t%s_reds[] = {", outname); | |
447 | num_cnt = 0; | |
448 | for (i = 0; i < fcnt; i++) { | |
449 | if (i == (fcnt - 1)) { | |
450 | fprintf(ofd, "%d};\n", fcolrs[i].red); | |
451 | } else { | |
452 | fprintf(ofd, "%d, ", fcolrs[i].red); | |
453 | if (++num_cnt >= COLS_PER_LINE) { | |
454 | fprintf(ofd, "\n"); | |
455 | num_cnt = 0; | |
456 | } | |
457 | } | |
458 | } | |
459 | fprintf(ofd, "int\t%s_greens[] = {", outname); | |
460 | num_cnt = 0; | |
461 | for (i = 0; i < fcnt; i++) { | |
462 | if (i == (fcnt - 1)) { | |
463 | fprintf(ofd, "%d};\n", fcolrs[i].green); | |
464 | } else { | |
465 | fprintf(ofd, "%d, ", fcolrs[i].green); | |
466 | if (++num_cnt >= COLS_PER_LINE) { | |
467 | fprintf(ofd, "\n"); | |
468 | num_cnt = 0; | |
469 | } | |
470 | } | |
471 | } | |
472 | fprintf(ofd, "int\t%s_blues[] = {", outname); | |
473 | num_cnt = 0; | |
474 | for (i = 0; i < fcnt; i++) { | |
475 | if (i == (fcnt - 1)) { | |
476 | fprintf(ofd, "%d};\n", fcolrs[i].blue); | |
477 | } else { | |
478 | fprintf(ofd, "%d, ", fcolrs[i].blue); | |
479 | if (++num_cnt >= COLS_PER_LINE) { | |
480 | fprintf(ofd, "\n"); | |
481 | num_cnt = 0; | |
482 | } | |
483 | } | |
484 | } | |
485 | fprintf(ofd, "unsigned char\t%s_rasterA[] = {\n", outname); | |
486 | num_cnt = 0; | |
487 | for (i = 0; i < (width1 * height1); i++) { | |
488 | fprintf(ofd, "0x%02x,", data1[i]); | |
489 | if (++num_cnt >= NUMS_PER_LINE) { | |
490 | fprintf(ofd, "\n"); | |
491 | num_cnt = 0; | |
492 | } | |
493 | } | |
494 | fprintf(ofd, "};\n"); | |
495 | fprintf(ofd, "unsigned char\t%s_rasterB[] = {\n", outname); | |
496 | num_cnt = 0; | |
497 | for (i = 0; i < (width1 * height1); i++) { | |
498 | fprintf(ofd, "0x%02x,", data2[i]); | |
499 | if (++num_cnt >= NUMS_PER_LINE) { | |
500 | fprintf(ofd, "\n"); | |
501 | num_cnt = 0; | |
502 | } | |
503 | } | |
504 | fprintf(ofd, "};\n"); | |
505 | ||
506 | fclose(ofd); | |
507 | ||
508 | exit(0); | |
509 | } |