bitmap_io.c
Go to the documentation of this file.
00001 /* Copyright (C) 2001-2007 Peter Selinger.
00002    This file is part of Potrace. It is free software and it is covered
00003    by the GNU General Public License. See the file COPYING for details. */
00004 
00005 /* $Id: bitmap_io.c 147 2007-04-09 00:44:09Z selinger $ */
00006 
00007 /* Routines for manipulating bitmaps, including reading pbm files. */
00008 
00009 #include <stdio.h>
00010 
00011 #include "bitmap.h"
00012 
00013 #define INTBITS (8*sizeof(int))
00014 
00015 static int bm_readbody_bmp(FILE *f, double threshold, potrace_bitmap_t **bmp);
00016 static int bm_readbody_pnm(FILE *f, double threshold, potrace_bitmap_t **bmp, int magic);
00017 
00018 /* ---------------------------------------------------------------------- */
00019 /* routines for reading pnm streams */
00020 
00021 /* read next character after whitespace and comments. Return EOF on
00022    end of file or error. */
00023 static int fgetc_ws(FILE *f) {
00024   int c;
00025 
00026   while (1) {
00027     c = fgetc(f);
00028     if (c=='#') {
00029       while (1) {
00030         c = fgetc(f);
00031         if (c=='\n' || c==EOF) {
00032           break;
00033         }
00034       }
00035     }
00036     /* space, tab, line feed, carriage return, form-feed */
00037     if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12) {
00038       return c;
00039     }
00040   }
00041 }
00042 
00043 /* skip whitespace and comments, then read a non-negative decimal
00044    number from a stream. Return -1 on EOF. Tolerate other errors (skip
00045    bad characters). Do not the read any characters following the
00046    number (put next character back into the stream) */
00047 
00048 static int readnum(FILE *f) {
00049   int c;
00050   int acc;
00051 
00052   /* skip whitespace and comments */
00053   while (1) {
00054     c = fgetc_ws(f);
00055     if (c==EOF) {
00056       return -1;
00057     }
00058     if (c>='0' && c<='9') {
00059       break;
00060     }
00061   }
00062 
00063   /* first digit is already in c */
00064   acc = c-'0';
00065   while (1) {
00066     c = fgetc(f);
00067     if (c==EOF) {
00068       break;
00069     }
00070     if (c<'0' || c>'9') {
00071       ungetc(c, f);
00072       break;
00073     }
00074     acc *= 10;
00075     acc += c-'0';
00076   }
00077   return acc;
00078 }
00079 
00080 /* similar to readnum, but read only a single 0 or 1, and do not read
00081    any characters after it. */
00082 
00083 static int readbit(FILE *f) {
00084   int c;
00085 
00086   /* skip whitespace and comments */
00087   while (1) {
00088     c = fgetc_ws(f);
00089     if (c==EOF) {
00090       return -1;
00091     }
00092     if (c>='0' && c<='1') {
00093       break;
00094     }
00095   }
00096 
00097   return c-'0';
00098 }
00099 
00100 /* ---------------------------------------------------------------------- */
00101 
00102 /* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and
00103    convert the output to a bitmap. Return bitmap in *bmp. Return 0 on
00104    success, -1 on error with errno set, -2 on bad file format (with
00105    error message in bm_read_error), and 1 on premature end of file, -3
00106    on empty file (including files which contain only whitespace and
00107    comments), -4 if wrong magic number. If the return value is >=0,
00108    *bmp is valid. */
00109 
00110 char *bm_read_error = NULL;
00111 
00112 int bm_read(FILE *f, double threshold, potrace_bitmap_t **bmp) {
00113   int magic[2];
00114 
00115   /* read magic number. We ignore whitespace and comments before the
00116      magic, for the benefit of concatenated files in P1-P3 format.
00117      Multiple P1-P3 images in a single file are not formally allowed
00118      by the PNM standard, but there is no harm in being lenient. */
00119 
00120   magic[0] = fgetc_ws(f);
00121   if (magic[0] == EOF) {
00122     return -3;
00123   } 
00124   magic[1] = fgetc(f);
00125   if (magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6') {
00126     return bm_readbody_pnm(f, threshold, bmp, magic[1]);
00127   }
00128   if (magic[0] == 'B' && magic[1] == 'M') {
00129     return bm_readbody_bmp(f, threshold, bmp);
00130   }
00131   return -4;
00132 }
00133 
00134 /* ---------------------------------------------------------------------- */
00135 /* read PNM format */
00136 
00137 /* read PNM stream after magic number. Return values as for bm_read */
00138 static int bm_readbody_pnm(FILE *f, double threshold, potrace_bitmap_t **bmp, int magic) {
00139   potrace_bitmap_t *bm;
00140   int x, y, i, b, b1, sum;
00141   int bpr; /* bytes per row (as opposed to 4*bm->c) */
00142   int w, h, max;
00143 
00144   bm = NULL;
00145 
00146   w = readnum(f);
00147   if (w<0) {
00148     goto format_error;
00149   }
00150 
00151   h = readnum(f);
00152   if (h<0) {
00153     goto format_error;
00154   }
00155 
00156   /* allocate bitmap */
00157   bm = bm_new(w, h);
00158   if (!bm) {
00159     return -1;
00160   }
00161 
00162   /* zero it out */
00163   bm_clear(bm, 0);
00164 
00165   switch (magic) {
00166   default: 
00167     /* not reached */
00168     goto format_error;  
00169 
00170   case '1':
00171     /* read P1 format: PBM ascii */
00172     
00173     for (y=h-1; y>=0; y--) {
00174       for (x=0; x<w; x++) {
00175         b = readbit(f);
00176         if (b<0) {
00177           goto eof;
00178         }
00179         BM_UPUT(bm, x, y, b);
00180       }
00181     }
00182     break;
00183 
00184   case '2':
00185     /* read P2 format: PGM ascii */
00186     
00187     max = readnum(f);
00188     if (max<1) {
00189       goto format_error;
00190     }
00191     
00192     for (y=h-1; y>=0; y--) {
00193       for (x=0; x<w; x++) {
00194         b = readnum(f);
00195         if (b<0) {
00196           goto eof;
00197         }
00198         BM_UPUT(bm, x, y, b > threshold * max ? 0 : 1);
00199       }
00200     }
00201     break;
00202 
00203   case '3':
00204     /* read P3 format: PPM ascii */
00205     
00206     max = readnum(f);
00207     if (max<1) {
00208       goto format_error;
00209     }
00210     
00211     for (y=h-1; y>=0; y--) {
00212       for (x=0; x<w; x++) {
00213         sum = 0;
00214         for (i=0; i<3; i++) {
00215           b = readnum(f);
00216           if (b<0) {
00217             goto eof;
00218           }
00219           sum += b;
00220         }
00221         BM_UPUT(bm, x, y, sum > 3 * threshold * max ? 0 : 1);
00222       }
00223     }
00224     break;
00225 
00226   case '4':
00227     /* read P4 format: PBM raw */
00228 
00229     b = fgetc(f);  /* read single white-space character after height */
00230     if (b==EOF) {
00231       goto format_error;
00232     }
00233 
00234     bpr = (w+7)/8;
00235 
00236     for (y=h-1; y>=0; y--) {
00237       for (i=0; i<bpr; i++) {
00238         b = fgetc(f);
00239         if (b==EOF) {
00240           goto eof;
00241         }
00242         *bm_index(bm, i*8, y) |= ((potrace_word)b) << (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)));
00243       }
00244     }
00245     break;
00246 
00247   case '5':
00248     /* read P5 format: PGM raw */
00249 
00250     max = readnum(f);
00251     if (max<1) {
00252       goto format_error;
00253     }
00254 
00255     b = fgetc(f);  /* read single white-space character after max */
00256     if (b==EOF) {
00257       goto format_error;
00258     }
00259 
00260     for (y=h-1; y>=0; y--) {
00261       for (x=0; x<w; x++) {
00262         b = fgetc(f);
00263         if (b==EOF)
00264           goto eof;
00265         if (max>=256) {
00266           b <<= 8;
00267           b1 = fgetc(f);
00268           if (b1==EOF)
00269             goto eof;
00270           b |= b1;
00271         }
00272         BM_UPUT(bm, x, y, b > threshold * max ? 0 : 1);
00273       }
00274     }
00275     break;
00276 
00277   case '6':
00278     /* read P6 format: PPM raw */
00279 
00280     max = readnum(f);
00281     if (max<1) {
00282       goto format_error;
00283     }
00284 
00285     b = fgetc(f);  /* read single white-space character after max */
00286     if (b==EOF) {
00287       goto format_error;
00288     }
00289 
00290     for (y=h-1; y>=0; y--) {
00291       for (x=0; x<w; x++) {
00292         sum = 0;
00293         for (i=0; i<3; i++) {
00294           b = fgetc(f);
00295           if (b==EOF) {
00296             goto eof;
00297           }
00298           if (max>=256) {
00299             b <<= 8;
00300             b1 = fgetc(f);
00301             if (b1==EOF)
00302               goto eof;
00303             b |= b1;
00304           }
00305           sum += b;
00306         }
00307         BM_UPUT(bm, x, y, sum > 3 * threshold * max ? 0 : 1);
00308       }
00309     }
00310     break;
00311   }
00312 
00313   *bmp = bm;
00314   return 0;
00315 
00316  eof:
00317   *bmp = bm;
00318   return 1;
00319 
00320  format_error:
00321   bm_free(bm);
00322   if (magic == '1' || magic == '4') {
00323     bm_read_error = "invalid pbm file";
00324   } else if (magic == '2' || magic == '5') {
00325     bm_read_error = "invalid pgm file";
00326   } else {
00327     bm_read_error = "invalid ppm file";
00328   }
00329   return -2;
00330 }
00331 
00332 /* ---------------------------------------------------------------------- */
00333 /* read BMP format */
00334 
00335 struct bmp_info_s {
00336   unsigned int FileSize;
00337   unsigned int reserved;
00338   unsigned int DataOffset;
00339   unsigned int InfoSize;
00340   unsigned int w;              /* width */
00341   unsigned int h;              /* height */
00342   unsigned int Planes;
00343   unsigned int bits;           /* bits per sample */
00344   unsigned int comp;           /* compression mode */
00345   unsigned int ImageSize;
00346   unsigned int XpixelsPerM;
00347   unsigned int YpixelsPerM;
00348   unsigned int ncolors;        /* number of colors in palette */
00349   unsigned int ColorsImportant;
00350   unsigned int ctbits;         /* sample size for color table */
00351 };
00352 typedef struct bmp_info_s bmp_info_t;
00353 
00354 /* auxiliary */
00355 
00356 static int bmp_count = 0; /* counter for byte padding */
00357 static int bmp_pos = 0;   /* counter from start of BMP data */
00358 
00359 /* read n-byte little-endian integer. Return 1 on EOF or error, else
00360    0. Assume n<=4. */
00361 static int bmp_readint(FILE *f, int n, unsigned int *p) {
00362   int i;
00363   unsigned int sum = 0;
00364   int b;
00365 
00366   for (i=0; i<n; i++) {
00367     b = fgetc(f);
00368     if (b==EOF) {
00369       return 1;
00370     }
00371     sum += b << (8*i);
00372   }
00373   bmp_count += n;
00374   bmp_pos += n;
00375   *p = sum;
00376   return 0;
00377 }
00378 
00379 /* reset padding boundary */
00380 static void bmp_pad_reset(void) {
00381   bmp_count = 0;
00382 }
00383 
00384 /* read padding bytes to 4-byte boundary. Return 1 on EOF or error,
00385    else 0. */
00386 static int bmp_pad(FILE *f) {
00387   int c, i, b;
00388 
00389   c = (-bmp_count) & 3;
00390   for (i=0; i<c; i++) {
00391     b = fgetc(f);
00392     if (b==EOF) {
00393       return 1;
00394     }
00395   }
00396   bmp_pos += c;
00397   bmp_count = 0;
00398   return 0;
00399 }
00400   
00401 /* forward to the new file position. Return 1 on EOF or error, else 0 */
00402 static int bmp_forward(FILE *f, int pos) {
00403   int b;
00404 
00405   while (bmp_pos < pos) {
00406     b = fgetc(f);
00407     if (b==EOF) {
00408       return 1;
00409     }
00410     bmp_pos++;
00411     bmp_count++;
00412   }
00413   return 0;
00414 }
00415 
00416 #define TRY(x) if (x) goto try_error
00417 #define TRY_EOF(x) if (x) goto eof
00418 
00419 /* read BMP stream after magic number. Return values as for bm_read.
00420    We choose to be as permissive as possible, since there are many
00421    programs out there which produce BMP. For instance, ppmtobmp can
00422    produce codings with anywhere from 1-8 or 24 bits per sample,
00423    although most specifications only allow 1,4,8,24,32. We can also
00424    read both the old and new OS/2 BMP formats in addition to the
00425    Windows BMP format. */
00426 static int bm_readbody_bmp(FILE *f, double threshold, potrace_bitmap_t **bmp) {
00427   bmp_info_t bmpinfo;
00428   int *coltable;
00429   unsigned int b, c;
00430   unsigned int i;
00431   potrace_bitmap_t *bm;
00432   int mask;
00433   unsigned int x, y;
00434   int col[2];
00435   unsigned int bitbuf;
00436   unsigned int n;
00437   int col1[2];
00438 
00439   bm_read_error = NULL;
00440   bm = NULL;
00441   coltable = NULL;
00442 
00443   bmp_pos = 2;  /* set file position */
00444 
00445   /* file header (minus magic number) */
00446   TRY(bmp_readint(f, 4, &bmpinfo.FileSize));
00447   TRY(bmp_readint(f, 4, &bmpinfo.reserved));
00448   TRY(bmp_readint(f, 4, &bmpinfo.DataOffset));
00449 
00450   /* info header */
00451   TRY(bmp_readint(f, 4, &bmpinfo.InfoSize));
00452   if (bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64) {
00453     /* Windows or new OS/2 format */
00454     bmpinfo.ctbits = 32; /* sample size in color table */
00455     TRY(bmp_readint(f, 4, &bmpinfo.w));
00456     TRY(bmp_readint(f, 4, &bmpinfo.h));
00457     TRY(bmp_readint(f, 2, &bmpinfo.Planes));
00458     TRY(bmp_readint(f, 2, &bmpinfo.bits));
00459     TRY(bmp_readint(f, 4, &bmpinfo.comp));
00460     TRY(bmp_readint(f, 4, &bmpinfo.ImageSize));
00461     TRY(bmp_readint(f, 4, &bmpinfo.XpixelsPerM));
00462     TRY(bmp_readint(f, 4, &bmpinfo.YpixelsPerM));
00463     TRY(bmp_readint(f, 4, &bmpinfo.ncolors));
00464     TRY(bmp_readint(f, 4, &bmpinfo.ColorsImportant));
00465   } else if (bmpinfo.InfoSize == 12) {
00466     /* old OS/2 format */
00467     bmpinfo.ctbits = 24; /* sample size in color table */
00468     TRY(bmp_readint(f, 2, &bmpinfo.w));
00469     TRY(bmp_readint(f, 2, &bmpinfo.h));
00470     TRY(bmp_readint(f, 2, &bmpinfo.Planes));
00471     TRY(bmp_readint(f, 2, &bmpinfo.bits));
00472     bmpinfo.comp = 0;
00473     bmpinfo.ncolors = 0;
00474   } else {
00475     goto format_error;
00476   }
00477 
00478   /* forward to color table (i.e., if bmpinfo.InfoSize == 64) */
00479   TRY(bmp_forward(f, 14+bmpinfo.InfoSize));
00480 
00481   if (bmpinfo.Planes != 1) {
00482     bm_read_error = "cannot handle bmp planes";
00483     goto format_error;  /* can't handle planes */
00484   }
00485   
00486   if (bmpinfo.ncolors == 0) {
00487     bmpinfo.ncolors = 1 << bmpinfo.bits;
00488   }
00489 
00490   /* color table, present only if bmpinfo.bits <= 8. */
00491   if (bmpinfo.bits <= 8) {
00492     coltable = (int *) malloc(bmpinfo.ncolors * sizeof(int));
00493     if (!coltable) {
00494       goto std_error;
00495     }
00496     /* NOTE: since we are reading a bitmap, we can immediately convert
00497        the color table entries to bits. */
00498     for (i=0; i<bmpinfo.ncolors; i++) {
00499       TRY(bmp_readint(f, bmpinfo.ctbits/8, &c));
00500       c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
00501       coltable[i] = (c > 3 * threshold * 255 ? 0 : 1);
00502       if (i<2) {
00503         col1[i] = c;
00504       }
00505     }
00506   }
00507 
00508   /* forward to data */
00509   if (bmpinfo.InfoSize != 12) { /* not old OS/2 format */
00510     TRY(bmp_forward(f, bmpinfo.DataOffset));
00511   }
00512 
00513   /* allocate bitmap */
00514   bm = bm_new(bmpinfo.w, bmpinfo.h);
00515   if (!bm) {
00516     goto std_error;
00517   }
00518   
00519   /* zero it out */
00520   bm_clear(bm, 0);
00521 
00522   switch (bmpinfo.bits + 0x100*bmpinfo.comp) {
00523     
00524   default:
00525     goto format_error;
00526     break;
00527     
00528   case 0x001:  /* monochrome palette */
00529     if (col1[0] < col1[1]) { /* make the darker color black */
00530       mask = 0xff;
00531     } else {
00532       mask = 0;
00533     }
00534     
00535     /* raster data */
00536     for (y=0; y<bmpinfo.h; y++) {
00537       bmp_pad_reset();
00538       for (i=0; 8*i<bmpinfo.w; i++) {
00539         TRY_EOF(bmp_readint(f, 1, &b));
00540         b ^= mask;
00541         *bm_index(bm, i*8, y) |= ((potrace_word)b) << (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)));
00542       }
00543       TRY(bmp_pad(f));
00544     }
00545     break;
00546    
00547   case 0x002:  /* 2-bit to 8-bit palettes */
00548   case 0x003: 
00549   case 0x004: 
00550   case 0x005: 
00551   case 0x006: 
00552   case 0x007: 
00553   case 0x008:
00554     for (y=0; y<bmpinfo.h; y++) {
00555       bmp_pad_reset();
00556       bitbuf = 0;  /* bit buffer: bits in buffer are high-aligned */
00557       n = 0;       /* number of bits currently in bitbuffer */
00558       for (x=0; x<bmpinfo.w; x++) {
00559         if (n < bmpinfo.bits) {
00560           TRY_EOF(bmp_readint(f, 1, &b));
00561           bitbuf |= b << (INTBITS - 8 - n);
00562           n += 8;
00563         }
00564         b = bitbuf >> (INTBITS - bmpinfo.bits);
00565         bitbuf <<= bmpinfo.bits;
00566         n -= bmpinfo.bits;
00567         BM_UPUT(bm, x, y, coltable[b]);
00568       }
00569       TRY(bmp_pad(f));
00570     }
00571     break;
00572 
00573   case 0x010:  /* 16-bit encoding */
00574     /* can't do this format because it is not well-documented and I
00575        don't have any samples */
00576     bm_read_error = "cannot handle bmp 16-bit coding";
00577     goto format_error;
00578     break;
00579 
00580   case 0x018:  /* 24-bit encoding */
00581   case 0x020:  /* 32-bit encoding */
00582     for (y=0; y<bmpinfo.h; y++) {
00583       bmp_pad_reset();
00584       for (x=0; x<bmpinfo.w; x++) {
00585         TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
00586         c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
00587         BM_UPUT(bm, x, y, c > 3 * threshold * 255 ? 0 : 1);
00588       }
00589       TRY(bmp_pad(f));
00590     }
00591     break;
00592 
00593   case 0x204:  /* 4-bit runlength compressed encoding (RLE4) */
00594     x = 0;
00595     y = 0;
00596     while (1) {
00597       TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
00598       TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
00599       if (b>0) {
00600         /* repeat count */
00601         col[0] = coltable[(c>>4) & 0xf];
00602         col[1] = coltable[c & 0xf];
00603         for (i=0; i<b && x<bmpinfo.w; i++) {
00604           if (x>=bmpinfo.w) {
00605             x=0;
00606             y++;
00607           }
00608           if (y>=bmpinfo.h) {
00609             break;
00610           }
00611           BM_UPUT(bm, x, y, col[i&1]);
00612           x++;
00613         }
00614       } else if (c == 0) {
00615         /* end of line */
00616         y++;
00617         x = 0;
00618       } else if (c == 1) {
00619         /* end of bitmap */
00620         break;
00621       } else if (c == 2) {
00622         /* "delta": skip pixels in x and y directions */
00623         TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
00624         TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
00625         x += b;
00626         y += c;
00627       } else {
00628         /* verbatim segment */
00629         for (i=0; i<c; i++) {
00630           if ((i&1)==0) {
00631             TRY_EOF(bmp_readint(f, 1, &b));
00632           }
00633           if (x>=bmpinfo.w) {
00634             x=0;
00635             y++;
00636           }
00637           if (y>=bmpinfo.h) {
00638             break;
00639           }
00640           BM_PUT(bm, x, y, coltable[(b>>(4-4*(i&1))) & 0xf]);
00641           x++;
00642         }
00643         if ((c+1) & 2) {
00644           /* pad to 16-bit boundary */
00645           TRY_EOF(bmp_readint(f, 1, &b));
00646         }
00647       }
00648     }
00649     break;
00650 
00651   case 0x108:  /* 8-bit runlength compressed encoding (RLE8) */
00652     x = 0;
00653     y = 0;
00654     while (1) {
00655       TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
00656       TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
00657       if (b>0) {
00658         /* repeat count */
00659         for (i=0; i<b; i++) {
00660           if (x>=bmpinfo.w) {
00661             x=0;
00662             y++;
00663           }
00664           if (y>=bmpinfo.h) {
00665             break;
00666           }
00667           BM_UPUT(bm, x, y, coltable[c]);
00668           x++;
00669         }
00670       } else if (c == 0) {
00671         /* end of line */
00672         y++;
00673         x = 0;
00674       } else if (c == 1) {
00675         /* end of bitmap */
00676         break;
00677       } else if (c == 2) {
00678         /* "delta": skip pixels in x and y directions */
00679         TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
00680         TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
00681         x += b;
00682         y += c;
00683       } else {
00684         /* verbatim segment */
00685         for (i=0; i<c; i++) {
00686           TRY_EOF(bmp_readint(f, 1, &b));
00687           if (x>=bmpinfo.w) {
00688             x=0;
00689             y++;
00690           }
00691           if (y>=bmpinfo.h) {
00692             break;
00693           }
00694           BM_PUT(bm, x, y, coltable[b]);
00695           x++;
00696         }
00697         if (c & 1) {
00698           /* pad input to 16-bit boundary */
00699           TRY_EOF(bmp_readint(f, 1, &b));
00700         }
00701       }
00702     }
00703     break;
00704 
00705   } /* switch */
00706 
00707   /* skip any potential junk after the data section, but don't
00708      complain in case EOF is encountered */
00709   bmp_forward(f, bmpinfo.FileSize);
00710 
00711   free(coltable);
00712   *bmp = bm;
00713   return 0;
00714 
00715  eof:
00716   free(coltable);
00717   *bmp = bm;
00718   return 1;
00719 
00720  format_error:
00721  try_error:
00722   free(coltable);
00723   free(bm);
00724   if (!bm_read_error) {
00725     bm_read_error = "invalid bmp file";
00726   }
00727   return -2;
00728 
00729  std_error:
00730   free(coltable);
00731   free(bm);
00732   return -1;
00733 }
00734 
00735 /* ---------------------------------------------------------------------- */
00736 /* output pbm format */
00737 
00738 void bm_writepbm(FILE *f, potrace_bitmap_t *bm) {
00739   int w, h, bpr, y, i, c;
00740 
00741   w = bm->w;
00742   h = bm->h;
00743 
00744   bpr = (w+7)/8;
00745 
00746   fprintf(f, "P4\n%d %d\n", w, h);
00747   for (y=h-1; y>=0; y--) {
00748     for (i=0; i<bpr; i++) {
00749       c = (*bm_index(bm, i*8, y) >> (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)))) & 0xff;
00750       fputc(c, f);
00751     }
00752   }
00753   return;
00754 }
00755 
00756 /* ---------------------------------------------------------------------- */
00757 /* output - for primitive debugging purposes only! */
00758 
00759 /* print bitmap to screen */
00760 int bm_print(FILE *f, potrace_bitmap_t *bm) {
00761   int x, y;
00762   int xx, yy;
00763   int d;
00764   int sw, sh;
00765 
00766   sw = bm->w < 79 ? bm->w : 79;
00767   sh = bm->w < 79 ? bm->h : bm->h*sw*44/(79*bm->w);
00768 
00769   for (yy=sh-1; yy>=0; yy--) {
00770     for (xx=0; xx<sw; xx++) {
00771       d=0;
00772       for (x=xx*bm->w/sw; x<(xx+1)*bm->w/sw; x++) {
00773         for (y=yy*bm->h/sh; y<(yy+1)*bm->h/sh; y++) {
00774           if (BM_GET(bm, x, y)) {
00775             d++;
00776           }
00777         }
00778       }
00779       fputc(d ? '*' : ' ', f);
00780     }
00781     fputc('\n', f);
00782   }
00783   return 0;
00784 }
00785 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


portrait_painter
Author(s): Niklas Meinzer, Ina Baumgarten
autogenerated on Wed Dec 26 2012 16:00:43