1 /* Copyright (C) 2001-2017 Peter Selinger.
2 This file is part of Potrace. It is free software and it is covered
3 by the GNU General Public License. See the file COPYING for details. */
4
5
6 /* Routines for manipulating bitmaps, including reading pbm files. */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13
14 #include "bitmap.h"
15 #include "bitops.h"
16 #include "bitmap_io.h"
17
18 #define INTBITS (8*sizeof(int))
19
20 static int bm_readbody_bmp(FILE *f, double threshold, potrace_bitmap_t **bmp);
21 static int bm_readbody_pnm(FILE *f, double threshold, potrace_bitmap_t **bmp, int magic);
22
23 #define TRY(x) if (x) goto try_error
24 #define TRY_EOF(x) if (x) goto eof
25 #define TRY_STD(x) if (x) goto std_error
26
27 /* ---------------------------------------------------------------------- */
28 /* routines for reading pnm streams */
29
30 /* read next character after whitespace and comments. Return EOF on
31 end of file or error. */
fgetc_ws(FILE * f)32 static int fgetc_ws(FILE *f) {
33 int c;
34
35 while (1) {
36 c = fgetc(f);
37 if (c=='#') {
38 while (1) {
39 c = fgetc(f);
40 if (c=='\n' || c==EOF) {
41 break;
42 }
43 }
44 }
45 /* space, tab, line feed, carriage return, form-feed */
46 if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12) {
47 return c;
48 }
49 }
50 }
51
52 /* skip whitespace and comments, then read a non-negative decimal
53 number from a stream. Return -1 on EOF. Tolerate other errors (skip
54 bad characters). Do not the read any characters following the
55 number (put next character back into the stream) */
56
readnum(FILE * f)57 static int readnum(FILE *f) {
58 int c;
59 int acc;
60
61 /* skip whitespace and comments */
62 while (1) {
63 c = fgetc_ws(f);
64 if (c==EOF) {
65 return -1;
66 }
67 if (c>='0' && c<='9') {
68 break;
69 }
70 }
71
72 /* first digit is already in c */
73 acc = c-'0';
74 while (1) {
75 c = fgetc(f);
76 if (c==EOF) {
77 break;
78 }
79 if (c<'0' || c>'9') {
80 ungetc(c, f);
81 break;
82 }
83 acc *= 10;
84 acc += c-'0';
85 }
86 return acc;
87 }
88
89 /* similar to readnum, but read only a single 0 or 1, and do not read
90 any characters after it. */
91
readbit(FILE * f)92 static int readbit(FILE *f) {
93 int c;
94
95 /* skip whitespace and comments */
96 while (1) {
97 c = fgetc_ws(f);
98 if (c==EOF) {
99 return -1;
100 }
101 if (c>='0' && c<='1') {
102 break;
103 }
104 }
105
106 return c-'0';
107 }
108
109 /* ---------------------------------------------------------------------- */
110
111 /* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and
112 convert the output to a bitmap. Return bitmap in *bmp. Return 0 on
113 success, -1 on error with errno set, -2 on bad file format (with
114 error message in bm_read_error), and 1 on premature end of file, -3
115 on empty file (including files which contain only whitespace and
116 comments), -4 if wrong magic number. If the return value is >=0,
117 *bmp is valid. */
118
119 const char *bm_read_error = NULL;
120
bm_read(FILE * f,double threshold,potrace_bitmap_t ** bmp)121 int bm_read(FILE *f, double threshold, potrace_bitmap_t **bmp) {
122 int magic[2];
123
124 /* read magic number. We ignore whitespace and comments before the
125 magic, for the benefit of concatenated files in P1-P3 format.
126 Multiple P1-P3 images in a single file are not formally allowed
127 by the PNM standard, but there is no harm in being lenient. */
128
129 magic[0] = fgetc_ws(f);
130 if (magic[0] == EOF) {
131 return -3;
132 }
133 magic[1] = fgetc(f);
134 if (magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6') {
135 return bm_readbody_pnm(f, threshold, bmp, magic[1]);
136 }
137 if (magic[0] == 'B' && magic[1] == 'M') {
138 return bm_readbody_bmp(f, threshold, bmp);
139 }
140 return -4;
141 }
142
143 /* ---------------------------------------------------------------------- */
144 /* read PNM format */
145
146 /* read PNM stream after magic number. Return values as for bm_read */
bm_readbody_pnm(FILE * f,double threshold,potrace_bitmap_t ** bmp,int magic)147 static int bm_readbody_pnm(FILE *f, double threshold, potrace_bitmap_t **bmp, int magic) {
148 potrace_bitmap_t *bm;
149 int x, y, i, b, b1, sum;
150 int bpr; /* bytes per row (as opposed to 4*bm->c) */
151 int w, h, max;
152 int realheight; /* in case of incomplete file, keeps track of how
153 many scan lines actually contain data */
154
155 bm = NULL;
156
157 w = readnum(f);
158 if (w<0) {
159 goto format_error;
160 }
161
162 h = readnum(f);
163 if (h<0) {
164 goto format_error;
165 }
166
167 /* allocate bitmap */
168 bm = bm_new(w, h);
169 if (!bm) {
170 goto std_error;
171 }
172
173 realheight = 0;
174
175 switch (magic) {
176 default:
177 /* not reached */
178 goto format_error;
179
180 case '1':
181 /* read P1 format: PBM ascii */
182
183 for (y=0; y<h; y++) {
184 realheight = y+1;
185 for (x=0; x<w; x++) {
186 b = readbit(f);
187 if (b<0) {
188 goto eof;
189 }
190 BM_UPUT(bm, x, y, b);
191 }
192 }
193 break;
194
195 case '2':
196 /* read P2 format: PGM ascii */
197
198 max = readnum(f);
199 if (max<1) {
200 goto format_error;
201 }
202
203 for (y=0; y<h; y++) {
204 realheight = y+1;
205 for (x=0; x<w; x++) {
206 b = readnum(f);
207 if (b<0) {
208 goto eof;
209 }
210 BM_UPUT(bm, x, y, b > threshold * max ? 0 : 1);
211 }
212 }
213 break;
214
215 case '3':
216 /* read P3 format: PPM ascii */
217
218 max = readnum(f);
219 if (max<1) {
220 goto format_error;
221 }
222
223 for (y=0; y<h; y++) {
224 realheight = y+1;
225 for (x=0; x<w; x++) {
226 sum = 0;
227 for (i=0; i<3; i++) {
228 b = readnum(f);
229 if (b<0) {
230 goto eof;
231 }
232 sum += b;
233 }
234 BM_UPUT(bm, x, y, sum > 3 * threshold * max ? 0 : 1);
235 }
236 }
237 break;
238
239 case '4':
240 /* read P4 format: PBM raw */
241
242 b = fgetc(f); /* read single white-space character after height */
243 if (b==EOF) {
244 goto format_error;
245 }
246
247 bpr = (w+7)/8;
248
249 for (y=0; y<h; y++) {
250 realheight = y+1;
251 for (i=0; i<bpr; i++) {
252 b = fgetc(f);
253 if (b==EOF) {
254 goto eof;
255 }
256 *bm_index(bm, i*8, y) |= ((potrace_word)b) << (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)));
257 }
258 }
259 break;
260
261 case '5':
262 /* read P5 format: PGM raw */
263
264 max = readnum(f);
265 if (max<1) {
266 goto format_error;
267 }
268
269 b = fgetc(f); /* read single white-space character after max */
270 if (b==EOF) {
271 goto format_error;
272 }
273
274 for (y=0; y<h; y++) {
275 realheight = y+1;
276 for (x=0; x<w; x++) {
277 b = fgetc(f);
278 if (b==EOF)
279 goto eof;
280 if (max>=256) {
281 b <<= 8;
282 b1 = fgetc(f);
283 if (b1==EOF)
284 goto eof;
285 b |= b1;
286 }
287 BM_UPUT(bm, x, y, b > threshold * max ? 0 : 1);
288 }
289 }
290 break;
291
292 case '6':
293 /* read P6 format: PPM raw */
294
295 max = readnum(f);
296 if (max<1) {
297 goto format_error;
298 }
299
300 b = fgetc(f); /* read single white-space character after max */
301 if (b==EOF) {
302 goto format_error;
303 }
304
305 for (y=0; y<h; y++) {
306 realheight = y+1;
307 for (x=0; x<w; x++) {
308 sum = 0;
309 for (i=0; i<3; i++) {
310 b = fgetc(f);
311 if (b==EOF) {
312 goto eof;
313 }
314 if (max>=256) {
315 b <<= 8;
316 b1 = fgetc(f);
317 if (b1==EOF)
318 goto eof;
319 b |= b1;
320 }
321 sum += b;
322 }
323 BM_UPUT(bm, x, y, sum > 3 * threshold * max ? 0 : 1);
324 }
325 }
326 break;
327 }
328
329 bm_flip(bm);
330 *bmp = bm;
331 return 0;
332
333 eof:
334 TRY_STD(bm_resize(bm, realheight));
335 bm_flip(bm);
336 *bmp = bm;
337 return 1;
338
339 format_error:
340 bm_free(bm);
341 if (magic == '1' || magic == '4') {
342 bm_read_error = "invalid pbm file";
343 } else if (magic == '2' || magic == '5') {
344 bm_read_error = "invalid pgm file";
345 } else {
346 bm_read_error = "invalid ppm file";
347 }
348 return -2;
349
350 std_error:
351 bm_free(bm);
352 return -1;
353 }
354
355 /* ---------------------------------------------------------------------- */
356 /* read BMP format */
357
358 struct bmp_info_s {
359 unsigned int FileSize;
360 unsigned int reserved;
361 unsigned int DataOffset;
362 unsigned int InfoSize;
363 unsigned int w; /* width */
364 unsigned int h; /* height */
365 unsigned int Planes;
366 unsigned int bits; /* bits per sample */
367 unsigned int comp; /* compression mode */
368 unsigned int ImageSize;
369 unsigned int XpixelsPerM;
370 unsigned int YpixelsPerM;
371 unsigned int ncolors; /* number of colors in palette */
372 unsigned int ColorsImportant;
373 unsigned int RedMask;
374 unsigned int GreenMask;
375 unsigned int BlueMask;
376 unsigned int AlphaMask;
377 unsigned int ctbits; /* sample size for color table */
378 int topdown; /* top-down mode? */
379 };
380 typedef struct bmp_info_s bmp_info_t;
381
382 /* auxiliary */
383
384 static int bmp_count = 0; /* counter for byte padding */
385 static int bmp_pos = 0; /* counter from start of BMP data */
386
387 /* read n-byte little-endian integer. Return 1 on EOF or error, else
388 0. Assume n<=4. */
bmp_readint(FILE * f,int n,unsigned int * p)389 static int bmp_readint(FILE *f, int n, unsigned int *p) {
390 int i;
391 unsigned int sum = 0;
392 int b;
393
394 for (i=0; i<n; i++) {
395 b = fgetc(f);
396 if (b==EOF) {
397 return 1;
398 }
399 sum += (unsigned)b << (8*i);
400 }
401 bmp_count += n;
402 bmp_pos += n;
403 *p = sum;
404 return 0;
405 }
406
407 /* reset padding boundary */
bmp_pad_reset(void)408 static void bmp_pad_reset(void) {
409 bmp_count = 0;
410 }
411
412 /* read padding bytes to 4-byte boundary. Return 1 on EOF or error,
413 else 0. */
bmp_pad(FILE * f)414 static int bmp_pad(FILE *f) {
415 int c, i, b;
416
417 c = (-bmp_count) & 3;
418 for (i=0; i<c; i++) {
419 b = fgetc(f);
420 if (b==EOF) {
421 return 1;
422 }
423 }
424 bmp_pos += c;
425 bmp_count = 0;
426 return 0;
427 }
428
429 /* forward to the new file position. Return 1 on EOF or error, else 0 */
bmp_forward(FILE * f,int pos)430 static int bmp_forward(FILE *f, int pos) {
431 int b;
432
433 while (bmp_pos < pos) {
434 b = fgetc(f);
435 if (b==EOF) {
436 return 1;
437 }
438 bmp_pos++;
439 bmp_count++;
440 }
441 return 0;
442 }
443
444 /* safe colortable access */
445 #define COLTABLE(c) ((c) < bmpinfo.ncolors ? coltable[(c)] : 0)
446
447 /* read BMP stream after magic number. Return values as for bm_read.
448 We choose to be as permissive as possible, since there are many
449 programs out there which produce BMP. For instance, ppmtobmp can
450 produce codings with anywhere from 1-8 or 24 bits per sample,
451 although most specifications only allow 1,4,8,24,32. We can also
452 read both the old and new OS/2 BMP formats in addition to the
453 Windows BMP format. */
bm_readbody_bmp(FILE * f,double threshold,potrace_bitmap_t ** bmp)454 static int bm_readbody_bmp(FILE *f, double threshold, potrace_bitmap_t **bmp) {
455 bmp_info_t bmpinfo;
456 int *coltable;
457 unsigned int b, c;
458 unsigned int i;
459 potrace_bitmap_t *bm;
460 int mask;
461 unsigned int x, y;
462 int col[2];
463 unsigned int bitbuf;
464 unsigned int n;
465 unsigned int redshift, greenshift, blueshift;
466 int col1[2];
467 int realheight; /* in case of incomplete file, keeps track of how
468 many scan lines actually contain data */
469
470 bm_read_error = NULL;
471 bm = NULL;
472 coltable = NULL;
473
474 bmp_pos = 2; /* set file position */
475
476 /* file header (minus magic number) */
477 TRY(bmp_readint(f, 4, &bmpinfo.FileSize));
478 TRY(bmp_readint(f, 4, &bmpinfo.reserved));
479 TRY(bmp_readint(f, 4, &bmpinfo.DataOffset));
480
481 /* info header */
482 TRY(bmp_readint(f, 4, &bmpinfo.InfoSize));
483 if (bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64
484 || bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124) {
485 /* Windows or new OS/2 format */
486 bmpinfo.ctbits = 32; /* sample size in color table */
487 TRY(bmp_readint(f, 4, &bmpinfo.w));
488 TRY(bmp_readint(f, 4, &bmpinfo.h));
489 TRY(bmp_readint(f, 2, &bmpinfo.Planes));
490 TRY(bmp_readint(f, 2, &bmpinfo.bits));
491 TRY(bmp_readint(f, 4, &bmpinfo.comp));
492 TRY(bmp_readint(f, 4, &bmpinfo.ImageSize));
493 TRY(bmp_readint(f, 4, &bmpinfo.XpixelsPerM));
494 TRY(bmp_readint(f, 4, &bmpinfo.YpixelsPerM));
495 TRY(bmp_readint(f, 4, &bmpinfo.ncolors));
496 TRY(bmp_readint(f, 4, &bmpinfo.ColorsImportant));
497 if (bmpinfo.InfoSize >= 108) { /* V4 and V5 bitmaps */
498 TRY(bmp_readint(f, 4, &bmpinfo.RedMask));
499 TRY(bmp_readint(f, 4, &bmpinfo.GreenMask));
500 TRY(bmp_readint(f, 4, &bmpinfo.BlueMask));
501 TRY(bmp_readint(f, 4, &bmpinfo.AlphaMask));
502 }
503 if (bmpinfo.w > 0x7fffffff) {
504 goto format_error;
505 }
506 if (bmpinfo.h > 0x7fffffff) {
507 bmpinfo.h = (-bmpinfo.h) & 0xffffffff;
508 bmpinfo.topdown = 1;
509 } else {
510 bmpinfo.topdown = 0;
511 }
512 if (bmpinfo.h > 0x7fffffff) {
513 goto format_error;
514 }
515 } else if (bmpinfo.InfoSize == 12) {
516 /* old OS/2 format */
517 bmpinfo.ctbits = 24; /* sample size in color table */
518 TRY(bmp_readint(f, 2, &bmpinfo.w));
519 TRY(bmp_readint(f, 2, &bmpinfo.h));
520 TRY(bmp_readint(f, 2, &bmpinfo.Planes));
521 TRY(bmp_readint(f, 2, &bmpinfo.bits));
522 bmpinfo.comp = 0;
523 bmpinfo.ncolors = 0;
524 bmpinfo.topdown = 0;
525 } else {
526 goto format_error;
527 }
528
529 if (bmpinfo.comp == 3 && bmpinfo.InfoSize < 108) {
530 /* bitfield feature is only understood with V4 and V5 format */
531 goto format_error;
532 }
533
534 if (bmpinfo.comp > 3 || bmpinfo.bits > 32) {
535 goto format_error;
536 }
537
538 /* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
539 TRY(bmp_forward(f, 14+bmpinfo.InfoSize));
540
541 if (bmpinfo.Planes != 1) {
542 bm_read_error = "cannot handle bmp planes";
543 goto format_error; /* can't handle planes */
544 }
545
546 if (bmpinfo.ncolors == 0 && bmpinfo.bits <= 8) {
547 bmpinfo.ncolors = 1 << bmpinfo.bits;
548 }
549
550 /* color table, present only if bmpinfo.bits <= 8. */
551 if (bmpinfo.bits <= 8) {
552 coltable = (int *) calloc(bmpinfo.ncolors, sizeof(int));
553 if (!coltable) {
554 goto std_error;
555 }
556 /* NOTE: since we are reading a bitmap, we can immediately convert
557 the color table entries to bits. */
558 for (i=0; i<bmpinfo.ncolors; i++) {
559 TRY(bmp_readint(f, bmpinfo.ctbits/8, &c));
560 c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
561 coltable[i] = (c > 3 * threshold * 255 ? 0 : 1);
562 if (i<2) {
563 col1[i] = c;
564 }
565 }
566 }
567
568 /* forward to data */
569 if (bmpinfo.InfoSize != 12) { /* not old OS/2 format */
570 TRY(bmp_forward(f, bmpinfo.DataOffset));
571 }
572
573 /* allocate bitmap */
574 bm = bm_new(bmpinfo.w, bmpinfo.h);
575 if (!bm) {
576 goto std_error;
577 }
578
579 realheight = 0;
580
581 switch (bmpinfo.bits + 0x100*bmpinfo.comp) {
582
583 default:
584 goto format_error;
585 break;
586
587 case 0x001: /* monochrome palette */
588 if (col1[0] < col1[1]) { /* make the darker color black */
589 mask = 0xff;
590 } else {
591 mask = 0;
592 }
593
594 /* raster data */
595 for (y=0; y<bmpinfo.h; y++) {
596 realheight = y+1;
597 bmp_pad_reset();
598 for (i=0; 8*i<bmpinfo.w; i++) {
599 TRY_EOF(bmp_readint(f, 1, &b));
600 b ^= mask;
601 *bm_index(bm, i*8, y) |= ((potrace_word)b) << (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)));
602 }
603 TRY(bmp_pad(f));
604 }
605 break;
606
607 case 0x002: /* 2-bit to 8-bit palettes */
608 case 0x003:
609 case 0x004:
610 case 0x005:
611 case 0x006:
612 case 0x007:
613 case 0x008:
614 for (y=0; y<bmpinfo.h; y++) {
615 realheight = y+1;
616 bmp_pad_reset();
617 bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
618 n = 0; /* number of bits currently in bitbuffer */
619 for (x=0; x<bmpinfo.w; x++) {
620 if (n < bmpinfo.bits) {
621 TRY_EOF(bmp_readint(f, 1, &b));
622 bitbuf |= b << (INTBITS - 8 - n);
623 n += 8;
624 }
625 b = bitbuf >> (INTBITS - bmpinfo.bits);
626 bitbuf <<= bmpinfo.bits;
627 n -= bmpinfo.bits;
628 BM_UPUT(bm, x, y, COLTABLE(b));
629 }
630 TRY(bmp_pad(f));
631 }
632 break;
633
634 case 0x010: /* 16-bit encoding */
635 /* can't do this format because it is not well-documented and I
636 don't have any samples */
637 bm_read_error = "cannot handle bmp 16-bit coding";
638 goto format_error;
639 break;
640
641 case 0x018: /* 24-bit encoding */
642 case 0x020: /* 32-bit encoding */
643 for (y=0; y<bmpinfo.h; y++) {
644 realheight = y+1;
645 bmp_pad_reset();
646 for (x=0; x<bmpinfo.w; x++) {
647 TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
648 c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
649 BM_UPUT(bm, x, y, c > 3 * threshold * 255 ? 0 : 1);
650 }
651 TRY(bmp_pad(f));
652 }
653 break;
654
655 case 0x320: /* 32-bit encoding with bitfields */
656 if (bmpinfo.RedMask == 0 || bmpinfo.GreenMask == 0 || bmpinfo.BlueMask == 0) {
657 goto format_error;
658 }
659
660 redshift = lobit(bmpinfo.RedMask);
661 greenshift = lobit(bmpinfo.GreenMask);
662 blueshift = lobit(bmpinfo.BlueMask);
663
664 for (y=0; y<bmpinfo.h; y++) {
665 realheight = y+1;
666 bmp_pad_reset();
667 for (x=0; x<bmpinfo.w; x++) {
668 TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
669 c = ((c & bmpinfo.RedMask) >> redshift) + ((c & bmpinfo.GreenMask) >> greenshift) + ((c & bmpinfo.BlueMask) >> blueshift);
670 BM_UPUT(bm, x, y, c > 3 * threshold * 255 ? 0 : 1);
671 }
672 TRY(bmp_pad(f));
673 }
674 break;
675
676 case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
677 x = 0;
678 y = 0;
679
680 while (1) {
681 TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
682 TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
683 if (b>0) {
684 /* repeat count */
685 col[0] = COLTABLE((c>>4) & 0xf);
686 col[1] = COLTABLE(c & 0xf);
687 for (i=0; i<b && x<bmpinfo.w; i++) {
688 if (x>=bmpinfo.w) {
689 x=0;
690 y++;
691 }
692 if (y>=bmpinfo.h) {
693 break;
694 }
695 realheight = y+1;
696 BM_UPUT(bm, x, y, col[i&1]);
697 x++;
698 }
699 } else if (c == 0) {
700 /* end of line */
701 y++;
702 x = 0;
703 } else if (c == 1) {
704 /* end of bitmap */
705 break;
706 } else if (c == 2) {
707 /* "delta": skip pixels in x and y directions */
708 TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
709 TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
710 x += b;
711 y += c;
712 } else {
713 /* verbatim segment */
714 for (i=0; i<c; i++) {
715 if ((i&1)==0) {
716 TRY_EOF(bmp_readint(f, 1, &b));
717 }
718 if (x>=bmpinfo.w) {
719 x=0;
720 y++;
721 }
722 if (y>=bmpinfo.h) {
723 break;
724 }
725 realheight = y+1;
726 BM_PUT(bm, x, y, COLTABLE((b>>(4-4*(i&1))) & 0xf));
727 x++;
728 }
729 if ((c+1) & 2) {
730 /* pad to 16-bit boundary */
731 TRY_EOF(bmp_readint(f, 1, &b));
732 }
733 }
734 }
735 break;
736
737 case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
738 x = 0;
739 y = 0;
740 while (1) {
741 TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
742 TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
743 if (b>0) {
744 /* repeat count */
745 for (i=0; i<b; i++) {
746 if (x>=bmpinfo.w) {
747 x=0;
748 y++;
749 }
750 if (y>=bmpinfo.h) {
751 break;
752 }
753 realheight = y+1;
754 BM_UPUT(bm, x, y, COLTABLE(c));
755 x++;
756 }
757 } else if (c == 0) {
758 /* end of line */
759 y++;
760 x = 0;
761 } else if (c == 1) {
762 /* end of bitmap */
763 break;
764 } else if (c == 2) {
765 /* "delta": skip pixels in x and y directions */
766 TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
767 TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
768 x += b;
769 y += c;
770 } else {
771 /* verbatim segment */
772 for (i=0; i<c; i++) {
773 TRY_EOF(bmp_readint(f, 1, &b));
774 if (x>=bmpinfo.w) {
775 x=0;
776 y++;
777 }
778 if (y>=bmpinfo.h) {
779 break;
780 }
781 realheight = y+1;
782 BM_PUT(bm, x, y, COLTABLE(b));
783 x++;
784 }
785 if (c & 1) {
786 /* pad input to 16-bit boundary */
787 TRY_EOF(bmp_readint(f, 1, &b));
788 }
789 }
790 }
791 break;
792
793 } /* switch */
794
795 /* skip any potential junk after the data section, but don't
796 complain in case EOF is encountered */
797 bmp_forward(f, bmpinfo.FileSize);
798
799 free(coltable);
800 if (bmpinfo.topdown) {
801 bm_flip(bm);
802 }
803 *bmp = bm;
804 return 0;
805
806 eof:
807 TRY_STD(bm_resize(bm, realheight));
808 free(coltable);
809 if (bmpinfo.topdown) {
810 bm_flip(bm);
811 }
812 *bmp = bm;
813 return 1;
814
815 format_error:
816 try_error:
817 free(coltable);
818 bm_free(bm);
819 if (!bm_read_error) {
820 bm_read_error = "invalid bmp file";
821 }
822 return -2;
823
824 std_error:
825 free(coltable);
826 bm_free(bm);
827 return -1;
828 }
829
830 /* ---------------------------------------------------------------------- */
831 /* output pbm format */
832
bm_writepbm(FILE * f,potrace_bitmap_t * bm)833 void bm_writepbm(FILE *f, potrace_bitmap_t *bm) {
834 int w, h, bpr, y, i, c;
835
836 w = bm->w;
837 h = bm->h;
838
839 bpr = (w+7)/8;
840
841 fprintf(f, "P4\n%d %d\n", w, h);
842 for (y=h-1; y>=0; y--) {
843 for (i=0; i<bpr; i++) {
844 c = (*bm_index(bm, i*8, y) >> (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)))) & 0xff;
845 fputc(c, f);
846 }
847 }
848 return;
849 }
850
851 /* ---------------------------------------------------------------------- */
852 /* output - for primitive debugging purposes only! */
853
854 /* print bitmap to screen */
bm_print(FILE * f,potrace_bitmap_t * bm)855 int bm_print(FILE *f, potrace_bitmap_t *bm) {
856 int x, y;
857 int xx, yy;
858 int d;
859 int sw, sh;
860
861 sw = bm->w < 79 ? bm->w : 79;
862 sh = bm->w < 79 ? bm->h : bm->h*sw*44/(79*bm->w);
863
864 for (yy=sh-1; yy>=0; yy--) {
865 for (xx=0; xx<sw; xx++) {
866 d=0;
867 for (x=xx*bm->w/sw; x<(xx+1)*bm->w/sw; x++) {
868 for (y=yy*bm->h/sh; y<(yy+1)*bm->h/sh; y++) {
869 if (BM_GET(bm, x, y)) {
870 d++;
871 }
872 }
873 }
874 fputc(d ? '*' : ' ', f);
875 }
876 fputc('\n', f);
877 }
878 return 0;
879 }
880
881