From 1fa449fed953fa11f6bd0ea82cc2d3b115ee0781 Mon Sep 17 00:00:00 2001 From: saurabhb17 Date: Wed, 26 Feb 2020 16:36:01 +0530 Subject: Remaining files transfered --- potrace/bitmap_io.cpp | 969 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 969 insertions(+) create mode 100644 potrace/bitmap_io.cpp (limited to 'potrace/bitmap_io.cpp') diff --git a/potrace/bitmap_io.cpp b/potrace/bitmap_io.cpp new file mode 100644 index 0000000..3866593 --- /dev/null +++ b/potrace/bitmap_io.cpp @@ -0,0 +1,969 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + * This file is part of Potrace. It is free software and it is covered + * by the GNU General Public License. See the file COPYING for details. */ + +/* $Id: bitmap_io.c 147 2007-04-09 00:44:09Z selinger $ */ + +/* Routines for manipulating bitmaps, including reading pbm files. */ + +#include + +#include + +#define INTBITS ( 8 * sizeof(int) ) + +static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp ); +static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, int magic ); + +/* ---------------------------------------------------------------------- */ +/* routines for reading pnm streams */ + +/* read next character after whitespace and comments. Return EOF on + * end of file or error. */ +static int fgetc_ws( FILE* f ) +{ + int c; + + while( 1 ) + { + c = fgetc( f ); + if( c=='#' ) + { + while( 1 ) + { + c = fgetc( f ); + if( c=='\n' || c==EOF ) + { + break; + } + } + } + /* space, tab, line feed, carriage return, form-feed */ + if( c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12 ) + { + return c; + } + } +} + + +/* skip whitespace and comments, then read a non-negative decimal + * number from a stream. Return -1 on EOF. Tolerate other errors (skip + * bad characters). Do not the read any characters following the + * number (put next character back into the stream) */ + +static int readnum( FILE* f ) +{ + int c; + int acc; + + /* skip whitespace and comments */ + while( 1 ) + { + c = fgetc_ws( f ); + if( c==EOF ) + { + return -1; + } + if( c>='0' && c<='9' ) + { + break; + } + } + + /* first digit is already in c */ + acc = c - '0'; + while( 1 ) + { + c = fgetc( f ); + if( c==EOF ) + { + break; + } + if( c<'0' || c>'9' ) + { + ungetc( c, f ); + break; + } + acc *= 10; + acc += c - '0'; + } + + return acc; +} + + +/* similar to readnum, but read only a single 0 or 1, and do not read + * any characters after it. */ + +static int readbit( FILE* f ) +{ + int c; + + /* skip whitespace and comments */ + while( 1 ) + { + c = fgetc_ws( f ); + if( c==EOF ) + { + return -1; + } + if( c>='0' && c<='1' ) + { + break; + } + } + + return c - '0'; +} + + +/* ---------------------------------------------------------------------- */ + +/* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and + * convert the output to a bitmap. Return bitmap in *bmp. Return 0 on + * success, -1 on error with errno set, -2 on bad file format (with + * error message in bm_read_error), and 1 on premature end of file, -3 + * on empty file (including files which contain only whitespace and + * comments), -4 if wrong magic number. If the return value is >=0, + *bmp is valid. */ + +const char* bm_read_error = NULL; + +int bm_read( FILE* f, double threshold, potrace_bitmap_t** bmp ) +{ + int magic[2]; + + /* read magic number. We ignore whitespace and comments before the + * magic, for the benefit of concatenated files in P1-P3 format. + * Multiple P1-P3 images in a single file are not formally allowed + * by the PNM standard, but there is no harm in being lenient. */ + + magic[0] = fgetc_ws( f ); + if( magic[0] == EOF ) + { + return -3; + } + magic[1] = fgetc( f ); + if( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' ) + { + return bm_readbody_pnm( f, threshold, bmp, magic[1] ); + } + if( magic[0] == 'B' && magic[1] == 'M' ) + { + return bm_readbody_bmp( f, threshold, bmp ); + } + return -4; +} + + +/* ---------------------------------------------------------------------- */ +/* read PNM format */ + +/* read PNM stream after magic number. Return values as for bm_read */ +static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, int magic ) +{ + potrace_bitmap_t* bm; + int x, y, i, b, b1, sum; + int bpr; /* bytes per row (as opposed to 4*bm->c) */ + int w, h, max; + + bm = NULL; + + w = readnum( f ); + if( w<0 ) + { + goto format_error; + } + + h = readnum( f ); + if( h<0 ) + { + goto format_error; + } + + /* allocate bitmap */ + bm = bm_new( w, h ); + if( !bm ) + { + return -1; + } + + /* zero it out */ + bm_clear( bm, 0 ); + + switch( magic ) + { + default: + /* not reached */ + goto format_error; + + case '1': + /* read P1 format: PBM ascii */ + + for( y = h - 1; y>=0; y-- ) + { + for( x = 0; x=0; y-- ) + { + for( x = 0; x threshold * max ? 0 : 1 ); + } + } + + break; + + case '3': + /* read P3 format: PPM ascii */ + + max = readnum( f ); + if( max<1 ) + { + goto format_error; + } + + for( y = h - 1; y>=0; y-- ) + { + for( x = 0; x 3 * threshold * max ? 0 : 1 ); + } + } + + break; + + case '4': + /* read P4 format: PBM raw */ + + b = fgetc( f ); /* read single white-space character after height */ + if( b==EOF ) + { + goto format_error; + } + + bpr = (w + 7) / 8; + + for( y = h - 1; y>=0; y-- ) + { + for( i = 0; i=0; y-- ) + { + for( x = 0; x=256 ) + { + b <<= 8; + b1 = fgetc( f ); + if( b1==EOF ) + goto eof; + b |= b1; + } + BM_UPUT( bm, x, y, b > threshold * max ? 0 : 1 ); + } + } + + break; + + case '6': + /* read P6 format: PPM raw */ + + max = readnum( f ); + if( max<1 ) + { + goto format_error; + } + + b = fgetc( f ); /* read single white-space character after max */ + if( b==EOF ) + { + goto format_error; + } + + for( y = h - 1; y>=0; y-- ) + { + for( x = 0; x=256 ) + { + b <<= 8; + b1 = fgetc( f ); + if( b1==EOF ) + goto eof; + b |= b1; + } + sum += b; + } + + BM_UPUT( bm, x, y, sum > 3 * threshold * max ? 0 : 1 ); + } + } + + break; + } + + *bmp = bm; + return 0; + +eof: + *bmp = bm; + return 1; + +format_error: + bm_free( bm ); + if( magic == '1' || magic == '4' ) + { + bm_read_error = "invalid pbm file"; + } + else if( magic == '2' || magic == '5' ) + { + bm_read_error = "invalid pgm file"; + } + else + { + bm_read_error = "invalid ppm file"; + } + return -2; +} + + +/* ---------------------------------------------------------------------- */ +/* read BMP format */ + +struct bmp_info_s +{ + unsigned int FileSize; + unsigned int reserved; + unsigned int DataOffset; + unsigned int InfoSize; + unsigned int w; /* width */ + unsigned int h; /* height */ + unsigned int Planes; + unsigned int bits; /* bits per sample */ + unsigned int comp; /* compression mode */ + unsigned int ImageSize; + unsigned int XpixelsPerM; + unsigned int YpixelsPerM; + unsigned int ncolors; /* number of colors in palette */ + unsigned int ColorsImportant; + unsigned int ctbits; /* sample size for color table */ +}; +typedef struct bmp_info_s bmp_info_t; + +/* auxiliary */ + +static int bmp_count = 0; /* counter for byte padding */ +static int bmp_pos = 0; /* counter from start of BMP data */ + +/* read n-byte little-endian integer. Return 1 on EOF or error, else + * 0. Assume n<=4. */ +static int bmp_readint( FILE* f, int n, unsigned int* p ) +{ + int i; + unsigned int sum = 0; + int b; + + for( i = 0; i> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff); + coltable[i] = (c > 3 * threshold * 255 ? 0 : 1); + if( i<2 ) + { + col1[i] = c; + } + } + } + + /* forward to data */ + if( bmpinfo.InfoSize != 12 ) /* not old OS/2 format */ + { + TRY( bmp_forward( f, bmpinfo.DataOffset ) ); + } + + /* allocate bitmap */ + bm = bm_new( bmpinfo.w, bmpinfo.h ); + if( !bm ) + { + goto std_error; + } + + /* zero it out */ + bm_clear( bm, 0 ); + + switch( bmpinfo.bits + 0x100 * bmpinfo.comp ) + { + default: + goto format_error; + break; + + case 0x001: /* monochrome palette */ + if( col1[0] < col1[1] ) /* make the darker color black */ + { + mask = 0xff; + } + else + { + mask = 0; + } + + /* raster data */ + for( y = 0; y> (INTBITS - bmpinfo.bits); + bitbuf <<= bmpinfo.bits; + n -= bmpinfo.bits; + BM_UPUT( bm, x, y, coltable[b] ); + } + + TRY( bmp_pad( f ) ); + } + + break; + + case 0x010: /* 16-bit encoding */ + + /* can't do this format because it is not well-documented and I + * don't have any samples */ + bm_read_error = "cannot handle bmp 16-bit coding"; + goto format_error; + break; + + case 0x018: /* 24-bit encoding */ + case 0x020: /* 32-bit encoding */ + for( y = 0; y> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff); + BM_UPUT( bm, x, y, c > 3 * threshold * 255 ? 0 : 1 ); + } + + TRY( bmp_pad( f ) ); + } + + break; + + case 0x204: /* 4-bit runlength compressed encoding (RLE4) */ + x = 0; + y = 0; + while( 1 ) + { + TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */ + TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */ + if( b>0 ) + { + /* repeat count */ + col[0] = coltable[(c >> 4) & 0xf]; + col[1] = coltable[c & 0xf]; + for( i = 0; i=bmpinfo.w ) + { + x = 0; + y++; + } + if( y>=bmpinfo.h ) + { + break; + } + BM_UPUT( bm, x, y, col[i & 1] ); + x++; + } + } + else if( c == 0 ) + { + /* end of line */ + y++; + x = 0; + } + else if( c == 1 ) + { + /* end of bitmap */ + break; + } + else if( c == 2 ) + { + /* "delta": skip pixels in x and y directions */ + TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */ + TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */ + x += b; + y += c; + } + else + { + /* verbatim segment */ + for( i = 0; i=bmpinfo.w ) + { + x = 0; + y++; + } + if( y>=bmpinfo.h ) + { + break; + } + BM_PUT( bm, x, y, coltable[( b >> ( 4 - 4 * (i & 1) ) ) & 0xf] ); + x++; + } + + if( (c + 1) & 2 ) + { + /* pad to 16-bit boundary */ + TRY_EOF( bmp_readint( f, 1, &b ) ); + } + } + } + + break; + + case 0x108: /* 8-bit runlength compressed encoding (RLE8) */ + x = 0; + y = 0; + while( 1 ) + { + TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */ + TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */ + if( b>0 ) + { + /* repeat count */ + for( i = 0; i=bmpinfo.w ) + { + x = 0; + y++; + } + if( y>=bmpinfo.h ) + { + break; + } + BM_UPUT( bm, x, y, coltable[c] ); + x++; + } + } + else if( c == 0 ) + { + /* end of line */ + y++; + x = 0; + } + else if( c == 1 ) + { + /* end of bitmap */ + break; + } + else if( c == 2 ) + { + /* "delta": skip pixels in x and y directions */ + TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */ + TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */ + x += b; + y += c; + } + else + { + /* verbatim segment */ + for( i = 0; i=bmpinfo.w ) + { + x = 0; + y++; + } + if( y>=bmpinfo.h ) + { + break; + } + BM_PUT( bm, x, y, coltable[b] ); + x++; + } + + if( c & 1 ) + { + /* pad input to 16-bit boundary */ + TRY_EOF( bmp_readint( f, 1, &b ) ); + } + } + } + + break; + } /* switch */ + + /* skip any potential junk after the data section, but don't + * complain in case EOF is encountered */ + bmp_forward( f, bmpinfo.FileSize ); + + free( coltable ); + *bmp = bm; + return 0; + +eof: + free( coltable ); + *bmp = bm; + return 1; + +format_error: +try_error: + free( coltable ); + free( bm ); + if( !bm_read_error ) + { + bm_read_error = "invalid bmp file"; + } + return -2; + +std_error: + free( coltable ); + free( bm ); + return -1; +} + + +/* ---------------------------------------------------------------------- */ +/* output pbm format */ + +void bm_writepbm( FILE* f, potrace_bitmap_t* bm ) +{ + int w, h, bpr, y, i, c; + + w = bm->w; + h = bm->h; + + bpr = (w + 7) / 8; + + fprintf( f, "P4\n%d %d\n", w, h ); + for( y = h - 1; y>=0; y-- ) + { + for( i = 0; i> ( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) ) ) & 0xff; + fputc( c, f ); + } + } + + return; +} + + +/* ---------------------------------------------------------------------- */ +/* output - for primitive debugging purposes only! */ + +/* print bitmap to screen */ +int bm_print( FILE* f, potrace_bitmap_t* bm ) +{ + int x, y; + int xx, yy; + int d; + int sw, sh; + + sw = bm->w < 79 ? bm->w : 79; + sh = bm->w < 79 ? bm->h : bm->h * sw * 44 / (79 * bm->w); + + for( yy = sh - 1; yy>=0; yy-- ) + { + for( xx = 0; xxw / sw; x<(xx + 1) * bm->w / sw; x++ ) + { + for( y = yy * bm->h / sh; y<(yy + 1) * bm->h / sh; y++ ) + { + if( BM_GET( bm, x, y ) ) + { + d++; + } + } + } + + fputc( d ? '*' : ' ', f ); + } + + fputc( '\n', f ); + } + + return 0; +} -- cgit