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