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