Statistics
| Revision:

gvsig-raster / libjni-potrace / trunk / libjni-potrace / src / main / native / jpotrace / bitmap_io.c @ 1780

History | View | Annotate | Download (16.9 KB)

1
/* Copyright (C) 2001-2007 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
/* $Id: bitmap_io.c 147 2007-04-09 00:44:09Z selinger $ */
6

    
7
/* Routines for manipulating bitmaps, including reading pbm files. */
8

    
9
#include <stdio.h>
10

    
11
#include "bitmap.h"
12

    
13
#define INTBITS (8*sizeof(int))
14

    
15
static int bm_readbody_bmp(FILE *f, double threshold, potrace_bitmap_t **bmp);
16
static int bm_readbody_pnm(FILE *f, double threshold, potrace_bitmap_t **bmp, int magic);
17

    
18
/* ---------------------------------------------------------------------- */
19
/* routines for reading pnm streams */
20

    
21
/* read next character after whitespace and comments. Return EOF on
22
 end of file or error. */
23
static int fgetc_ws(FILE *f) {
24
        int c;
25

    
26
        while (1) {
27
                c = fgetc(f);
28
                if (c == '#') {
29
                        while (1) {
30
                                c = fgetc(f);
31
                                if (c == '\n' || c == EOF) {
32
                                        break;
33
                                }
34
                        }
35
                }
36
                /* space, tab, line feed, carriage return, form-feed */
37
                if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != 12) {
38
                        return c;
39
                }
40
        }
41
}
42

    
43
/* skip whitespace and comments, then read a non-negative decimal
44
 number from a stream. Return -1 on EOF. Tolerate other errors (skip
45
 bad characters). Do not the read any characters following the
46
 number (put next character back into the stream) */
47

    
48
static int readnum(FILE *f) {
49
        int c;
50
        int acc;
51

    
52
        /* skip whitespace and comments */
53
        while (1) {
54
                c = fgetc_ws(f);
55
                if (c == EOF) {
56
                        return -1;
57
                }
58
                if (c >= '0' && c <= '9') {
59
                        break;
60
                }
61
        }
62

    
63
        /* first digit is already in c */
64
        acc = c - '0';
65
        while (1) {
66
                c = fgetc(f);
67
                if (c == EOF) {
68
                        break;
69
                }
70
                if (c < '0' || c > '9') {
71
                        ungetc(c, f);
72
                        break;
73
                }
74
                acc *= 10;
75
                acc += c - '0';
76
        }
77
        return acc;
78
}
79

    
80
/* similar to readnum, but read only a single 0 or 1, and do not read
81
 any characters after it. */
82

    
83
static int readbit(FILE *f) {
84
        int c;
85

    
86
        /* skip whitespace and comments */
87
        while (1) {
88
                c = fgetc_ws(f);
89
                if (c == EOF) {
90
                        return -1;
91
                }
92
                if (c >= '0' && c <= '1') {
93
                        break;
94
                }
95
        }
96

    
97
        return c - '0';
98
}
99

    
100
/* ---------------------------------------------------------------------- */
101

    
102
/* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and
103
 convert the output to a bitmap. Return bitmap in *bmp. Return 0 on
104
 success, -1 on error with errno set, -2 on bad file format (with
105
 error message in bm_read_error), and 1 on premature end of file, -3
106
 on empty file (including files which contain only whitespace and
107
 comments), -4 if wrong magic number. If the return value is >=0,
108
 *bmp is valid. */
109

    
110
char *bm_read_error = NULL;
111

    
112
int bm_read(FILE *f, double threshold, potrace_bitmap_t **bmp) {
113
        int magic[2];
114

    
115
        /* read magic number. We ignore whitespace and comments before the
116
         magic, for the benefit of concatenated files in P1-P3 format.
117
         Multiple P1-P3 images in a single file are not formally allowed
118
         by the PNM standard, but there is no harm in being lenient. */
119

    
120
        magic[0] = fgetc_ws(f);
121
        if (magic[0] == EOF) {
122
                return -3;
123
        }
124
        magic[1] = fgetc(f);
125
        if (magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6') {
126
                return bm_readbody_pnm(f, threshold, bmp, magic[1]);
127
        }
128
        if (magic[0] == 'B' && magic[1] == 'M') {
129
                return bm_readbody_bmp(f, threshold, bmp);
130
        }
131
        return -4;
132
}
133

    
134
/* ---------------------------------------------------------------------- */
135
/* read PNM format */
136

    
137
/* read PNM stream after magic number. Return values as for bm_read */
138
static int bm_readbody_pnm(FILE *f, double threshold, potrace_bitmap_t **bmp, int magic) {
139
        potrace_bitmap_t *bm;
140
        int x, y, i, b, b1, sum;
141
        int bpr; /* bytes per row (as opposed to 4*bm->c) */
142
        int w, h, max;
143

    
144
        bm = NULL;
145

    
146
        w = readnum(f);
147
        if (w < 0) {
148
                goto format_error;
149
        }
150

    
151
        h = readnum(f);
152
        if (h < 0) {
153
                goto format_error;
154
        }
155

    
156
        /* allocate bitmap */
157
        bm = bm_new(w, h);
158
        if (!bm) {
159
                return -1;
160
        }
161

    
162
        /* zero it out */
163
        bm_clear(bm, 0);
164

    
165
        switch (magic) {
166
                default:
167
                        /* not reached */
168
                        goto format_error;
169

    
170
                case '1':
171
                        /* read P1 format: PBM ascii */
172

    
173
                        for (y = h - 1; y >= 0; y--) {
174
                                for (x = 0; x < w; x++) {
175
                                        b = readbit(f);
176
                                        if (b < 0) {
177
                                                goto eof;
178
                                        }
179
                                        BM_UPUT(bm, x, y, b);
180
                                }
181
                        }
182
                        break;
183

    
184
                case '2':
185
                        /* read P2 format: PGM ascii */
186

    
187
                        max = readnum(f);
188
                        if (max < 1) {
189
                                goto format_error;
190
                        }
191

    
192
                        for (y = h - 1; y >= 0; y--) {
193
                                for (x = 0; x < w; x++) {
194
                                        b = readnum(f);
195
                                        if (b < 0) {
196
                                                goto eof;
197
                                        }
198
                                        BM_UPUT(bm, x, y, b > threshold * max ? 0 : 1);
199
                                }
200
                        }
201
                        break;
202

    
203
                case '3':
204
                        /* read P3 format: PPM ascii */
205

    
206
                        max = readnum(f);
207
                        if (max < 1) {
208
                                goto format_error;
209
                        }
210

    
211
                        for (y = h - 1; y >= 0; y--) {
212
                                for (x = 0; x < w; x++) {
213
                                        sum = 0;
214
                                        for (i = 0; i < 3; i++) {
215
                                                b = readnum(f);
216
                                                if (b < 0) {
217
                                                        goto eof;
218
                                                }
219
                                                sum += b;
220
                                        }
221
                                        BM_UPUT(bm, x, y, sum > 3 * threshold * max ? 0 : 1);
222
                                }
223
                        }
224
                        break;
225

    
226
                case '4':
227
                        /* read P4 format: PBM raw */
228

    
229
                        b = fgetc(f); /* read single white-space character after height */
230
                        if (b == EOF) {
231
                                goto format_error;
232
                        }
233

    
234
                        bpr = (w + 7) / 8;
235

    
236
                        for (y = h - 1; y >= 0; y--) {
237
                                for (i = 0; i < bpr; i++) {
238
                                        b = fgetc(f);
239
                                        if (b == EOF) {
240
                                                goto eof;
241
                                        }
242
                                        *bm_index(bm, i * 8, y) |= ((potrace_word) b) << (8 * (BM_WORDSIZE - 1 - (i % BM_WORDSIZE)));
243
                                }
244
                        }
245
                        break;
246

    
247
                case '5':
248
                        /* read P5 format: PGM raw */
249

    
250
                        max = readnum(f);
251
                        if (max < 1) {
252
                                goto format_error;
253
                        }
254

    
255
                        b = fgetc(f); /* read single white-space character after max */
256
                        if (b == EOF) {
257
                                goto format_error;
258
                        }
259

    
260
                        for (y = h - 1; y >= 0; y--) {
261
                                for (x = 0; x < w; x++) {
262
                                        b = fgetc(f);
263
                                        if (b == EOF)
264
                                                goto eof;
265
                                        if (max >= 256) {
266
                                                b <<= 8;
267
                                                b1 = fgetc(f);
268
                                                if (b1 == EOF)
269
                                                        goto eof;
270
                                                b |= b1;
271
                                        }
272
                                        BM_UPUT(bm, x, y, b > threshold * max ? 0 : 1);
273
                                }
274
                        }
275
                        break;
276

    
277
                case '6':
278
                        /* read P6 format: PPM raw */
279

    
280
                        max = readnum(f);
281
                        if (max < 1) {
282
                                goto format_error;
283
                        }
284

    
285
                        b = fgetc(f); /* read single white-space character after max */
286
                        if (b == EOF) {
287
                                goto format_error;
288
                        }
289

    
290
                        for (y = h - 1; y >= 0; y--) {
291
                                for (x = 0; x < w; x++) {
292
                                        sum = 0;
293
                                        for (i = 0; i < 3; i++) {
294
                                                b = fgetc(f);
295
                                                if (b == EOF) {
296
                                                        goto eof;
297
                                                }
298
                                                if (max >= 256) {
299
                                                        b <<= 8;
300
                                                        b1 = fgetc(f);
301
                                                        if (b1 == EOF)
302
                                                                goto eof;
303
                                                        b |= b1;
304
                                                }
305
                                                sum += b;
306
                                        }
307
                                        BM_UPUT(bm, x, y, sum > 3 * threshold * max ? 0 : 1);
308
                                }
309
                        }
310
                        break;
311
        }
312

    
313
        *bmp = bm;
314
        return 0;
315

    
316
        eof: *bmp = bm;
317
        return 1;
318

    
319
        format_error: bm_free(bm);
320
        if (magic == '1' || magic == '4') {
321
                bm_read_error = "invalid pbm file";
322
        } else
323
                if (magic == '2' || magic == '5') {
324
                        bm_read_error = "invalid pgm file";
325
                } else {
326
                        bm_read_error = "invalid ppm file";
327
                }
328
        return -2;
329
}
330

    
331
/* ---------------------------------------------------------------------- */
332
/* read BMP format */
333

    
334
struct bmp_info_s {
335
        unsigned int FileSize;
336
        unsigned int reserved;
337
        unsigned int DataOffset;
338
        unsigned int InfoSize;
339
        unsigned int w; /* width */
340
        unsigned int h; /* height */
341
        unsigned int Planes;
342
        unsigned int bits; /* bits per sample */
343
        unsigned int comp; /* compression mode */
344
        unsigned int ImageSize;
345
        unsigned int XpixelsPerM;
346
        unsigned int YpixelsPerM;
347
        unsigned int ncolors; /* number of colors in palette */
348
        unsigned int ColorsImportant;
349
        unsigned int ctbits; /* sample size for color table */
350
};
351
typedef struct bmp_info_s bmp_info_t;
352

    
353
/* auxiliary */
354

    
355
static int bmp_count = 0; /* counter for byte padding */
356
static int bmp_pos = 0; /* counter from start of BMP data */
357

    
358
/* read n-byte little-endian integer. Return 1 on EOF or error, else
359
 0. Assume n<=4. */
360
static int bmp_readint(FILE *f, int n, unsigned int *p) {
361
        int i;
362
        unsigned int sum = 0;
363
        int b;
364

    
365
        for (i = 0; i < n; i++) {
366
                b = fgetc(f);
367
                if (b == EOF) {
368
                        return 1;
369
                }
370
                sum += b << (8 * i);
371
        }
372
        bmp_count += n;
373
        bmp_pos += n;
374
        *p = sum;
375
        return 0;
376
}
377

    
378
/* reset padding boundary */
379
static void bmp_pad_reset(void) {
380
        bmp_count = 0;
381
}
382

    
383
/* read padding bytes to 4-byte boundary. Return 1 on EOF or error,
384
 else 0. */
385
static int bmp_pad(FILE *f) {
386
        int c, i, b;
387

    
388
        c = (-bmp_count) & 3;
389
        for (i = 0; i < c; i++) {
390
                b = fgetc(f);
391
                if (b == EOF) {
392
                        return 1;
393
                }
394
        }
395
        bmp_pos += c;
396
        bmp_count = 0;
397
        return 0;
398
}
399

    
400
/* forward to the new file position. Return 1 on EOF or error, else 0 */
401
static int bmp_forward(FILE *f, int pos) {
402
        int b;
403

    
404
        while (bmp_pos < pos) {
405
                b = fgetc(f);
406
                if (b == EOF) {
407
                        return 1;
408
                }
409
                bmp_pos++;
410
                bmp_count++;
411
        }
412
        return 0;
413
}
414

    
415
#define TRY(x) if (x) goto try_error
416
#define TRY_EOF(x) if (x) goto eof
417

    
418
/* read BMP stream after magic number. Return values as for bm_read.
419
 We choose to be as permissive as possible, since there are many
420
 programs out there which produce BMP. For instance, ppmtobmp can
421
 produce codings with anywhere from 1-8 or 24 bits per sample,
422
 although most specifications only allow 1,4,8,24,32. We can also
423
 read both the old and new OS/2 BMP formats in addition to the
424
 Windows BMP format. */
425
static int bm_readbody_bmp(FILE *f, double threshold, potrace_bitmap_t **bmp) {
426
        bmp_info_t bmpinfo;
427
        int *coltable;
428
        unsigned int b, c;
429
        unsigned int i;
430
        potrace_bitmap_t *bm;
431
        int mask;
432
        unsigned int x, y;
433
        int col[2];
434
        unsigned int bitbuf;
435
        unsigned int n;
436
        int col1[2];
437

    
438
        bm_read_error = NULL;
439
        bm = NULL;
440
        coltable = NULL;
441

    
442
        bmp_pos = 2; /* set file position */
443

    
444
        /* file header (minus magic number) */
445
        TRY(bmp_readint(f, 4, &bmpinfo.FileSize));
446
        TRY(bmp_readint(f, 4, &bmpinfo.reserved));
447
        TRY(bmp_readint(f, 4, &bmpinfo.DataOffset));
448

    
449
        /* info header */
450
        TRY(bmp_readint(f, 4, &bmpinfo.InfoSize));
451
        if (bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64) {
452
                /* Windows or new OS/2 format */
453
                bmpinfo.ctbits = 32; /* sample size in color table */
454
                TRY(bmp_readint(f, 4, &bmpinfo.w));
455
                TRY(bmp_readint(f, 4, &bmpinfo.h));
456
                TRY(bmp_readint(f, 2, &bmpinfo.Planes));
457
                TRY(bmp_readint(f, 2, &bmpinfo.bits));
458
                TRY(bmp_readint(f, 4, &bmpinfo.comp));
459
                TRY(bmp_readint(f, 4, &bmpinfo.ImageSize));
460
                TRY(bmp_readint(f, 4, &bmpinfo.XpixelsPerM));
461
                TRY(bmp_readint(f, 4, &bmpinfo.YpixelsPerM));
462
                TRY(bmp_readint(f, 4, &bmpinfo.ncolors));
463
                TRY(bmp_readint(f, 4, &bmpinfo.ColorsImportant));
464
        } else if (bmpinfo.InfoSize == 12) {
465
                /* old OS/2 format */
466
                bmpinfo.ctbits = 24; /* sample size in color table */
467
                TRY(bmp_readint(f, 2, &bmpinfo.w));
468
                TRY(bmp_readint(f, 2, &bmpinfo.h));
469
                TRY(bmp_readint(f, 2, &bmpinfo.Planes));
470
                TRY(bmp_readint(f, 2, &bmpinfo.bits));
471
                bmpinfo.comp = 0;
472
                bmpinfo.ncolors = 0;
473
        } else {
474
                goto format_error;
475
        }
476

    
477
        /* forward to color table (i.e., if bmpinfo.InfoSize == 64) */
478
        TRY(bmp_forward(f, 14+bmpinfo.InfoSize));
479

    
480
        if (bmpinfo.Planes != 1) {
481
                bm_read_error = "cannot handle bmp planes";
482
                goto format_error; /* can't handle planes */
483
        }
484

    
485
        if (bmpinfo.ncolors == 0) {
486
                bmpinfo.ncolors = 1 << bmpinfo.bits;
487
        }
488

    
489
        /* color table, present only if bmpinfo.bits <= 8. */
490
        if (bmpinfo.bits <= 8) {
491
                coltable = (int *) malloc(bmpinfo.ncolors * sizeof(int));
492
                if (!coltable) {
493
                        goto std_error;
494
                }
495
                /* NOTE: since we are reading a bitmap, we can immediately convert
496
                 the color table entries to bits. */
497
                for (i=0; i<bmpinfo.ncolors; i++) {
498
                        TRY(bmp_readint(f, bmpinfo.ctbits/8, &c));
499
                        c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
500
                        coltable[i] = (c> 3 * threshold * 255 ? 0 : 1);
501
                        if (i<2) {
502
                                col1[i] = c;
503
                        }
504
                }
505
        }
506

    
507
        /* forward to data */
508
        if (bmpinfo.InfoSize != 12) { /* not old OS/2 format */
509
                TRY(bmp_forward(f, bmpinfo.DataOffset));
510
        }
511

    
512
        /* allocate bitmap */
513
        bm = bm_new(bmpinfo.w, bmpinfo.h);
514
        if (!bm) {
515
                goto std_error;
516
        }
517

    
518
        /* zero it out */
519
        bm_clear(bm, 0);
520

    
521
        switch (bmpinfo.bits + 0x100*bmpinfo.comp) {
522

    
523
                default:
524
                goto format_error;
525
                break;
526

    
527
                case 0x001: /* monochrome palette */
528
                if (col1[0] < col1[1]) { /* make the darker color black */
529
                        mask = 0xff;
530
                } else {
531
                        mask = 0;
532
                }
533

    
534
                /* raster data */
535
                for (y=0; y<bmpinfo.h; y++) {
536
                        bmp_pad_reset();
537
                        for (i=0; 8*i<bmpinfo.w; i++) {
538
                                TRY_EOF(bmp_readint(f, 1, &b));
539
                                b ^= mask;
540
                                *bm_index(bm, i*8, y) |= ((potrace_word)b) << (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)));
541
                        }
542
                        TRY(bmp_pad(f));
543
                }
544
                break;
545

    
546
                case 0x002: /* 2-bit to 8-bit palettes */
547
                case 0x003:
548
                case 0x004:
549
                case 0x005:
550
                case 0x006:
551
                case 0x007:
552
                case 0x008:
553
                for (y=0; y<bmpinfo.h; y++) {
554
                        bmp_pad_reset();
555
                        bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
556
                        n = 0; /* number of bits currently in bitbuffer */
557
                        for (x=0; x<bmpinfo.w; x++) {
558
                                if (n < bmpinfo.bits) {
559
                                        TRY_EOF(bmp_readint(f, 1, &b));
560
                                        bitbuf |= b << (INTBITS - 8 - n);
561
                                        n += 8;
562
                                }
563
                                b = bitbuf >> (INTBITS - bmpinfo.bits);
564
                                bitbuf <<= bmpinfo.bits;
565
                                n -= bmpinfo.bits;
566
                                BM_UPUT(bm, x, y, coltable[b]);
567
                        }
568
                        TRY(bmp_pad(f));
569
                }
570
                break;
571

    
572
                case 0x010: /* 16-bit encoding */
573
                /* can't do this format because it is not well-documented and I
574
                 don't have any samples */
575
                bm_read_error = "cannot handle bmp 16-bit coding";
576
                goto format_error;
577
                break;
578

    
579
                case 0x018: /* 24-bit encoding */
580
                case 0x020: /* 32-bit encoding */
581
                for (y=0; y<bmpinfo.h; y++) {
582
                        bmp_pad_reset();
583
                        for (x=0; x<bmpinfo.w; x++) {
584
                                TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
585
                                c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
586
                                BM_UPUT(bm, x, y, c> 3 * threshold * 255 ? 0 : 1);
587
                        }
588
                        TRY(bmp_pad(f));
589
                }
590
                break;
591

    
592
                case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
593
                x = 0;
594
                y = 0;
595
                while (1) {
596
                        TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
597
                        TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
598
                        if (b>0) {
599
                                /* repeat count */
600
                                col[0] = coltable[(c>>4) & 0xf];
601
                                col[1] = coltable[c & 0xf];
602
                                for (i=0; i<b && x<bmpinfo.w; i++) {
603
                                        if (x>=bmpinfo.w) {
604
                                                x=0;
605
                                                y++;
606
                                        }
607
                                        if (y>=bmpinfo.h) {
608
                                                break;
609
                                        }
610
                                        BM_UPUT(bm, x, y, col[i&1]);
611
                                        x++;
612
                                }
613
                        } else if (c == 0) {
614
                                /* end of line */
615
                                y++;
616
                                x = 0;
617
                        } else if (c == 1) {
618
                                /* end of bitmap */
619
                                break;
620
                        } else if (c == 2) {
621
                                /* "delta": skip pixels in x and y directions */
622
                                TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
623
                                TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
624
                                x += b;
625
                                y += c;
626
                        } else {
627
                                /* verbatim segment */
628
                                for (i=0; i<c; i++) {
629
                                        if ((i&1)==0) {
630
                                                TRY_EOF(bmp_readint(f, 1, &b));
631
                                        }
632
                                        if (x>=bmpinfo.w) {
633
                                                x=0;
634
                                                y++;
635
                                        }
636
                                        if (y>=bmpinfo.h) {
637
                                                break;
638
                                        }
639
                                        BM_PUT(bm, x, y, coltable[(b>>(4-4*(i&1))) & 0xf]);
640
                                        x++;
641
                                }
642
                                if ((c+1) & 2) {
643
                                        /* pad to 16-bit boundary */
644
                                        TRY_EOF(bmp_readint(f, 1, &b));
645
                                }
646
                        }
647
                }
648
                break;
649

    
650
                case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
651
                x = 0;
652
                y = 0;
653
                while (1) {
654
                        TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
655
                        TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
656
                        if (b>0) {
657
                                /* repeat count */
658
                                for (i=0; i<b; i++) {
659
                                        if (x>=bmpinfo.w) {
660
                                                x=0;
661
                                                y++;
662
                                        }
663
                                        if (y>=bmpinfo.h) {
664
                                                break;
665
                                        }
666
                                        BM_UPUT(bm, x, y, coltable[c]);
667
                                        x++;
668
                                }
669
                        } else if (c == 0) {
670
                                /* end of line */
671
                                y++;
672
                                x = 0;
673
                        } else if (c == 1) {
674
                                /* end of bitmap */
675
                                break;
676
                        } else if (c == 2) {
677
                                /* "delta": skip pixels in x and y directions */
678
                                TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
679
                                TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
680
                                x += b;
681
                                y += c;
682
                        } else {
683
                                /* verbatim segment */
684
                                for (i=0; i<c; i++) {
685
                                        TRY_EOF(bmp_readint(f, 1, &b));
686
                                        if (x>=bmpinfo.w) {
687
                                                x=0;
688
                                                y++;
689
                                        }
690
                                        if (y>=bmpinfo.h) {
691
                                                break;
692
                                        }
693
                                        BM_PUT(bm, x, y, coltable[b]);
694
                                        x++;
695
                                }
696
                                if (c & 1) {
697
                                        /* pad input to 16-bit boundary */
698
                                        TRY_EOF(bmp_readint(f, 1, &b));
699
                                }
700
                        }
701
                }
702
                break;
703

    
704
        } /* switch */
705

    
706
        /* skip any potential junk after the data section, but don't
707
         complain in case EOF is encountered */
708
        bmp_forward(f, bmpinfo.FileSize);
709

    
710
        free(coltable);
711
        *bmp = bm;
712
        return 0;
713

    
714
        eof:
715
        free(coltable);
716
        *bmp = bm;
717
        return 1;
718

    
719
        format_error:
720
        try_error:
721
        free(coltable);
722
        free(bm);
723
        if (!bm_read_error) {
724
                bm_read_error = "invalid bmp file";
725
        }
726
        return -2;
727

    
728
        std_error:
729
        free(coltable);
730
        free(bm);
731
        return -1;
732
}
733

    
734
/* ---------------------------------------------------------------------- */
735
/* output pbm format */
736

    
737
void bm_writepbm(FILE *f, potrace_bitmap_t *bm) {
738
        int w, h, bpr, y, i, c;
739

    
740
        w = bm->w;
741
        h = bm->h;
742

    
743
        bpr = (w + 7) / 8;
744

    
745
        fprintf(f, "P4\n%d %d\n", w, h);
746
        for (y = h - 1; y >= 0; y--) {
747
                for (i = 0; i < bpr; i++) {
748
                        c = (*bm_index(bm, i * 8, y) >> (8 * (BM_WORDSIZE - 1 - (i % BM_WORDSIZE)))) & 0xff;
749
                        fputc(c, f);
750
                }
751
        }
752
        return;
753
}
754

    
755
/* ---------------------------------------------------------------------- */
756
/* output - for primitive debugging purposes only! */
757

    
758
/* print bitmap to screen */
759
int bm_print(FILE *f, potrace_bitmap_t *bm) {
760
        int x, y;
761
        int xx, yy;
762
        int d;
763
        int sw, sh;
764

    
765
        sw = bm->w < 79 ? bm->w : 79;
766
        sh = bm->w < 79 ? bm->h : bm->h * sw * 44 / (79 * bm->w);
767

    
768
        for (yy = sh - 1; yy >= 0; yy--) {
769
                for (xx = 0; xx < sw; xx++) {
770
                        d = 0;
771
                        for (x = xx * bm->w / sw; x < (xx + 1) * bm->w / sw; x++) {
772
                                for (y = yy * bm->h / sh; y < (yy + 1) * bm->h / sh; y++) {
773
                                        if (BM_GET(bm, x, y)) {
774
                                                d++;
775
                                        }
776
                                }
777
                        }
778
                        fputc(d ? '*' : ' ', f);
779
                }
780
                fputc('\n', f);
781
        }
782
        return 0;
783
}
784