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/greymap.cpp | 1108 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1108 insertions(+) create mode 100644 potrace/greymap.cpp (limited to 'potrace/greymap.cpp') diff --git a/potrace/greymap.cpp b/potrace/greymap.cpp new file mode 100644 index 0000000..203fa1a --- /dev/null +++ b/potrace/greymap.cpp @@ -0,0 +1,1108 @@ +/* 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: greymap.c 147 2007-04-09 00:44:09Z selinger $ */ + +/* Routines for manipulating greymaps, including reading pgm files. We + * only deal with greymaps of depth 8 bits. */ + +#include +#include +#include +#include + +#include + +#define INTBITS ( 8 * sizeof(int) ) + +#define mod( a, n ) ( (a)>=(n) ? (a) % (n) : (a)>=0 ? (a) : (n) - 1 - ( -1 - (a) ) % (n) ) + +static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic ); +static int gm_readbody_bmp( FILE* f, greymap_t** gmp ); + +/* ---------------------------------------------------------------------- */ +/* basic greymap routines */ + +/* return new un-initialized greymap. NULL with errno on error */ + +greymap_t* gm_new( int w, int h ) +{ + greymap_t* gm; + int errno_save; + + gm = (greymap_t*) malloc( sizeof(greymap_t) ); + if( !gm ) + { + return NULL; + } + gm->w = w; + gm->h = h; + gm->map = (signed short int*) malloc( w * h * sizeof(signed short int) ); + if( !gm->map ) + { + errno_save = errno; + free( gm ); + errno = errno_save; + return NULL; + } + return gm; +} + + +/* free the given greymap */ +void gm_free( greymap_t* gm ) +{ + if( gm ) + { + free( gm->map ); + } + free( gm ); +} + + +/* duplicate the given greymap. Return NULL on error with errno set. */ +greymap_t* gm_dup( greymap_t* gm ) +{ + greymap_t* gm1 = gm_new( gm->w, gm->h ); + + if( !gm1 ) + { + return NULL; + } + memcpy( gm1->map, gm->map, gm->w * gm->h * 2 ); + return gm1; +} + + +/* clear the given greymap to color b. */ +void gm_clear( greymap_t* gm, int b ) +{ + int i; + + if( b==0 ) + { + memset( gm->map, 0, gm->w * gm->h * 2 ); + } + else + { + for( i = 0; iw * gm->h; i++ ) + { + gm->map[i] = b; + } + } +} + + +/* ---------------------------------------------------------------------- */ +/* 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 greymap. Return greymap in *gmp. Return 0 + * on success, -1 on error with errno set, -2 on bad file format (with + * error message in gm_read_error), and 1 on premature end of file, -3 + * on empty file (including files with only whitespace and comments), + * -4 if wrong magic number. If the return value is >=0, *gmp is + * valid. */ + +const char* gm_read_error = NULL; + +int gm_read( FILE* f, greymap_t** gmp ) +{ + 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 ) + { + /* files which contain only comments and whitespace count as "empty" */ + return -3; + } + magic[1] = fgetc( f ); + if( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' ) + { + return gm_readbody_pnm( f, gmp, magic[1] ); + } + if( magic[0] == 'B' && magic[1] == 'M' ) + { + return gm_readbody_bmp( f, gmp ); + } + return -4; +} + + +/* ---------------------------------------------------------------------- */ +/* read PNM format */ + +/* read PNM stream after magic number. Return values as for gm_read */ +static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic ) +{ + greymap_t* gm; + int x, y, i, j, b, b1, sum; + int bpr; /* bytes per row (as opposed to 4*gm->c) */ + int w, h, max; + + gm = NULL; + + w = readnum( f ); + if( w<0 ) + { + goto format_error; + } + + h = readnum( f ); + if( h<0 ) + { + goto format_error; + } + + /* allocate greymap */ + gm = gm_new( w, h ); + if( !gm ) + { + return -1; + } + + /* zero it out */ + gm_clear( gm, 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=0; y-- ) + { + for( x = 0; x=0; y-- ) + { + for( i = 0; i> j) ? 0 : 255 ); + } + } + } + + break; + + case '5': + /* read P5 format: PGM 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; + } + GM_UPUT( gm, x, y, b * 255 / max ); + } + } + + 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; + } + + GM_UPUT( gm, x, y, sum * (255 / 3) / max ); + } + } + + break; + } + + *gmp = gm; + return 0; + +eof: + *gmp = gm; + return 1; + +format_error: + gm_free( gm ); + if( magic == '1' || magic == '4' ) + { + gm_read_error = "invalid pbm file"; + } + else if( magic == '2' || magic == '5' ) + { + gm_read_error = "invalid pgm file"; + } + else + { + gm_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; + } + } + + /* forward to data */ + if( bmpinfo.InfoSize != 12 ) /* not old OS/2 format */ + { + TRY( bmp_forward( f, bmpinfo.DataOffset ) ); + } + + /* allocate greymap */ + gm = gm_new( bmpinfo.w, bmpinfo.h ); + if( !gm ) + { + goto std_error; + } + + /* zero it out */ + gm_clear( gm, 0 ); + + switch( bmpinfo.bits + 0x100 * bmpinfo.comp ) + { + default: + goto format_error; + break; + + case 0x001: /* monochrome palette */ + + /* raster data */ + for( y = 0; y> j) ? coltable[1] : coltable[0] ); + } + } + + TRY( bmp_pad( f ) ); + } + + break; + + case 0x002: /* 2-bit to 8-bit palettes */ + case 0x003: + case 0x004: + case 0x005: + case 0x006: + case 0x007: + case 0x008: + for( y = 0; y> (INTBITS - bmpinfo.bits); + bitbuf <<= bmpinfo.bits; + n -= bmpinfo.bits; + GM_UPUT( gm, 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 */ + gm_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); + GM_UPUT( gm, x, y, c / 3 ); + } + + 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; + } + GM_UPUT( gm, x, y, col[i & 1] ); + x++; + } + } + else if( c == 0 ) + { + /* end of line */ + y++; + x = 0; + } + else if( c == 1 ) + { + /* end of greymap */ + 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; + } + GM_PUT( gm, 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; + } + GM_UPUT( gm, x, y, coltable[c] ); + x++; + } + } + else if( c == 0 ) + { + /* end of line */ + y++; + x = 0; + } + else if( c == 1 ) + { + /* end of greymap */ + 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; + } + GM_PUT( gm, 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 ); + *gmp = gm; + return 0; + +eof: + free( coltable ); + *gmp = gm; + return 1; + +format_error: +try_error: + free( coltable ); + free( gm ); + if( !gm_read_error ) + { + gm_read_error = "invalid bmp file"; + } + return -2; + +std_error: + free( coltable ); + free( gm ); + return -1; +} + + +/* ---------------------------------------------------------------------- */ + +/* write a pgm stream, either P2 or (if raw != 0) P5 format. Include + * one-line comment if non-NULL. Mode determines how out-of-range + * color values are converted. Gamma is the desired gamma correction, + * if any (set to 2.2 if the image is to look optimal on a CRT monitor, + * 2.8 for LCD). Set to 1.0 for no gamma correction */ + +int gm_writepgm( FILE* f, greymap_t* gm, char* comment, int raw, int mode, double gamma ) +{ + int x, y, v; + int gammatable[256]; + + /* prepare gamma correction lookup table */ + if( gamma != 1.0 ) + { + gammatable[0] = 0; + for( v = 1; v<256; v++ ) + { + gammatable[v] = (int) ( 255 * exp( log( v / 255.0 ) / gamma ) + 0.5 ); + } + } + else + { + for( v = 0; v<256; v++ ) + { + gammatable[v] = v; + } + } + + fprintf( f, raw ? "P5\n" : "P2\n" ); + if( comment && *comment ) + { + fprintf( f, "# %s\n", comment ); + } + fprintf( f, "%d %d 255\n", gm->w, gm->h ); + for( y = gm->h - 1; y>=0; y-- ) + { + for( x = 0; xw; x++ ) + { + v = GM_UGET( gm, x, y ); + if( mode == GM_MODE_NONZERO ) + { + if( v > 255 ) + { + v = 510 - v; + } + if( v < 0 ) + { + v = 0; + } + } + else if( mode == GM_MODE_ODD ) + { + v = mod( v, 510 ); + if( v > 255 ) + { + v = 510 - v; + } + } + else if( mode == GM_MODE_POSITIVE ) + { + if( v < 0 ) + { + v = 0; + } + else if( v > 255 ) + { + v = 255; + } + } + else if( mode == GM_MODE_NEGATIVE ) + { + v = 510 - v; + if( v < 0 ) + { + v = 0; + } + else if( v > 255 ) + { + v = 255; + } + } + v = gammatable[v]; + + if( raw ) + { + fputc( v, f ); + } + else + { + fprintf( f, x == gm->w - 1 ? "%d\n" : "%d ", v ); + } + } + } + + return 0; +} + + +/* ---------------------------------------------------------------------- */ +/* output - for primitive debugging purposes only! */ + +/* print greymap to screen */ +int gm_print( FILE* f, greymap_t* gm ) +{ + int x, y; + int xx, yy; + int d, t; + int sw, sh; + + sw = gm->w < 79 ? gm->w : 79; + sh = gm->w < 79 ? gm->h : gm->h * sw * 44 / (79 * gm->w); + + for( yy = sh - 1; yy>=0; yy-- ) + { + for( xx = 0; xxw / sw; x<(xx + 1) * gm->w / sw; x++ ) + { + for( y = yy * gm->h / sh; y<(yy + 1) * gm->h / sh; y++ ) + { + d += GM_GET( gm, x, y ); + t += 256; + } + } + + if( t ) + fputc( "*#=- "[5 * d / t], f ); /* what a cute trick :) */ + } + + fputc( '\n', f ); + } + + return 0; +} -- cgit