KiCad PCB EDA Suite
greymap.cpp File Reference
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <stddef.h>
#include "greymap.h"
#include "bitops.h"

Go to the source code of this file.

Classes

struct  bmp_info_s
 

Macros

#define INTBITS   ( 8 * sizeof(int) )
 
#define mod(a, n)   ( (a)>=(n) ? (a) % (n) : (a)>=0 ? (a) : (n) - 1 - ( -1 - (a) ) % (n) )
 
#define TRY(x)
 
#define TRY_EOF(x)
 
#define ycorr(y)   (bmpinfo.topdown ? bmpinfo.h - 1 - y : y)
 

Typedefs

typedef struct bmp_info_s bmp_info_t
 

Functions

static int gm_readbody_pnm (FILE *f, greymap_t **gmp, int magic)
 
static int gm_readbody_bmp (FILE *f, greymap_t **gmp)
 
greymap_tgm_new (int w, int h)
 
void gm_free (greymap_t *gm)
 
greymap_tgm_dup (greymap_t *gm)
 
void gm_clear (greymap_t *gm, int b)
 
static int fgetc_ws (FILE *f)
 
static int readnum (FILE *f)
 
static int readbit (FILE *f)
 
int gm_read (FILE *f, greymap_t **gmp)
 
static int bmp_readint (FILE *f, int n, unsigned int *p)
 
static void bmp_pad_reset (void)
 
static int bmp_pad (FILE *f)
 
static int bmp_forward (FILE *f, int pos)
 
int gm_writepgm (FILE *f, greymap_t *gm, char *comment, int raw, int mode, double gamma)
 
int gm_print (FILE *f, greymap_t *gm)
 

Variables

const char * gm_read_error = NULL
 
static int bmp_count = 0
 
static int bmp_pos = 0
 

Macro Definition Documentation

#define INTBITS   ( 8 * sizeof(int) )

Definition at line 22 of file greymap.cpp.

Referenced by gm_readbody_bmp().

#define TRY (   x)
Value:
if( x ) \
goto try_error

Definition at line 665 of file greymap.cpp.

Referenced by gm_readbody_bmp().

#define TRY_EOF (   x)
Value:
if( x ) \
goto eof

Definition at line 667 of file greymap.cpp.

Referenced by gm_readbody_bmp().

#define ycorr (   y)    (bmpinfo.topdown ? bmpinfo.h - 1 - y : y)

Definition at line 671 of file greymap.cpp.

Referenced by gm_readbody_bmp().

Typedef Documentation

typedef struct bmp_info_s bmp_info_t

Definition at line 578 of file greymap.cpp.

Function Documentation

static int bmp_forward ( FILE *  f,
int  pos 
)
static

Definition at line 644 of file greymap.cpp.

References bmp_count, and bmp_pos.

Referenced by gm_readbody_bmp().

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 }
static int bmp_count
Definition: greymap.cpp:582
static int bmp_pos
Definition: greymap.cpp:583
static int bmp_pad ( FILE *  f)
static

Definition at line 621 of file greymap.cpp.

References bmp_count, and bmp_pos.

Referenced by gm_readbody_bmp().

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 }
static int bmp_count
Definition: greymap.cpp:582
static int bmp_pos
Definition: greymap.cpp:583
static void bmp_pad_reset ( void  )
static

Definition at line 613 of file greymap.cpp.

References bmp_count.

Referenced by gm_readbody_bmp().

614 {
615  bmp_count = 0;
616 }
static int bmp_count
Definition: greymap.cpp:582
static int bmp_readint ( FILE *  f,
int  n,
unsigned int *  p 
)
static

Definition at line 587 of file greymap.cpp.

References bmp_count, and bmp_pos.

Referenced by gm_readbody_bmp().

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 }
static int bmp_count
Definition: greymap.cpp:582
static int bmp_pos
Definition: greymap.cpp:583
static int fgetc_ws ( FILE *  f)
static

Definition at line 118 of file greymap.cpp.

Referenced by gm_read(), readbit(), and readnum().

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 }
void gm_clear ( greymap_t gm,
int  b 
)

Definition at line 95 of file greymap.cpp.

References greymap_s::h, greymap_s::map, and greymap_s::w.

Referenced by gm_readbody_bmp(), and gm_readbody_pnm().

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 }
int h
Definition: greymap.h:20
signed short int * map
Definition: greymap.h:21
int w
Definition: greymap.h:19
greymap_t* gm_dup ( greymap_t gm)

Definition at line 80 of file greymap.cpp.

References gm_new(), greymap_s::h, greymap_s::map, and greymap_s::w.

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 }
int h
Definition: greymap.h:20
signed short int * map
Definition: greymap.h:21
int w
Definition: greymap.h:19
greymap_t * gm_new(int w, int h)
Definition: greymap.cpp:34
void gm_free ( greymap_t gm)

Definition at line 68 of file greymap.cpp.

References greymap_s::map.

Referenced by gm_readbody_pnm().

69 {
70  if( gm )
71  {
72  free( gm->map );
73  }
74 
75  free( gm );
76 }
signed short int * map
Definition: greymap.h:21
greymap_t* gm_new ( int  w,
int  h 
)

Definition at line 34 of file greymap.cpp.

References greymap_s::h, greymap_s::map, and greymap_s::w.

Referenced by gm_dup(), gm_readbody_bmp(), and gm_readbody_pnm().

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 }
int h
Definition: greymap.h:20
signed short int * map
Definition: greymap.h:21
int w
Definition: greymap.h:19
int gm_print ( FILE *  f,
greymap_t gm 
)

Definition at line 1249 of file greymap.cpp.

References GM_GET, greymap_s::h, and greymap_s::w.

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
int w
Definition: greymap.h:19
#define GM_GET(gm, x, y)
Definition: greymap.h:37
int gm_read ( FILE *  f,
greymap_t **  gmp 
)

Definition at line 239 of file greymap.cpp.

References fgetc_ws(), gm_readbody_bmp(), and gm_readbody_pnm().

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 }
static int gm_readbody_bmp(FILE *f, greymap_t **gmp)
Definition: greymap.cpp:680
static int gm_readbody_pnm(FILE *f, greymap_t **gmp, int magic)
Definition: greymap.cpp:276
static int fgetc_ws(FILE *f)
Definition: greymap.cpp:118
static int gm_readbody_bmp ( FILE *  f,
greymap_t **  gmp 
)
static

Definition at line 680 of file greymap.cpp.

References bmp_info_s::AlphaMask, bmp_info_s::bits, bmp_info_s::BlueMask, bmp_forward(), bmp_pad(), bmp_pad_reset(), bmp_pos, bmp_readint(), bmp_info_s::ColorsImportant, bmp_info_s::comp, bmp_info_s::ctbits, bmp_info_s::DataOffset, bmp_info_s::FileSize, gm_clear(), gm_new(), GM_PUT, gm_read_error, GM_UPUT, bmp_info_s::GreenMask, bmp_info_s::h, bmp_info_s::ImageSize, bmp_info_s::InfoSize, INTBITS, lobit(), bmp_info_s::ncolors, bmp_info_s::Planes, bmp_info_s::RedMask, bmp_info_s::reserved, bmp_info_s::topdown, TRY, TRY_EOF, bmp_info_s::w, bmp_info_s::XpixelsPerM, ycorr, and bmp_info_s::YpixelsPerM.

Referenced by gm_read().

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 }
void gm_clear(greymap_t *gm, int b)
Definition: greymap.cpp:95
unsigned int Planes
Definition: bitmap_io.cpp:470
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_pos
Definition: greymap.cpp:583
unsigned int YpixelsPerM
Definition: bitmap_io.cpp:475
#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
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 bmp_forward(FILE *f, int pos)
Definition: greymap.cpp:644
#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
unsigned int AlphaMask
Definition: bitmap_io.cpp:481
unsigned int GreenMask
Definition: bitmap_io.cpp:479
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
unsigned int ImageSize
Definition: bitmap_io.cpp:473
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
static int gm_readbody_pnm ( FILE *  f,
greymap_t **  gmp,
int  magic 
)
static

Definition at line 276 of file greymap.cpp.

References gm_clear(), gm_free(), gm_new(), GM_PUT, gm_read_error, GM_UPUT, max, readbit(), and readnum().

Referenced by gm_read().

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 }
void gm_clear(greymap_t *gm, int b)
Definition: greymap.cpp:95
void gm_free(greymap_t *gm)
Definition: greymap.cpp:68
static int readnum(FILE *f)
Definition: greymap.cpp:153
const char * gm_read_error
Definition: greymap.cpp:237
#define GM_UPUT(gm, x, y, b)
Definition: greymap.h:36
#define max(a, b)
Definition: auxiliary.h:86
greymap_t * gm_new(int w, int h)
Definition: greymap.cpp:34
static int readbit(FILE *f)
Definition: greymap.cpp:203
#define GM_PUT(gm, x, y, b)
Definition: greymap.h:40
int gm_writepgm ( FILE *  f,
greymap_t gm,
char *  comment,
int  raw,
int  mode,
double  gamma 
)

Definition at line 1144 of file greymap.cpp.

References GM_MODE_NEGATIVE, GM_MODE_NONZERO, GM_MODE_ODD, GM_MODE_POSITIVE, GM_UGET, greymap_s::h, mod, and greymap_s::w.

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 }
int h
Definition: greymap.h:20
#define GM_MODE_NEGATIVE
Definition: greymap.h:50
int w
Definition: greymap.h:19
#define GM_MODE_NONZERO
Definition: greymap.h:47
#define GM_MODE_ODD
Definition: greymap.h:48
#define GM_MODE_POSITIVE
Definition: greymap.h:49
#define mod(a, n)
Definition: greymap.cpp:24
#define GM_UGET(gm, x, y)
Definition: greymap.h:33
static int readbit ( FILE *  f)
static

Definition at line 203 of file greymap.cpp.

References fgetc_ws().

Referenced by gm_readbody_pnm().

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 }
static int fgetc_ws(FILE *f)
Definition: greymap.cpp:118
static int readnum ( FILE *  f)
static

Definition at line 153 of file greymap.cpp.

References fgetc_ws().

Referenced by gm_readbody_pnm().

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 }
static int fgetc_ws(FILE *f)
Definition: greymap.cpp:118

Variable Documentation

int bmp_count = 0
static

Definition at line 582 of file greymap.cpp.

Referenced by bmp_forward(), bmp_pad(), bmp_pad_reset(), and bmp_readint().

int bmp_pos = 0
static

Definition at line 583 of file greymap.cpp.

Referenced by bmp_forward(), bmp_pad(), bmp_readint(), and gm_readbody_bmp().

const char* gm_read_error = NULL

Definition at line 237 of file greymap.cpp.

Referenced by gm_readbody_bmp(), and gm_readbody_pnm().