w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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