]>
Commit | Line | Data |
---|---|---|
2ac45f02 MG |
1 | #include <X11/Xlib.h> |
2 | #include <stdio.h> | |
3 | #include <stdlib.h> | |
4 | #include <string.h> | |
5 | #include "compact.h" | |
6 | #include "medcut.h" | |
7 | ||
8 | #define DEF_BLACK BlackPixel(Dpy, DefaultScreen(Dpy)) | |
9 | #define DEF_WHITE WhitePixel(Dpy, DefaultScreen(Dpy)) | |
10 | #define MAX_LINE 81 | |
11 | ||
12 | ||
13 | extern unsigned char *ReadGifBitmap(); | |
14 | ||
15 | ||
16 | extern Display *Dpy; | |
17 | ||
18 | int NumColors; | |
19 | ||
20 | char nibMask[8] = { | |
21 | 1, 2, 4, 8, 16, 32, 64, 128 | |
22 | }; | |
23 | ||
24 | ||
25 | ||
26 | /* | |
27 | * dscan is a quick replacement for: | |
28 | * | |
29 | * fscanf (fp, "%d", &ip); | |
30 | */ | |
31 | dscan(fp, ip) | |
32 | FILE *fp; | |
33 | int *ip; | |
34 | { | |
35 | ||
36 | register int v = 0; | |
37 | register int n = 0; | |
38 | int done = 0; | |
39 | static int nerrors; | |
40 | ||
41 | while (!done) { | |
42 | register int i; | |
43 | i = getc(fp); | |
44 | if (i < 0) { | |
45 | *ip = v; | |
46 | fprintf(stderr, "dscanf: EOF"); | |
47 | if (nerrors++ > 2) | |
48 | return (-1); | |
49 | else if (nerrors++ > 4) | |
50 | exit(-1); | |
51 | return (n); | |
52 | } | |
53 | i &= 0xFF; | |
54 | switch (i) { | |
55 | case '0': | |
56 | case '1': | |
57 | case '2': | |
58 | case '3': | |
59 | case '4': | |
60 | case '5': | |
61 | case '6': | |
62 | case '7': | |
63 | case '8': | |
64 | case '9': | |
65 | v = i - '0' + (v * 10); | |
66 | n++; | |
67 | break; | |
68 | case '\n': | |
69 | case '\r': | |
70 | case ' ': | |
71 | case '\t': | |
72 | if (n) { | |
73 | *ip = v; | |
74 | done = 1; | |
75 | } | |
76 | break; | |
77 | default: | |
78 | fprintf(stderr, "dscanf: non numeric character (0x%x) '%c'\n", i, i); | |
79 | if (nerrors++ > 4) | |
80 | exit(-1); | |
81 | return (-1); | |
82 | ||
83 | } | |
84 | } | |
85 | return (n); | |
86 | } | |
87 | ||
88 | ||
89 | unsigned char * | |
90 | ReadXpmPixmap(fp, w, h, colrs, Colors, CharsPP) | |
91 | FILE *fp; | |
92 | int *w, *h; | |
93 | struct colr_data *colrs; | |
94 | int Colors, CharsPP; | |
95 | { | |
96 | unsigned char *pixels; | |
97 | char **Color_Vals; | |
98 | XColor tmpcolr; | |
99 | int i, j, k; | |
100 | int value, found; | |
101 | char line[BUFSIZ], name_and_type[MAX_LINE]; | |
102 | unsigned char *dataP; | |
103 | unsigned char *bitp; | |
104 | int tchar; | |
105 | char *t; | |
106 | char *t2; | |
107 | ||
108 | NumColors = 256; | |
109 | if (Colors == 0) { | |
110 | fprintf(stderr, "Can't find Colors.\n"); | |
111 | return ((unsigned char *) NULL); | |
112 | } | |
113 | if (*w == 0) { | |
114 | fprintf(stderr, "Invalid width.\n"); | |
115 | return ((unsigned char *) NULL); | |
116 | } | |
117 | if (*h == 0) { | |
118 | fprintf(stderr, "Invalid height.\n"); | |
119 | return ((unsigned char *) NULL); | |
120 | } | |
121 | ||
122 | Color_Vals = (char **) malloc(sizeof(char *) * Colors); | |
123 | for (i = 0; i < Colors; i++) { | |
124 | tchar = getc(fp); | |
125 | while ((tchar != '"') && (tchar != EOF)) { | |
126 | tchar = getc(fp); | |
127 | } | |
128 | Color_Vals[i] = (char *) malloc(sizeof(char) * (CharsPP + 1)); | |
129 | j = 0; | |
130 | tchar = getc(fp); | |
131 | while ((tchar != '"') && (tchar != EOF) && (j < CharsPP)) { | |
132 | Color_Vals[i][j] = (char) tchar; | |
133 | tchar = getc(fp); | |
134 | j++; | |
135 | } | |
136 | Color_Vals[i][j] = '\0'; | |
137 | if (tchar != '"') { | |
138 | tchar = getc(fp); | |
139 | while ((tchar != '"') && (tchar != EOF)) { | |
140 | tchar = getc(fp); | |
141 | } | |
142 | } | |
143 | tchar = getc(fp); | |
144 | while ((tchar != '"') && (tchar != EOF)) { | |
145 | tchar = getc(fp); | |
146 | } | |
147 | j = 0; | |
148 | tchar = getc(fp); | |
149 | while ((tchar != '"') && (tchar != EOF)) { | |
150 | line[j] = (char) tchar; | |
151 | tchar = getc(fp); | |
152 | j++; | |
153 | } | |
154 | line[j] = '\0'; | |
155 | XParseColor(Dpy, DefaultColormap(Dpy, DefaultScreen(Dpy)), line, &tmpcolr); | |
156 | colrs[i].red = tmpcolr.red; | |
157 | colrs[i].green = tmpcolr.green; | |
158 | colrs[i].blue = tmpcolr.blue; | |
159 | } | |
160 | for (i = Colors; i < 256; i++) { | |
161 | colrs[i].red = 0; | |
162 | colrs[i].green = 0; | |
163 | colrs[i].blue = 0; | |
164 | } | |
165 | tchar = getc(fp); | |
166 | while ((tchar != ';') && (tchar != EOF)) { | |
167 | tchar = getc(fp); | |
168 | } | |
169 | ||
170 | for (;;) { | |
171 | if (!(fgets(line, MAX_LINE, fp))) { | |
172 | fprintf(stderr, "Can't find Pixels\n"); | |
173 | return ((unsigned char *) NULL); | |
174 | } else if (sscanf(line, "static char * %s = {", name_and_type) == 1) { | |
175 | if ((t = (char *) rindex(name_and_type, '_')) == NULL) { | |
176 | t = name_and_type; | |
177 | } else { | |
178 | t++; | |
179 | } | |
180 | if ((t2 = (char *) index(name_and_type, '[')) != NULL) { | |
181 | *t2 = '\0'; | |
182 | } | |
183 | if (!strcmp("pixels", t)) { | |
184 | break; | |
185 | } | |
186 | } | |
187 | } | |
188 | pixels = (unsigned char *) malloc((*w) * (*h)); | |
189 | if (pixels == NULL) { | |
190 | fprintf(stderr, "Not enough memory for data.\n"); | |
191 | return ((unsigned char *) NULL); | |
192 | } | |
193 | ||
194 | line[0] = '\0'; | |
195 | t = line; | |
196 | dataP = pixels; | |
197 | tchar = getc(fp); | |
198 | while ((tchar != '"') && (tchar != EOF)) { | |
199 | tchar = getc(fp); | |
200 | } | |
201 | tchar = getc(fp); | |
202 | for (j = 0; j < (*h); j++) { | |
203 | for (i = 0; i < (*w); i++) { | |
204 | k = 0; | |
205 | while ((tchar != '"') && (tchar != EOF) && (k < CharsPP)) { | |
206 | line[k] = (char) tchar; | |
207 | tchar = getc(fp); | |
208 | k++; | |
209 | } | |
210 | if ((k == 0) && (tchar == '"')) { | |
211 | tchar = getc(fp); | |
212 | while ((tchar != '"') && (tchar != EOF)) { | |
213 | tchar = getc(fp); | |
214 | } | |
215 | k = 0; | |
216 | tchar = getc(fp); | |
217 | while ((tchar != '"') && (tchar != EOF) && (k < CharsPP)) { | |
218 | line[k] = (char) tchar; | |
219 | tchar = getc(fp); | |
220 | k++; | |
221 | } | |
222 | } | |
223 | line[k] = '\0'; | |
224 | found = 0; | |
225 | for (k = 0; k < Colors; k++) { | |
226 | if (strncmp(Color_Vals[k], line, CharsPP) == 0) { | |
227 | *dataP++ = (unsigned char) k; | |
228 | found = 1; | |
229 | break; | |
230 | } | |
231 | } | |
232 | if (found == 0) { | |
233 | fprintf(stderr, "Invalid Pixel (%2s) in file\n", line); | |
234 | *dataP++ = (unsigned char) 0; | |
235 | } | |
236 | } | |
237 | } | |
238 | bitp = pixels; | |
239 | for (i = 0; i < ((*w) * (*h)); i++) { | |
240 | if ((int) *bitp > (256 - 1)) | |
241 | *bitp = (unsigned char) 0; | |
242 | bitp++; | |
243 | } | |
244 | for (i = 0; i < Colors; i++) { | |
245 | free((char *) Color_Vals[i]); | |
246 | } | |
247 | free((char *) Color_Vals); | |
248 | return (pixels); | |
249 | } | |
250 | ||
251 | ||
252 | unsigned char * | |
253 | ReadXbmBitmap(fp, w, h, colrs) | |
254 | FILE *fp; | |
255 | int *w, *h; | |
256 | struct colr_data *colrs; | |
257 | { | |
258 | int blackbit = BlackPixel(Dpy, DefaultScreen(Dpy)); | |
259 | int whitebit = WhitePixel(Dpy, DefaultScreen(Dpy)); | |
260 | char line[MAX_LINE], name_and_type[MAX_LINE]; | |
261 | char *t; | |
262 | char *t2; | |
263 | unsigned char *ptr, *dataP; | |
264 | int bytes_per_line, version10p, raster_length, padding; | |
265 | int i, bytes, temp, value; | |
266 | int Ncolors, charspp, xpmformat; | |
267 | ||
268 | *w = 0; | |
269 | *h = 0; | |
270 | Ncolors = 0; | |
271 | charspp = 0; | |
272 | xpmformat = 0; | |
273 | for (;;) { | |
274 | if (!(fgets(line, MAX_LINE, fp))) | |
275 | break; | |
276 | if (strlen(line) == (MAX_LINE - 1)) { | |
277 | fprintf(stderr, "Line too long.\n"); | |
278 | return ((unsigned char *) NULL); | |
279 | } | |
280 | if (sscanf(line, "#define %s %d", name_and_type, &value) == 2) { | |
281 | if (!(t = (char *) rindex(name_and_type, '_'))) | |
282 | t = name_and_type; | |
283 | else | |
284 | t++; | |
285 | if (!strcmp("width", t)) | |
286 | *w = value; | |
287 | if (!strcmp("height", t)) | |
288 | *h = value; | |
289 | if (!strcmp("ncolors", t)) | |
290 | Ncolors = value; | |
291 | if (!strcmp("pixel", t)) | |
292 | charspp = value; | |
293 | continue; | |
294 | } | |
295 | if (sscanf(line, "static short %s = {", name_and_type) == 1) { | |
296 | version10p = 1; | |
297 | break; | |
298 | } else if (sscanf(line, "static char * %s = {", name_and_type) == 1) { | |
299 | xpmformat = 1; | |
300 | if (!(t = (char *) rindex(name_and_type, '_'))) | |
301 | t = name_and_type; | |
302 | else | |
303 | t++; | |
304 | if ((t2 = (char *) index(name_and_type, '[')) != NULL) | |
305 | *t2 = '\0'; | |
306 | if (!strcmp("mono", t)) | |
307 | continue; | |
308 | else | |
309 | break; | |
310 | } else if (sscanf(line, "static char %s = {", name_and_type) == 1) { | |
311 | version10p = 0; | |
312 | break; | |
313 | } else | |
314 | continue; | |
315 | } | |
316 | if (xpmformat) { | |
317 | dataP = ReadXpmPixmap(fp, w, h, colrs, Ncolors, charspp); | |
318 | return (dataP); | |
319 | } | |
320 | if (*w == 0) { | |
321 | fprintf(stderr, "Invalid width.\n"); | |
322 | return ((unsigned char *) NULL); | |
323 | } | |
324 | if (*h == 0) { | |
325 | fprintf(stderr, "Invalid height.\n"); | |
326 | return ((unsigned char *) NULL); | |
327 | } | |
328 | padding = 0; | |
329 | if (((*w % 16) >= 1) && ((*w % 16) <= 8) && version10p) { | |
330 | padding = 1; | |
331 | } | |
332 | bytes_per_line = ((*w + 7) / 8) + padding; | |
333 | raster_length = bytes_per_line * *h; | |
334 | dataP = (unsigned char *) malloc((*w) * (*h)); | |
335 | if (dataP == NULL) { | |
336 | fprintf(stderr, "Not enough memory.\n"); | |
337 | return ((unsigned char *) NULL); | |
338 | } | |
339 | ptr = dataP; | |
340 | if (version10p) { | |
341 | int cnt = 0; | |
342 | int lim = (bytes_per_line - padding) * 8; | |
343 | for (bytes = 0; bytes < raster_length; bytes += 2) { | |
344 | if (fscanf(fp, " 0x%x%*[,}]%*[ \n]", &value) != 1) { | |
345 | fprintf(stderr, "Error scanning bits item.\n"); | |
346 | return ((unsigned char *) NULL); | |
347 | } | |
348 | temp = value; | |
349 | value = temp & 0xff; | |
350 | for (i = 0; i < 8; i++) { | |
351 | if (cnt < (*w)) { | |
352 | if (value & nibMask[i]) | |
353 | *ptr++ = blackbit; | |
354 | else | |
355 | *ptr++ = whitebit; | |
356 | } | |
357 | if (++cnt >= lim) | |
358 | cnt = 0; | |
359 | } | |
360 | if ((!padding) || ((bytes + 2) % bytes_per_line)) { | |
361 | value = temp >> 8; | |
362 | for (i = 0; i < 8; i++) { | |
363 | if (cnt < (*w)) { | |
364 | if (value & nibMask[i]) | |
365 | *ptr++ = blackbit; | |
366 | else | |
367 | *ptr++ = whitebit; | |
368 | } | |
369 | if (++cnt >= lim) | |
370 | cnt = 0; | |
371 | } | |
372 | } | |
373 | } | |
374 | } else { | |
375 | int cnt = 0; | |
376 | int lim = bytes_per_line * 8; | |
377 | for (bytes = 0; bytes < raster_length; bytes++) { | |
378 | if (fscanf(fp, " 0x%x%*[,}]%*[ \n]", &value) != 1) { | |
379 | fprintf(stderr, "Error scanning bits item.\n"); | |
380 | return ((unsigned char *) NULL); | |
381 | } | |
382 | for (i = 0; i < 8; i++) { | |
383 | if (cnt < (*w)) { | |
384 | if (value & nibMask[i]) | |
385 | *ptr++ = blackbit; | |
386 | else | |
387 | *ptr++ = whitebit; | |
388 | } | |
389 | if (++cnt >= lim) | |
390 | cnt = 0; | |
391 | } | |
392 | } | |
393 | } | |
394 | NumColors = 2; | |
395 | return (dataP); | |
396 | } | |
397 | ||
398 | ||
399 | unsigned char * | |
400 | ReadEbmBitmap(fp, w, h, colrs) | |
401 | FILE *fp; | |
402 | int *w, *h; | |
403 | struct colr_data *colrs; | |
404 | { | |
405 | int i, temp, scale; | |
406 | unsigned int bmap_size; | |
407 | int *ptr[3]; | |
408 | int red, green, blue; | |
409 | char line[1024]; | |
410 | unsigned char *bit_data; | |
411 | unsigned char *bitp; | |
412 | ||
413 | bit_data = NULL; | |
414 | *w = 0; | |
415 | *h = 0; | |
416 | ||
417 | if ((fscanf(fp, "%12s %d %d %d\n", line, w, h, &scale) == 4) && | |
418 | (strcmp(line, "xstitch_data") == 0)) { | |
419 | for (i = 0; i < 3; i++) { | |
420 | fscanf(fp, "%s", line); | |
421 | if (strcmp(line, "red") == 0) { | |
422 | ptr[i] = &red; | |
423 | } else if (strcmp(line, "green") == 0) { | |
424 | ptr[i] = &green; | |
425 | } else if (strcmp(line, "blue") == 0) { | |
426 | ptr[i] = &blue; | |
427 | } else { | |
428 | fprintf(stderr, "File has improper format\n"); | |
429 | return ((unsigned char *) NULL); | |
430 | } | |
431 | } | |
432 | fscanf(fp, "[^\n]\n"); | |
433 | for (i = 0; i < scale; i++) { | |
434 | line[0] = '\0'; | |
435 | if (fscanf(fp, "%d %d %d%[^\n]\n", ptr[0], ptr[1], ptr[2], line) < 3) { | |
436 | fprintf(stderr, "Bad color data #%d\n", i); | |
437 | } | |
438 | colrs[i].red = red * 65536 / scale; | |
439 | colrs[i].green = green * 65536 / scale; | |
440 | colrs[i].blue = blue * 65536 / scale; | |
441 | } | |
442 | for (i = scale; i < 256; i++) { | |
443 | colrs[i].red = 0; | |
444 | colrs[i].green = 0; | |
445 | colrs[i].blue = 0; | |
446 | } | |
447 | ||
448 | bmap_size = (*w) * (*h); | |
449 | bit_data = (unsigned char *) malloc(bmap_size); | |
450 | if (bit_data == NULL) { | |
451 | fprintf(stderr, "Cannot allocate space for bitmap\n"); | |
452 | } | |
453 | bitp = bit_data; | |
454 | for (i = 0; i < bmap_size; i++) { | |
455 | if (dscan(fp, &temp) == -1) | |
456 | break; | |
457 | if (temp > (256 - 1)) | |
458 | temp = 0; | |
459 | *bitp = (unsigned char) temp; | |
460 | bitp++; | |
461 | } | |
462 | } else { | |
463 | return ((unsigned char *) NULL); | |
464 | } | |
465 | NumColors = scale; | |
466 | return (bit_data); | |
467 | } | |
468 | ||
469 | ||
470 | int | |
471 | swapint(in) | |
472 | int in; | |
473 | { | |
474 | int out; | |
475 | ||
476 | out = 0; | |
477 | out = out | ((in >> 24) & 0xff); | |
478 | out = out | ((in >> 8) & 0xff00); | |
479 | out = out | ((in << 8) & 0xff0000); | |
480 | out = out | ((in << 24) & 0xff000000); | |
481 | return (out); | |
482 | } | |
483 | ||
484 | ||
485 | unsigned char * | |
486 | ReadCompactEbmBitmap(fp, w, h, colrs) | |
487 | FILE *fp; | |
488 | int *w, *h; | |
489 | struct colr_data *colrs; | |
490 | { | |
491 | int i, scale; | |
492 | unsigned int bmap_size; | |
493 | char pix_file[1024]; | |
494 | unsigned char *bit_data; | |
495 | unsigned char *bitp; | |
496 | struct ebmhdr Hdr; | |
497 | struct rgb_color color_data; | |
498 | int doswap; | |
499 | ||
500 | doswap = 0; | |
501 | bit_data = NULL; | |
502 | *w = 0; | |
503 | *h = 0; | |
504 | ||
505 | fread(&Hdr, sizeof(struct ebmhdr), 1, fp); | |
506 | if (strcmp(Hdr.magic, "xstitch") == 0) { | |
507 | /* | |
508 | * a horrible hack to deal with different byte ordering on | |
509 | * different machines. Is based on assumption of only 2 | |
510 | * possible byte orderings, and never more than 256 colors. | |
511 | */ | |
512 | if (Hdr.num_colors > 256) { | |
513 | doswap = 1; | |
514 | Hdr.width = swapint(Hdr.width); | |
515 | Hdr.height = swapint(Hdr.height); | |
516 | Hdr.num_colors = swapint(Hdr.num_colors); | |
517 | } | |
518 | ||
519 | *w = Hdr.width; | |
520 | *h = Hdr.height; | |
521 | scale = Hdr.num_colors; | |
522 | for (i = 0; i < Hdr.num_colors; i++) { | |
523 | fread(&color_data, sizeof(struct rgb_color), 1, fp); | |
524 | if (doswap) { | |
525 | color_data.red = swapint(color_data.red); | |
526 | color_data.green = swapint(color_data.green); | |
527 | color_data.blue = swapint(color_data.blue); | |
528 | color_data.pix_len = swapint(color_data.pix_len); | |
529 | } | |
530 | colrs[i].red = color_data.red * 65536 / scale; | |
531 | colrs[i].green = color_data.green * 65536 / scale; | |
532 | colrs[i].blue = color_data.blue * 65536 / scale; | |
533 | if (color_data.pix_len != 0) { | |
534 | if (color_data.pix_len > 1023) { | |
535 | fprintf(stderr, "bad pattern\n"); | |
536 | return ((unsigned char *) NULL); | |
537 | } | |
538 | fread(pix_file, sizeof(char), color_data.pix_len, fp); | |
539 | } | |
540 | } | |
541 | for (i = scale; i < 256; i++) { | |
542 | colrs[i].red = 0; | |
543 | colrs[i].green = 0; | |
544 | colrs[i].blue = 0; | |
545 | } | |
546 | ||
547 | bmap_size = (*w) * (*h); | |
548 | bit_data = (unsigned char *) malloc(bmap_size); | |
549 | if (bit_data == NULL) { | |
550 | fprintf(stderr, "Cannot allocate space for bitmap\n"); | |
551 | } | |
552 | fread(bit_data, sizeof(unsigned char), ((*w) * (*h)), fp); | |
553 | ||
554 | bitp = bit_data; | |
555 | for (i = 0; i < bmap_size; i++) { | |
556 | if ((int) *bitp > (256 - 1)) | |
557 | *bitp = (unsigned char) 0; | |
558 | bitp++; | |
559 | } | |
560 | } else { | |
561 | return ((unsigned char *) NULL); | |
562 | } | |
563 | NumColors = scale; | |
564 | return (bit_data); | |
565 | } | |
566 | ||
567 | ||
568 | unsigned char * | |
569 | ReadBitmap(fp, w, h, colrs) | |
570 | FILE *fp; | |
571 | int *w, *h; | |
572 | struct colr_data *colrs; | |
573 | { | |
574 | unsigned char *bit_data; | |
575 | ||
576 | NumColors = 0; | |
577 | ||
578 | if (fp != NULL) { | |
579 | bit_data = ReadEbmBitmap(fp, w, h, colrs); | |
580 | if (bit_data != NULL) { | |
581 | return (bit_data); | |
582 | } | |
583 | rewind(fp); | |
584 | bit_data = ReadCompactEbmBitmap(fp, w, h, colrs); | |
585 | if (bit_data != NULL) { | |
586 | return (bit_data); | |
587 | } | |
588 | #ifdef GIF | |
589 | rewind(fp); | |
590 | bit_data = ReadGifBitmap(fp, w, h, colrs); | |
591 | if (bit_data != NULL) { | |
592 | return (bit_data); | |
593 | } | |
594 | #endif | |
595 | rewind(fp); | |
596 | bit_data = ReadXbmBitmap(fp, w, h, colrs); | |
597 | if (bit_data != NULL) { | |
598 | return (bit_data); | |
599 | } | |
600 | } | |
601 | return ((unsigned char *) NULL); | |
602 | } |