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 "bitmap_io.h"
16 #include "bitops.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 ) \
24 if( x ) \
25 goto try_error
26 #define TRY_EOF( x ) \
27 if( x ) \
28 goto eof
29 #define TRY_STD( x ) \
30 if( x ) \
31 goto std_error
32
33 /* ---------------------------------------------------------------------- */
34 /* routines for reading pnm streams */
35
36 /* read next character after whitespace and comments. Return EOF on
37 * end of file or error. */
fgetc_ws(FILE * f)38 static int fgetc_ws( FILE* f )
39 {
40 int c;
41
42 while( 1 )
43 {
44 c = fgetc( f );
45
46 if( c == '#' )
47 {
48 while( 1 )
49 {
50 c = fgetc( f );
51
52 if( c == '\n' || c == EOF )
53 {
54 break;
55 }
56 }
57 }
58
59 /* space, tab, line feed, carriage return, form-feed */
60 if( c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != 12 )
61 {
62 return c;
63 }
64 }
65 }
66
67
68 /* skip whitespace and comments, then read a non-negative decimal
69 * number from a stream. Return -1 on EOF. Tolerate other errors (skip
70 * bad characters). Do not the read any characters following the
71 * number (put next character back into the stream) */
72
readnum(FILE * f)73 static int readnum( FILE* f )
74 {
75 int c;
76 int acc;
77
78 /* skip whitespace and comments */
79 while( 1 )
80 {
81 c = fgetc_ws( f );
82
83 if( c == EOF )
84 {
85 return -1;
86 }
87
88 if( c >= '0' && c <= '9' )
89 {
90 break;
91 }
92 }
93
94 /* first digit is already in c */
95 acc = c - '0';
96
97 while( 1 )
98 {
99 c = fgetc( f );
100
101 if( c == EOF )
102 {
103 break;
104 }
105
106 if( c < '0' || c > '9' )
107 {
108 ungetc( c, f );
109 break;
110 }
111
112 acc *= 10;
113 acc += c - '0';
114 }
115
116 return acc;
117 }
118
119
120 /* similar to readnum, but read only a single 0 or 1, and do not read
121 * any characters after it. */
122
readbit(FILE * f)123 static int readbit( FILE* f )
124 {
125 int c;
126
127 /* skip whitespace and comments */
128 while( 1 )
129 {
130 c = fgetc_ws( f );
131
132 if( c == EOF )
133 {
134 return -1;
135 }
136
137 if( c >= '0' && c <= '1' )
138 {
139 break;
140 }
141 }
142
143 return c - '0';
144 }
145
146
147 /* ---------------------------------------------------------------------- */
148
149 /* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and
150 * convert the output to a bitmap. Return bitmap in *bmp. Return 0 on
151 * success, -1 on error with errno set, -2 on bad file format (with
152 * error message in bm_read_error), and 1 on premature end of file, -3
153 * on empty file (including files which contain only whitespace and
154 * comments), -4 if wrong magic number. If the return value is >=0,
155 * bmp is valid. */
156
157 const char* bm_read_error = NULL;
158
bm_read(FILE * f,double threshold,potrace_bitmap_t ** bmp)159 int bm_read( FILE* f, double threshold, potrace_bitmap_t** bmp )
160 {
161 int magic[2];
162
163 /* read magic number. We ignore whitespace and comments before the
164 * magic, for the benefit of concatenated files in P1-P3 format.
165 * Multiple P1-P3 images in a single file are not formally allowed
166 * by the PNM standard, but there is no harm in being lenient. */
167
168 magic[0] = fgetc_ws( f );
169
170 if( magic[0] == EOF )
171 {
172 return -3;
173 }
174
175 magic[1] = fgetc( f );
176
177 if( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' )
178 {
179 return bm_readbody_pnm( f, threshold, bmp, magic[1] );
180 }
181
182 if( magic[0] == 'B' && magic[1] == 'M' )
183 {
184 return bm_readbody_bmp( f, threshold, bmp );
185 }
186
187 return -4;
188 }
189
190
191 /* ---------------------------------------------------------------------- */
192 /* read PNM format */
193
194 /* 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)195 static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, int magic )
196 {
197 potrace_bitmap_t* bm;
198 int x, y, i, b, b1, sum;
199 int bpr; /* bytes per row (as opposed to 4*bm->c) */
200 int w, h, max;
201 int realheight; /* in case of incomplete file, keeps track of how
202 * many scan lines actually contain data */
203
204 bm = NULL;
205
206 w = readnum( f );
207
208 if( w < 0 )
209 {
210 goto format_error;
211 }
212
213 h = readnum( f );
214
215 if( h < 0 )
216 {
217 goto format_error;
218 }
219
220 /* allocate bitmap */
221 bm = bm_new( w, h );
222
223 if( !bm )
224 {
225 goto std_error;
226 }
227
228 realheight = 0;
229
230 switch( magic )
231 {
232 default:
233 /* not reached */
234 goto format_error;
235
236 case '1':
237 /* read P1 format: PBM ascii */
238
239 for( y = 0; y < h; y++ )
240 {
241 realheight = y + 1;
242
243 for( x = 0; x < w; x++ )
244 {
245 b = readbit( f );
246
247 if( b < 0 )
248 {
249 goto eof;
250 }
251
252 BM_UPUT( bm, x, y, b );
253 }
254 }
255
256 break;
257
258 case '2':
259 /* read P2 format: PGM ascii */
260
261 max = readnum( f );
262
263 if( max < 1 )
264 {
265 goto format_error;
266 }
267
268 for( y = 0; y < h; y++ )
269 {
270 realheight = y + 1;
271
272 for( x = 0; x < w; x++ )
273 {
274 b = readnum( f );
275
276 if( b < 0 )
277 {
278 goto eof;
279 }
280
281 BM_UPUT( bm, x, y, b > threshold * max ? 0 : 1 );
282 }
283 }
284
285 break;
286
287 case '3':
288 /* read P3 format: PPM ascii */
289
290 max = readnum( f );
291
292 if( max < 1 )
293 {
294 goto format_error;
295 }
296
297 for( y = 0; y < h; y++ )
298 {
299 realheight = y + 1;
300
301 for( x = 0; x < w; x++ )
302 {
303 sum = 0;
304
305 for( i = 0; i < 3; i++ )
306 {
307 b = readnum( f );
308
309 if( b < 0 )
310 {
311 goto eof;
312 }
313
314 sum += b;
315 }
316
317 BM_UPUT( bm, x, y, sum > 3 * threshold * max ? 0 : 1 );
318 }
319 }
320
321 break;
322
323 case '4':
324 /* read P4 format: PBM raw */
325
326 b = fgetc( f ); /* read single white-space character after height */
327
328 if( b == EOF )
329 {
330 goto format_error;
331 }
332
333 bpr = ( w + 7 ) / 8;
334
335 for( y = 0; y < h; y++ )
336 {
337 realheight = y + 1;
338
339 for( i = 0; i < bpr; i++ )
340 {
341 b = fgetc( f );
342
343 if( b == EOF )
344 {
345 goto eof;
346 }
347
348 *bm_index( bm, i * 8, y ) |= ( (potrace_word) b )
349 << ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) );
350 }
351 }
352
353 break;
354
355 case '5':
356 /* read P5 format: PGM raw */
357
358 max = readnum( f );
359
360 if( max < 1 )
361 {
362 goto format_error;
363 }
364
365 b = fgetc( f ); /* read single white-space character after max */
366
367 if( b == EOF )
368 {
369 goto format_error;
370 }
371
372 for( y = 0; y < h; y++ )
373 {
374 realheight = y + 1;
375
376 for( x = 0; x < w; x++ )
377 {
378 b = fgetc( f );
379
380 if( b == EOF )
381 goto eof;
382
383 if( max >= 256 )
384 {
385 b <<= 8;
386 b1 = fgetc( f );
387
388 if( b1 == EOF )
389 goto eof;
390
391 b |= b1;
392 }
393
394 BM_UPUT( bm, x, y, b > threshold * max ? 0 : 1 );
395 }
396 }
397
398 break;
399
400 case '6':
401 /* read P6 format: PPM raw */
402
403 max = readnum( f );
404
405 if( max < 1 )
406 {
407 goto format_error;
408 }
409
410 b = fgetc( f ); /* read single white-space character after max */
411
412 if( b == EOF )
413 {
414 goto format_error;
415 }
416
417 for( y = 0; y < h; y++ )
418 {
419 realheight = y + 1;
420
421 for( x = 0; x < w; x++ )
422 {
423 sum = 0;
424
425 for( i = 0; i < 3; i++ )
426 {
427 b = fgetc( f );
428
429 if( b == EOF )
430 {
431 goto eof;
432 }
433
434 if( max >= 256 )
435 {
436 b <<= 8;
437 b1 = fgetc( f );
438
439 if( b1 == EOF )
440 goto eof;
441
442 b |= b1;
443 }
444
445 sum += b;
446 }
447
448 BM_UPUT( bm, x, y, sum > 3 * threshold * max ? 0 : 1 );
449 }
450 }
451
452 break;
453 }
454
455 bm_flip( bm );
456 *bmp = bm;
457 return 0;
458
459 eof:
460 TRY_STD( bm_resize( bm, realheight ) );
461 bm_flip( bm );
462 *bmp = bm;
463 return 1;
464
465 format_error:
466 bm_free( bm );
467
468 if( magic == '1' || magic == '4' )
469 {
470 bm_read_error = "invalid pbm file";
471 }
472 else if( magic == '2' || magic == '5' )
473 {
474 bm_read_error = "invalid pgm file";
475 }
476 else
477 {
478 bm_read_error = "invalid ppm file";
479 }
480
481 return -2;
482
483 std_error:
484 bm_free( bm );
485 return -1;
486 }
487
488
489 /* ---------------------------------------------------------------------- */
490 /* read BMP format */
491
492 struct bmp_info_s
493 {
494 unsigned int FileSize;
495 unsigned int reserved;
496 unsigned int DataOffset;
497 unsigned int InfoSize;
498 unsigned int w; /* width */
499 unsigned int h; /* height */
500 unsigned int Planes;
501 unsigned int bits; /* bits per sample */
502 unsigned int comp; /* compression mode */
503 unsigned int ImageSize;
504 unsigned int XpixelsPerM;
505 unsigned int YpixelsPerM;
506 unsigned int ncolors; /* number of colors in palette */
507 unsigned int ColorsImportant;
508 unsigned int RedMask;
509 unsigned int GreenMask;
510 unsigned int BlueMask;
511 unsigned int AlphaMask;
512 unsigned int ctbits; /* sample size for color table */
513 int topdown; /* top-down mode? */
514 };
515 typedef struct bmp_info_s bmp_info_t;
516
517 /* auxiliary */
518
519 static int bmp_count = 0; /* counter for byte padding */
520 static int bmp_pos = 0; /* counter from start of BMP data */
521
522 /* read n-byte little-endian integer. Return 1 on EOF or error, else
523 * 0. Assume n<=4. */
bmp_readint(FILE * f,int n,unsigned int * p)524 static int bmp_readint( FILE* f, int n, unsigned int* p )
525 {
526 int i;
527 unsigned int sum = 0;
528 int b;
529
530 for( i = 0; i < n; i++ )
531 {
532 b = fgetc( f );
533
534 if( b == EOF )
535 {
536 return 1;
537 }
538
539 sum += (unsigned) b << ( 8 * i );
540 }
541
542 bmp_count += n;
543 bmp_pos += n;
544 *p = sum;
545 return 0;
546 }
547
548
549 /* reset padding boundary */
bmp_pad_reset(void)550 static void bmp_pad_reset( void )
551 {
552 bmp_count = 0;
553 }
554
555
556 /* read padding bytes to 4-byte boundary. Return 1 on EOF or error,
557 * else 0. */
bmp_pad(FILE * f)558 static int bmp_pad( FILE* f )
559 {
560 int c, i, b;
561
562 c = ( -bmp_count ) & 3;
563
564 for( i = 0; i < c; i++ )
565 {
566 b = fgetc( f );
567
568 if( b == EOF )
569 {
570 return 1;
571 }
572 }
573
574 bmp_pos += c;
575 bmp_count = 0;
576 return 0;
577 }
578
579
580 /* forward to the new file position. Return 1 on EOF or error, else 0 */
bmp_forward(FILE * f,int pos)581 static int bmp_forward( FILE* f, int pos )
582 {
583 int b;
584
585 while( bmp_pos < pos )
586 {
587 b = fgetc( f );
588
589 if( b == EOF )
590 {
591 return 1;
592 }
593
594 bmp_pos++;
595 bmp_count++;
596 }
597
598 return 0;
599 }
600
601
602 /* safe colortable access */
603 #define COLTABLE( c ) ( ( c ) < bmpinfo.ncolors ? coltable[( c )] : 0 )
604
605 /* read BMP stream after magic number. Return values as for bm_read.
606 * We choose to be as permissive as possible, since there are many
607 * programs out there which produce BMP. For instance, ppmtobmp can
608 * produce codings with anywhere from 1-8 or 24 bits per sample,
609 * although most specifications only allow 1,4,8,24,32. We can also
610 * read both the old and new OS/2 BMP formats in addition to the
611 * Windows BMP format. */
bm_readbody_bmp(FILE * f,double threshold,potrace_bitmap_t ** bmp)612 static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
613 {
614 bmp_info_t bmpinfo;
615 int* coltable;
616 unsigned int b, c;
617 unsigned int i;
618 potrace_bitmap_t* bm;
619 int mask;
620 unsigned int x, y;
621 int col[2];
622 unsigned int bitbuf;
623 unsigned int n;
624 unsigned int redshift, greenshift, blueshift;
625 int col1[2];
626 int realheight; /* in case of incomplete file, keeps track of how
627 * many scan lines actually contain data */
628
629 bm_read_error = NULL;
630 bm = NULL;
631 coltable = NULL;
632
633 bmp_pos = 2; /* set file position */
634
635 /* file header (minus magic number) */
636 TRY( bmp_readint( f, 4, &bmpinfo.FileSize ) );
637 TRY( bmp_readint( f, 4, &bmpinfo.reserved ) );
638 TRY( bmp_readint( f, 4, &bmpinfo.DataOffset ) );
639
640 /* info header */
641 TRY( bmp_readint( f, 4, &bmpinfo.InfoSize ) );
642
643 if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64 || bmpinfo.InfoSize == 108
644 || bmpinfo.InfoSize == 124 )
645 {
646 /* Windows or new OS/2 format */
647 bmpinfo.ctbits = 32; /* sample size in color table */
648 TRY( bmp_readint( f, 4, &bmpinfo.w ) );
649 TRY( bmp_readint( f, 4, &bmpinfo.h ) );
650 TRY( bmp_readint( f, 2, &bmpinfo.Planes ) );
651 TRY( bmp_readint( f, 2, &bmpinfo.bits ) );
652 TRY( bmp_readint( f, 4, &bmpinfo.comp ) );
653 TRY( bmp_readint( f, 4, &bmpinfo.ImageSize ) );
654 TRY( bmp_readint( f, 4, &bmpinfo.XpixelsPerM ) );
655 TRY( bmp_readint( f, 4, &bmpinfo.YpixelsPerM ) );
656 TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
657 TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
658
659 if( bmpinfo.InfoSize >= 108 )
660 {
661 /* V4 and V5 bitmaps */
662 TRY( bmp_readint( f, 4, &bmpinfo.RedMask ) );
663 TRY( bmp_readint( f, 4, &bmpinfo.GreenMask ) );
664 TRY( bmp_readint( f, 4, &bmpinfo.BlueMask ) );
665 TRY( bmp_readint( f, 4, &bmpinfo.AlphaMask ) );
666 }
667
668 if( bmpinfo.w > 0x7fffffff )
669 {
670 goto format_error;
671 }
672
673 if( bmpinfo.h > 0x7fffffff )
674 {
675 bmpinfo.h = ( -bmpinfo.h ) & 0xffffffff;
676 bmpinfo.topdown = 1;
677 }
678 else
679 {
680 bmpinfo.topdown = 0;
681 }
682
683 if( bmpinfo.h > 0x7fffffff )
684 {
685 goto format_error;
686 }
687 }
688 else if( bmpinfo.InfoSize == 12 )
689 {
690 /* old OS/2 format */
691 bmpinfo.ctbits = 24; /* sample size in color table */
692 TRY( bmp_readint( f, 2, &bmpinfo.w ) );
693 TRY( bmp_readint( f, 2, &bmpinfo.h ) );
694 TRY( bmp_readint( f, 2, &bmpinfo.Planes ) );
695 TRY( bmp_readint( f, 2, &bmpinfo.bits ) );
696 bmpinfo.comp = 0;
697 bmpinfo.ncolors = 0;
698 bmpinfo.topdown = 0;
699 }
700 else
701 {
702 goto format_error;
703 }
704
705 if( bmpinfo.comp == 3 && bmpinfo.InfoSize < 108 )
706 {
707 /* bitfield feature is only understood with V4 and V5 format */
708 goto format_error;
709 }
710
711 if( bmpinfo.comp > 3 || bmpinfo.bits > 32 )
712 {
713 goto format_error;
714 }
715
716 /* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
717 TRY( bmp_forward( f, 14 + bmpinfo.InfoSize ) );
718
719 if( bmpinfo.Planes != 1 )
720 {
721 bm_read_error = "cannot handle bmp planes";
722 goto format_error; /* can't handle planes */
723 }
724
725 if( bmpinfo.ncolors == 0 && bmpinfo.bits <= 8 )
726 {
727 bmpinfo.ncolors = 1 << bmpinfo.bits;
728 }
729
730 /* color table, present only if bmpinfo.bits <= 8. */
731 if( bmpinfo.bits <= 8 )
732 {
733 coltable = (int*) calloc( bmpinfo.ncolors, sizeof( int ) );
734
735 if( !coltable )
736 {
737 goto std_error;
738 }
739
740 /* NOTE: since we are reading a bitmap, we can immediately convert
741 * the color table entries to bits. */
742 for( i = 0; i < bmpinfo.ncolors; i++ )
743 {
744 TRY( bmp_readint( f, bmpinfo.ctbits / 8, &c ) );
745 c = ( ( c >> 16 ) & 0xff ) + ( ( c >> 8 ) & 0xff ) + ( c & 0xff );
746 coltable[i] = ( c > 3 * threshold * 255 ? 0 : 1 );
747
748 if( i < 2 )
749 {
750 col1[i] = c;
751 }
752 }
753 }
754
755 /* forward to data */
756 if( bmpinfo.InfoSize != 12 )
757 {
758 /* not old OS/2 format */
759 TRY( bmp_forward( f, bmpinfo.DataOffset ) );
760 }
761
762 /* allocate bitmap */
763 bm = bm_new( bmpinfo.w, bmpinfo.h );
764
765 if( !bm )
766 {
767 goto std_error;
768 }
769
770 realheight = 0;
771
772 switch( bmpinfo.bits + 0x100 * bmpinfo.comp )
773 {
774 default:
775 goto format_error; break;
776
777 case 0x001: /* monochrome palette */
778
779 if( col1[0] < col1[1] )
780 {
781 /* make the darker color black */
782 mask = 0xff;
783 }
784 else
785 {
786 mask = 0;
787 }
788
789 /* raster data */
790 for( y = 0; y < bmpinfo.h; y++ )
791 {
792 realheight = y + 1;
793 bmp_pad_reset();
794
795 for( i = 0; 8 * i < bmpinfo.w; i++ )
796 {
797 TRY_EOF( bmp_readint( f, 1, &b ) );
798 b ^= mask;
799 *bm_index( bm, i * 8, y ) |= ( (potrace_word) b )
800 << ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) );
801 }
802
803 TRY( bmp_pad( f ) );
804 }
805
806 break;
807
808 case 0x002: /* 2-bit to 8-bit palettes */
809 case 0x003:
810 case 0x004:
811 case 0x005:
812 case 0x006:
813 case 0x007:
814 case 0x008:
815
816 for( y = 0; y < bmpinfo.h; y++ )
817 {
818 realheight = y + 1;
819 bmp_pad_reset();
820 bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
821 n = 0; /* number of bits currently in bitbuffer */
822
823 for( x = 0; x < bmpinfo.w; x++ )
824 {
825 if( n < bmpinfo.bits )
826 {
827 TRY_EOF( bmp_readint( f, 1, &b ) );
828 bitbuf |= b << ( INTBITS - 8 - n );
829 n += 8;
830 }
831
832 b = bitbuf >> ( INTBITS - bmpinfo.bits );
833 bitbuf <<= bmpinfo.bits;
834 n -= bmpinfo.bits;
835 BM_UPUT( bm, x, y, COLTABLE( b ) );
836 }
837
838 TRY( bmp_pad( f ) );
839 }
840
841 break;
842
843 case 0x010: /* 16-bit encoding */
844 /* can't do this format because it is not well-documented and I
845 * don't have any samples */
846 bm_read_error = "cannot handle bmp 16-bit coding";
847 goto format_error;
848 break;
849
850 case 0x018: /* 24-bit encoding */
851 case 0x020: /* 32-bit encoding */
852
853 for( y = 0; y < bmpinfo.h; y++ )
854 {
855 realheight = y + 1;
856 bmp_pad_reset();
857
858 for( x = 0; x < bmpinfo.w; x++ )
859 {
860 TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
861 c = ( ( c >> 16 ) & 0xff ) + ( ( c >> 8 ) & 0xff ) + ( c & 0xff );
862 BM_UPUT( bm, x, y, c > 3 * threshold * 255 ? 0 : 1 );
863 }
864
865 TRY( bmp_pad( f ) );
866 }
867
868 break;
869
870 case 0x320: /* 32-bit encoding with bitfields */
871
872 if( bmpinfo.RedMask == 0 || bmpinfo.GreenMask == 0 || bmpinfo.BlueMask == 0 )
873 {
874 goto format_error;
875 }
876
877 redshift = lobit( bmpinfo.RedMask );
878 greenshift = lobit( bmpinfo.GreenMask );
879 blueshift = lobit( bmpinfo.BlueMask );
880
881 for( y = 0; y < bmpinfo.h; y++ )
882 {
883 realheight = y + 1;
884 bmp_pad_reset();
885
886 for( x = 0; x < bmpinfo.w; x++ )
887 {
888 TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
889 c = ( ( c & bmpinfo.RedMask ) >> redshift )
890 + ( ( c & bmpinfo.GreenMask ) >> greenshift )
891 + ( ( c & bmpinfo.BlueMask ) >> blueshift );
892 BM_UPUT( bm, x, y, c > 3 * threshold * 255 ? 0 : 1 );
893 }
894
895 TRY( bmp_pad( f ) );
896 }
897
898 break;
899
900 case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
901 x = 0;
902 y = 0;
903
904 while( 1 )
905 {
906 TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
907 TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
908
909 if( b > 0 )
910 {
911 /* repeat count */
912 col[0] = COLTABLE( ( c >> 4 ) & 0xf );
913 col[1] = COLTABLE( c & 0xf );
914
915 for( i = 0; i < b && x < bmpinfo.w; i++ )
916 {
917 if( x >= bmpinfo.w )
918 {
919 x = 0;
920 y++;
921 }
922
923 if( x >= bmpinfo.w || y >= bmpinfo.h )
924 {
925 break;
926 }
927
928 realheight = y + 1;
929 BM_PUT( bm, x, y, col[i & 1] );
930 x++;
931 }
932 }
933 else if( c == 0 )
934 {
935 /* end of line */
936 y++;
937 x = 0;
938 }
939 else if( c == 1 )
940 {
941 /* end of bitmap */
942 break;
943 }
944 else if( c == 2 )
945 {
946 /* "delta": skip pixels in x and y directions */
947 TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
948 TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
949 x += b;
950 y += c;
951 }
952 else
953 {
954 /* verbatim segment */
955 for( i = 0; i < c; i++ )
956 {
957 if( ( i & 1 ) == 0 )
958 {
959 TRY_EOF( bmp_readint( f, 1, &b ) );
960 }
961
962 if( x >= bmpinfo.w )
963 {
964 x = 0;
965 y++;
966 }
967
968 if( x >= bmpinfo.w || y >= bmpinfo.h )
969 {
970 break;
971 }
972
973 realheight = y + 1;
974 BM_PUT( bm, x, y, COLTABLE( ( b >> ( 4 - 4 * ( i & 1 ) ) ) & 0xf ) );
975 x++;
976 }
977
978 if( ( c + 1 ) & 2 )
979 {
980 /* pad to 16-bit boundary */
981 TRY_EOF( bmp_readint( f, 1, &b ) );
982 }
983 }
984 }
985
986 break;
987
988 case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
989 x = 0;
990 y = 0;
991
992 while( 1 )
993 {
994 TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
995 TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
996
997 if( b > 0 )
998 {
999 /* repeat count */
1000 for( i = 0; i < b; i++ )
1001 {
1002 if( x >= bmpinfo.w )
1003 {
1004 x = 0;
1005 y++;
1006 }
1007
1008 if( x >= bmpinfo.w || y >= bmpinfo.h )
1009 {
1010 break;
1011 }
1012
1013 realheight = y + 1;
1014 BM_PUT( bm, x, y, COLTABLE( c ) );
1015 x++;
1016 }
1017 }
1018 else if( c == 0 )
1019 {
1020 /* end of line */
1021 y++;
1022 x = 0;
1023 }
1024 else if( c == 1 )
1025 {
1026 /* end of bitmap */
1027 break;
1028 }
1029 else if( c == 2 )
1030 {
1031 /* "delta": skip pixels in x and y directions */
1032 TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
1033 TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
1034 x += b;
1035 y += c;
1036 }
1037 else
1038 {
1039 /* verbatim segment */
1040 for( i = 0; i < c; i++ )
1041 {
1042 TRY_EOF( bmp_readint( f, 1, &b ) );
1043
1044 if( x >= bmpinfo.w )
1045 {
1046 x = 0;
1047 y++;
1048 }
1049
1050 if( x >= bmpinfo.w || y >= bmpinfo.h )
1051 {
1052 break;
1053 }
1054
1055 realheight = y + 1;
1056 BM_PUT( bm, x, y, COLTABLE( b ) );
1057 x++;
1058 }
1059
1060 if( c & 1 )
1061 {
1062 /* pad input to 16-bit boundary */
1063 TRY_EOF( bmp_readint( f, 1, &b ) );
1064 }
1065 }
1066 }
1067
1068 break;
1069 } /* switch */
1070
1071 /* skip any potential junk after the data section, but don't
1072 * complain in case EOF is encountered */
1073 bmp_forward( f, bmpinfo.FileSize );
1074
1075 free( coltable );
1076
1077 if( bmpinfo.topdown )
1078 {
1079 bm_flip( bm );
1080 }
1081
1082 *bmp = bm;
1083 return 0;
1084
1085 eof:
1086 TRY_STD( bm_resize( bm, realheight ) );
1087 free( coltable );
1088
1089 if( bmpinfo.topdown )
1090 {
1091 bm_flip( bm );
1092 }
1093
1094 *bmp = bm;
1095 return 1;
1096
1097 format_error:
1098 try_error:
1099 free( coltable );
1100 bm_free( bm );
1101
1102 if( !bm_read_error )
1103 {
1104 bm_read_error = "invalid bmp file";
1105 }
1106
1107 return -2;
1108
1109 std_error:
1110 free( coltable );
1111 bm_free( bm );
1112 return -1;
1113 }
1114
1115
1116 /* ---------------------------------------------------------------------- */
1117 /* output pbm format */
1118
bm_writepbm(FILE * f,potrace_bitmap_t * bm)1119 void bm_writepbm( FILE* f, potrace_bitmap_t* bm )
1120 {
1121 int w, h, bpr, y, i, c;
1122
1123 w = bm->w;
1124 h = bm->h;
1125
1126 bpr = ( w + 7 ) / 8;
1127
1128 fprintf( f, "P4\n%d %d\n", w, h );
1129
1130 for( y = h - 1; y >= 0; y-- )
1131 {
1132 for( i = 0; i < bpr; i++ )
1133 {
1134 c = ( *bm_index( bm, i * 8, y ) >> ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) ) )
1135 & 0xff;
1136 fputc( c, f );
1137 }
1138 }
1139 }
1140
1141
1142 /* ---------------------------------------------------------------------- */
1143 /* output - for primitive debugging purposes only! */
1144
1145 /* print bitmap to screen */
bm_print(FILE * f,potrace_bitmap_t * bm)1146 int bm_print( FILE* f, potrace_bitmap_t* bm )
1147 {
1148 int x, y;
1149 int xx, yy;
1150 int d;
1151 int sw, sh;
1152
1153 sw = bm->w < 79 ? bm->w : 79;
1154 sh = bm->w < 79 ? bm->h : bm->h * sw * 44 / ( 79 * bm->w );
1155
1156 for( yy = sh - 1; yy >= 0; yy-- )
1157 {
1158 for( xx = 0; xx < sw; xx++ )
1159 {
1160 d = 0;
1161
1162 for( x = xx * bm->w / sw; x < ( xx + 1 ) * bm->w / sw; x++ )
1163 {
1164 for( y = yy * bm->h / sh; y < ( yy + 1 ) * bm->h / sh; y++ )
1165 {
1166 if( BM_GET( bm, x, y ) )
1167 {
1168 d++;
1169 }
1170 }
1171 }
1172
1173 fputc( d ? '*' : ' ', f );
1174 }
1175
1176 fputc( '\n', f );
1177 }
1178
1179 return 0;
1180 }
1181