Update potrace to version 1.15 (that fixes some bugs)
This commit is contained in:
parent
e5847b7953
commit
23d1905c55
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
|
192
potrace/bitmap.h
192
potrace/bitmap.h
|
@ -1,14 +1,14 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* The bitmap type is defined in potracelib.h */
|
||||
#include "potracelib.h"
|
||||
|
@ -45,33 +45,92 @@
|
|||
#define BM_INV( bm, x, y ) ( bm_safe( bm, x, y ) ? BM_UINV( bm, x, y ) : 0 )
|
||||
#define BM_PUT( bm, x, y, b ) ( bm_safe( bm, x, y ) ? BM_UPUT( bm, x, y, b ) : 0 )
|
||||
|
||||
/* calculate the size, in bytes, required for the data area of a
|
||||
* bitmap of the given dy and h. Assume h >= 0. Return -1 if the size
|
||||
* does not fit into the ptrdiff_t type. */
|
||||
static inline ptrdiff_t getsize( int dy, int h )
|
||||
{
|
||||
ptrdiff_t size;
|
||||
|
||||
if( dy < 0 )
|
||||
{
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
size = (ptrdiff_t) dy * (ptrdiff_t) h * (ptrdiff_t) BM_WORDSIZE;
|
||||
|
||||
/* check for overflow error */
|
||||
if( size < 0 || ( h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* return the size, in bytes, of the data area of the bitmap. Return
|
||||
* -1 if the size does not fit into the ptrdiff_t type; however, this
|
||||
* cannot happen if the bitmap is well-formed, i.e., if created with
|
||||
* bm_new or bm_dup. */
|
||||
static inline ptrdiff_t bm_size( const potrace_bitmap_t* bm )
|
||||
{
|
||||
return getsize( bm->dy, bm->h );
|
||||
}
|
||||
|
||||
|
||||
/* calculate the base address of the bitmap data. Assume that the
|
||||
* bitmap is well-formed, i.e., its size fits into the ptrdiff_t type.
|
||||
* This is the case if created with bm_new or bm_dup. The base address
|
||||
* may differ from bm->map if dy is negative */
|
||||
static inline potrace_word* bm_base( const potrace_bitmap_t* bm )
|
||||
{
|
||||
int dy = bm->dy;
|
||||
|
||||
if( dy >= 0 || bm->h == 0 )
|
||||
{
|
||||
return bm->map;
|
||||
}
|
||||
else
|
||||
{
|
||||
return bm_scanline( bm, bm->h - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* free the given bitmap. Leaves errno untouched. */
|
||||
static inline void bm_free( potrace_bitmap_t* bm )
|
||||
{
|
||||
if( bm )
|
||||
if( bm && bm->map )
|
||||
{
|
||||
free( bm->map );
|
||||
free( bm_base( bm ) );
|
||||
}
|
||||
|
||||
free( bm );
|
||||
}
|
||||
|
||||
|
||||
/* return new un-initialized bitmap. NULL with errno on error.
|
||||
/* return new bitmap initialized to 0. NULL with errno on error.
|
||||
* Assumes w, h >= 0. */
|
||||
static inline potrace_bitmap_t* bm_new( int w, int h )
|
||||
{
|
||||
potrace_bitmap_t* bm;
|
||||
int dy = w == 0 ? 0 : ( w - 1 ) / BM_WORDBITS + 1;
|
||||
ptrdiff_t size = (ptrdiff_t) dy * (ptrdiff_t) h * (ptrdiff_t) BM_WORDSIZE;
|
||||
ptrdiff_t size;
|
||||
|
||||
/* check for overflow error */
|
||||
if( size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE) )
|
||||
size = getsize( dy, h );
|
||||
|
||||
if( size < 0 )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( size == 0 )
|
||||
{
|
||||
size = 1; /* make sure calloc() doesn't return NULL */
|
||||
}
|
||||
|
||||
bm = (potrace_bitmap_t*) malloc( sizeof( potrace_bitmap_t ) );
|
||||
|
||||
if( !bm )
|
||||
|
@ -82,7 +141,7 @@ static inline potrace_bitmap_t* bm_new( int w, int h )
|
|||
bm->w = w;
|
||||
bm->h = h;
|
||||
bm->dy = dy;
|
||||
bm->map = (potrace_word*) malloc( size );
|
||||
bm->map = (potrace_word*) calloc( 1, size );
|
||||
|
||||
if( !bm->map )
|
||||
{
|
||||
|
@ -94,29 +153,36 @@ static inline potrace_bitmap_t* bm_new( int w, int h )
|
|||
}
|
||||
|
||||
|
||||
/* clear the given bitmap. Set all bits to c. */
|
||||
/* clear the given bitmap. Set all bits to c. Assumes a well-formed
|
||||
* bitmap. */
|
||||
static inline void bm_clear( potrace_bitmap_t* bm, int c )
|
||||
{
|
||||
/* Note: if the bitmap was created with bm_new, then it is
|
||||
* guaranteed that size will fit into the ptrdiff_t type. */
|
||||
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h * (ptrdiff_t) BM_WORDSIZE;
|
||||
ptrdiff_t size = bm_size( bm );
|
||||
|
||||
memset( bm->map, c ? -1 : 0, size );
|
||||
memset( bm_base( bm ), c ? -1 : 0, size );
|
||||
}
|
||||
|
||||
|
||||
/* duplicate the given bitmap. Return NULL on error with errno set. */
|
||||
/* duplicate the given bitmap. Return NULL on error with errno
|
||||
* set. Assumes a well-formed bitmap. */
|
||||
static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
||||
{
|
||||
potrace_bitmap_t* bm1 = bm_new( bm->w, bm->h );
|
||||
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h * (ptrdiff_t) BM_WORDSIZE;
|
||||
int y;
|
||||
|
||||
if( !bm1 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy( bm1->map, bm->map, size );
|
||||
for( y = 0; y < bm->h; y++ )
|
||||
{
|
||||
memcpy( bm_scanline( bm1, y ), bm_scanline( bm, y ),
|
||||
(size_t) bm1->dy * (size_t) BM_WORDSIZE );
|
||||
}
|
||||
|
||||
return bm1;
|
||||
}
|
||||
|
||||
|
@ -124,13 +190,99 @@ static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
|||
/* invert the given bitmap. */
|
||||
static inline void bm_invert( potrace_bitmap_t* bm )
|
||||
{
|
||||
ptrdiff_t i;
|
||||
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h;
|
||||
int dy = bm->dy;
|
||||
int y;
|
||||
int i;
|
||||
potrace_word* p;
|
||||
|
||||
for( i = 0; i < size; i++ )
|
||||
if( dy < 0 )
|
||||
{
|
||||
bm->map[i] ^= BM_ALLBITS;
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
for( y = 0; y < bm->h; y++ )
|
||||
{
|
||||
p = bm_scanline( bm, y );
|
||||
|
||||
for( i = 0; i < dy; i++ )
|
||||
{
|
||||
p[i] ^= BM_ALLBITS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* turn the given bitmap upside down. This does not move the bitmap
|
||||
* data or change the bm_base() address. */
|
||||
static inline void bm_flip( potrace_bitmap_t* bm )
|
||||
{
|
||||
int dy = bm->dy;
|
||||
|
||||
if( bm->h == 0 || bm->h == 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bm->map = bm_scanline( bm, bm->h - 1 );
|
||||
bm->dy = -dy;
|
||||
}
|
||||
|
||||
|
||||
/* resize the bitmap to the given new height. The bitmap data remains
|
||||
* bottom-aligned (truncated at the top) when dy >= 0 and top-aligned
|
||||
* (truncated at the bottom) when dy < 0. Return 0 on success, or 1 on
|
||||
* error with errno set. If the new height is <= the old one, no error
|
||||
* should occur. If the new height is larger, the additional bitmap
|
||||
* data is *not* initialized. */
|
||||
static inline int bm_resize( potrace_bitmap_t* bm, int h )
|
||||
{
|
||||
int dy = bm->dy;
|
||||
ptrdiff_t newsize;
|
||||
potrace_word* newmap;
|
||||
|
||||
if( dy < 0 )
|
||||
{
|
||||
bm_flip( bm );
|
||||
}
|
||||
|
||||
newsize = getsize( dy, h );
|
||||
|
||||
if( newsize < 0 )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if( newsize == 0 )
|
||||
{
|
||||
newsize = 1; /* make sure realloc() doesn't return NULL */
|
||||
}
|
||||
|
||||
newmap = (potrace_word*) realloc( bm->map, newsize );
|
||||
|
||||
if( newmap == NULL )
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
bm->map = newmap;
|
||||
bm->h = h;
|
||||
|
||||
if( dy < 0 )
|
||||
{
|
||||
bm_flip( bm );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
if( dy < 0 )
|
||||
{
|
||||
bm_flip( bm );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "bitmap_io.h"
|
||||
#include "bitops.h"
|
||||
|
||||
#define INTBITS ( 8 * sizeof( int ) )
|
||||
|
@ -19,6 +20,16 @@
|
|||
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 );
|
||||
|
||||
#define TRY( x ) \
|
||||
if( x ) \
|
||||
goto try_error
|
||||
#define TRY_EOF( x ) \
|
||||
if( x ) \
|
||||
goto eof
|
||||
#define TRY_STD( x ) \
|
||||
if( x ) \
|
||||
goto std_error
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* routines for reading pnm streams */
|
||||
|
||||
|
@ -187,6 +198,8 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
int x, y, i, b, b1, sum;
|
||||
int bpr; /* bytes per row (as opposed to 4*bm->c) */
|
||||
int w, h, max;
|
||||
int realheight; /* in case of incomplete file, keeps track of how
|
||||
* many scan lines actually contain data */
|
||||
|
||||
bm = NULL;
|
||||
|
||||
|
@ -209,11 +222,10 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
|
||||
if( !bm )
|
||||
{
|
||||
return -1;
|
||||
goto std_error;
|
||||
}
|
||||
|
||||
/* zero it out */
|
||||
bm_clear( bm, 0 );
|
||||
realheight = 0;
|
||||
|
||||
switch( magic )
|
||||
{
|
||||
|
@ -224,8 +236,10 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
case '1':
|
||||
/* read P1 format: PBM ascii */
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
b = readbit( f );
|
||||
|
@ -251,8 +265,10 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
b = readnum( f );
|
||||
|
@ -278,8 +294,10 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
sum = 0;
|
||||
|
@ -314,8 +332,10 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
|
||||
bpr = ( w + 7 ) / 8;
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( i = 0; i < bpr; i++ )
|
||||
{
|
||||
b = fgetc( f );
|
||||
|
@ -325,9 +345,8 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
goto eof;
|
||||
}
|
||||
|
||||
*bm_index( bm, i * 8,
|
||||
y ) |= ( (potrace_word) b ) <<
|
||||
( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) );
|
||||
*bm_index( bm, i * 8, y ) |= ( (potrace_word) b )
|
||||
<< ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,8 +369,10 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
b = fgetc( f );
|
||||
|
@ -393,8 +414,10 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
sum = 0;
|
||||
|
@ -429,10 +452,13 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
|||
break;
|
||||
}
|
||||
|
||||
bm_flip( bm );
|
||||
*bmp = bm;
|
||||
return 0;
|
||||
|
||||
eof:
|
||||
TRY_STD( bm_resize( bm, realheight ) );
|
||||
bm_flip( bm );
|
||||
*bmp = bm;
|
||||
return 1;
|
||||
|
||||
|
@ -453,6 +479,10 @@ format_error:
|
|||
}
|
||||
|
||||
return -2;
|
||||
|
||||
std_error:
|
||||
bm_free( bm );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -506,7 +536,7 @@ static int bmp_readint( FILE* f, int n, unsigned int* p )
|
|||
return 1;
|
||||
}
|
||||
|
||||
sum += b << (8 * i);
|
||||
sum += (unsigned) b << ( 8 * i );
|
||||
}
|
||||
|
||||
bmp_count += n;
|
||||
|
@ -569,14 +599,6 @@ static int bmp_forward( FILE* f, int pos )
|
|||
}
|
||||
|
||||
|
||||
#define TRY( x ) if( x ) \
|
||||
goto try_error
|
||||
#define TRY_EOF( x ) if( x ) \
|
||||
goto eof
|
||||
|
||||
/* correct y-coordinate for top-down format */
|
||||
#define ycorr( y ) (bmpinfo.topdown ? bmpinfo.h - 1 - y : y)
|
||||
|
||||
/* safe colortable access */
|
||||
#define COLTABLE( c ) ( ( c ) < bmpinfo.ncolors ? coltable[( c )] : 0 )
|
||||
|
||||
|
@ -601,6 +623,8 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
unsigned int n;
|
||||
unsigned int redshift, greenshift, blueshift;
|
||||
int col1[2];
|
||||
int realheight; /* in case of incomplete file, keeps track of how
|
||||
* many scan lines actually contain data */
|
||||
|
||||
bm_read_error = NULL;
|
||||
bm = NULL;
|
||||
|
@ -616,8 +640,8 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
/* info header */
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.InfoSize ) );
|
||||
|
||||
if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64
|
||||
|| bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124 )
|
||||
if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64 || bmpinfo.InfoSize == 108
|
||||
|| bmpinfo.InfoSize == 124 )
|
||||
{
|
||||
/* Windows or new OS/2 format */
|
||||
bmpinfo.ctbits = 32; /* sample size in color table */
|
||||
|
@ -632,8 +656,9 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
|
||||
|
||||
if( bmpinfo.InfoSize >= 108 ) /* V4 and V5 bitmaps */
|
||||
if( bmpinfo.InfoSize >= 108 )
|
||||
{
|
||||
/* V4 and V5 bitmaps */
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.RedMask ) );
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.GreenMask ) );
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.BlueMask ) );
|
||||
|
@ -697,7 +722,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
goto format_error; /* can't handle planes */
|
||||
}
|
||||
|
||||
if( bmpinfo.ncolors == 0 )
|
||||
if( bmpinfo.ncolors == 0 && bmpinfo.bits <= 8 )
|
||||
{
|
||||
bmpinfo.ncolors = 1 << bmpinfo.bits;
|
||||
}
|
||||
|
@ -728,8 +753,9 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
}
|
||||
|
||||
/* forward to data */
|
||||
if( bmpinfo.InfoSize != 12 ) /* not old OS/2 format */
|
||||
if( bmpinfo.InfoSize != 12 )
|
||||
{
|
||||
/* not old OS/2 format */
|
||||
TRY( bmp_forward( f, bmpinfo.DataOffset ) );
|
||||
}
|
||||
|
||||
|
@ -741,19 +767,18 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
goto std_error;
|
||||
}
|
||||
|
||||
/* zero it out */
|
||||
bm_clear( bm, 0 );
|
||||
realheight = 0;
|
||||
|
||||
switch( bmpinfo.bits + 0x100 * bmpinfo.comp )
|
||||
{
|
||||
default:
|
||||
goto format_error;
|
||||
break;
|
||||
goto format_error; break;
|
||||
|
||||
case 0x001: /* monochrome palette */
|
||||
|
||||
if( col1[0] < col1[1] ) /* make the darker color black */
|
||||
if( col1[0] < col1[1] )
|
||||
{
|
||||
/* make the darker color black */
|
||||
mask = 0xff;
|
||||
}
|
||||
else
|
||||
|
@ -764,15 +789,15 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
/* raster data */
|
||||
for( y = 0; y < bmpinfo.h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
bmp_pad_reset();
|
||||
|
||||
for( i = 0; 8 * i < bmpinfo.w; i++ )
|
||||
{
|
||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||
b ^= mask;
|
||||
*bm_index( bm, i * 8,
|
||||
ycorr( y ) ) |= ( (potrace_word) b ) <<
|
||||
( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) );
|
||||
*bm_index( bm, i * 8, y ) |= ( (potrace_word) b )
|
||||
<< ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) );
|
||||
}
|
||||
|
||||
TRY( bmp_pad( f ) );
|
||||
|
@ -790,6 +815,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
|
||||
for( y = 0; y < bmpinfo.h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
bmp_pad_reset();
|
||||
bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
|
||||
n = 0; /* number of bits currently in bitbuffer */
|
||||
|
@ -806,7 +832,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
b = bitbuf >> ( INTBITS - bmpinfo.bits );
|
||||
bitbuf <<= bmpinfo.bits;
|
||||
n -= bmpinfo.bits;
|
||||
BM_UPUT( bm, x, ycorr( y ), COLTABLE( b ) );
|
||||
BM_UPUT( bm, x, y, COLTABLE( b ) );
|
||||
}
|
||||
|
||||
TRY( bmp_pad( f ) );
|
||||
|
@ -826,13 +852,14 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
|
||||
for( y = 0; y < bmpinfo.h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
bmp_pad_reset();
|
||||
|
||||
for( x = 0; x < bmpinfo.w; x++ )
|
||||
{
|
||||
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
||||
c = ( ( c >> 16 ) & 0xff ) + ( ( c >> 8 ) & 0xff ) + ( c & 0xff );
|
||||
BM_UPUT( bm, x, ycorr( y ), c > 3 * threshold * 255 ? 0 : 1 );
|
||||
BM_UPUT( bm, x, y, c > 3 * threshold * 255 ? 0 : 1 );
|
||||
}
|
||||
|
||||
TRY( bmp_pad( f ) );
|
||||
|
@ -841,21 +868,28 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
break;
|
||||
|
||||
case 0x320: /* 32-bit encoding with bitfields */
|
||||
|
||||
if( bmpinfo.RedMask == 0 || bmpinfo.GreenMask == 0 || bmpinfo.BlueMask == 0 )
|
||||
{
|
||||
goto format_error;
|
||||
}
|
||||
|
||||
redshift = lobit( bmpinfo.RedMask );
|
||||
greenshift = lobit( bmpinfo.GreenMask );
|
||||
blueshift = lobit( bmpinfo.BlueMask );
|
||||
|
||||
for( y = 0; y < bmpinfo.h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
bmp_pad_reset();
|
||||
|
||||
for( x = 0; x < bmpinfo.w; x++ )
|
||||
{
|
||||
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
||||
c = ( (c & bmpinfo.RedMask) >> redshift ) +
|
||||
( (c & bmpinfo.GreenMask) >> greenshift ) +
|
||||
( (c & bmpinfo.BlueMask) >> blueshift );
|
||||
BM_UPUT( bm, x, ycorr( y ), c > 3 * threshold * 255 ? 0 : 1 );
|
||||
c = ( ( c & bmpinfo.RedMask ) >> redshift )
|
||||
+ ( ( c & bmpinfo.GreenMask ) >> greenshift )
|
||||
+ ( ( c & bmpinfo.BlueMask ) >> blueshift );
|
||||
BM_UPUT( bm, x, y, c > 3 * threshold * 255 ? 0 : 1 );
|
||||
}
|
||||
|
||||
TRY( bmp_pad( f ) );
|
||||
|
@ -886,12 +920,13 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
y++;
|
||||
}
|
||||
|
||||
if( y>=bmpinfo.h )
|
||||
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
BM_UPUT( bm, x, ycorr( y ), col[i & 1] );
|
||||
realheight = y + 1;
|
||||
BM_PUT( bm, x, y, col[i & 1] );
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
@ -930,12 +965,13 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
y++;
|
||||
}
|
||||
|
||||
if( y>=bmpinfo.h )
|
||||
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
BM_PUT( bm, x, ycorr( y ), COLTABLE( ( b >> ( 4 - 4 * (i & 1) ) ) & 0xf ) );
|
||||
realheight = y + 1;
|
||||
BM_PUT( bm, x, y, COLTABLE( ( b >> ( 4 - 4 * ( i & 1 ) ) ) & 0xf ) );
|
||||
x++;
|
||||
}
|
||||
|
||||
|
@ -969,12 +1005,13 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
y++;
|
||||
}
|
||||
|
||||
if( y>=bmpinfo.h )
|
||||
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
BM_UPUT( bm, x, ycorr( y ), COLTABLE( c ) );
|
||||
realheight = y + 1;
|
||||
BM_PUT( bm, x, y, COLTABLE( c ) );
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
@ -1010,12 +1047,13 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
y++;
|
||||
}
|
||||
|
||||
if( y>=bmpinfo.h )
|
||||
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
BM_PUT( bm, x, ycorr( y ), COLTABLE( b ) );
|
||||
realheight = y + 1;
|
||||
BM_PUT( bm, x, y, COLTABLE( b ) );
|
||||
x++;
|
||||
}
|
||||
|
||||
|
@ -1035,11 +1073,24 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
|||
bmp_forward( f, bmpinfo.FileSize );
|
||||
|
||||
free( coltable );
|
||||
|
||||
if( bmpinfo.topdown )
|
||||
{
|
||||
bm_flip( bm );
|
||||
}
|
||||
|
||||
*bmp = bm;
|
||||
return 0;
|
||||
|
||||
eof:
|
||||
TRY_STD( bm_resize( bm, realheight ) );
|
||||
free( coltable );
|
||||
|
||||
if( bmpinfo.topdown )
|
||||
{
|
||||
bm_flip( bm );
|
||||
}
|
||||
|
||||
*bmp = bm;
|
||||
return 1;
|
||||
|
||||
|
@ -1080,9 +1131,8 @@ void bm_writepbm( FILE* f, potrace_bitmap_t* bm )
|
|||
{
|
||||
for( i = 0; i < bpr; i++ )
|
||||
{
|
||||
c =
|
||||
( *bm_index( bm, i * 8,
|
||||
y ) >> ( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) ) ) & 0xff;
|
||||
c = ( *bm_index( bm, i * 8, y ) >> ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) ) )
|
||||
& 0xff;
|
||||
fputc( c, f );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
|||
#ifndef BITMAP_IO_H
|
||||
#define BITMAP_IO_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bitmap.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* Note that bitmaps are stored bottom to top, i.e., the first
|
||||
* scanline is the bottom-most one */
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
||||
/* bits.h: this file defines some macros for bit manipulations. We
|
||||
* provide a generic implementation, as well as machine- and
|
||||
* compiler-specific fast implementations */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -12,9 +12,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "potracelib.h"
|
||||
#include "lists.h"
|
||||
#include "curve.h"
|
||||
#include "lists.h"
|
||||
#include "potracelib.h"
|
||||
|
||||
#define SAFE_CALLOC( var, n, typ ) \
|
||||
if( ( var = (typ*) calloc( n, sizeof( typ ) ) ) == NULL ) \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -6,16 +6,21 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include "potracelib.h"
|
||||
#include "curve.h"
|
||||
#include "lists.h"
|
||||
#include "bitmap.h"
|
||||
#include "curve.h"
|
||||
#include "decompose.h"
|
||||
#include "lists.h"
|
||||
#include "potracelib.h"
|
||||
#include "progress.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -28,17 +33,16 @@ static inline int detrand( int x, int y )
|
|||
{
|
||||
/* non-linear sequence: constant term of inverse in GF(8),
|
||||
* mod x^8+x^4+x^3+x+1 */
|
||||
0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
|
||||
0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
|
||||
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
|
||||
1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
|
||||
0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
|
||||
1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0,
|
||||
1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1,
|
||||
1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
|
||||
1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0,
|
||||
1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
|
||||
0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1, 0,
|
||||
};
|
||||
|
||||
/* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
|
||||
|
@ -103,8 +107,9 @@ static int majority( potrace_bitmap_t* bm, int x, int y )
|
|||
{
|
||||
int i, a, ct;
|
||||
|
||||
for( i = 2; i<5; i++ ) /* check at "radius" i */
|
||||
for( i = 2; i < 5; i++ )
|
||||
{
|
||||
/* check at "radius" i */
|
||||
ct = 0;
|
||||
|
||||
for( a = -i + 1; a <= i - 1; a++ )
|
||||
|
@ -176,8 +181,9 @@ static void xor_path( potrace_bitmap_t* bm, path_t* p )
|
|||
{
|
||||
int xa, x, y, k, y1;
|
||||
|
||||
if( p->priv->len <= 0 ) /* a path of length 0 is silly, but legal */
|
||||
if( p->priv->len <= 0 )
|
||||
{
|
||||
/* a path of length 0 is silly, but legal */
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -248,7 +254,8 @@ static void setbbox_path( bbox_t* bbox, path_t* p )
|
|||
* of turnpolicies. */
|
||||
static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int turnpolicy )
|
||||
{
|
||||
int x, y, dirx, diry, len, size, area;
|
||||
int x, y, dirx, diry, len, size;
|
||||
uint64_t area;
|
||||
int c, d, tmp;
|
||||
point_t* pt, * pt1;
|
||||
path_t* p = NULL;
|
||||
|
@ -298,8 +305,9 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
|||
c = BM_GET( bm, x + ( dirx + diry - 1 ) / 2, y + ( diry - dirx - 1 ) / 2 );
|
||||
d = BM_GET( bm, x + ( dirx - diry - 1 ) / 2, y + ( diry + dirx - 1 ) / 2 );
|
||||
|
||||
if( c && !d ) /* ambiguous turn */
|
||||
if( c && !d )
|
||||
{
|
||||
/* ambiguous turn */
|
||||
if( turnpolicy == POTRACE_TURNPOLICY_RIGHT
|
||||
|| ( turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+' )
|
||||
|| ( turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-' )
|
||||
|
@ -318,14 +326,16 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
|||
diry = tmp;
|
||||
}
|
||||
}
|
||||
else if( c ) /* right turn */
|
||||
else if( c )
|
||||
{
|
||||
/* right turn */
|
||||
tmp = dirx;
|
||||
dirx = diry;
|
||||
diry = -tmp;
|
||||
}
|
||||
else if( !d ) /* left turn */
|
||||
else if( !d )
|
||||
{
|
||||
/* left turn */
|
||||
tmp = dirx;
|
||||
dirx = -diry;
|
||||
diry = tmp;
|
||||
|
@ -342,7 +352,7 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
|||
|
||||
p->priv->pt = pt;
|
||||
p->priv->len = len;
|
||||
p->area = area;
|
||||
p->area = area <= INT_MAX ? area : INT_MAX; /* avoid overflow */
|
||||
p->sign = sign;
|
||||
|
||||
return p;
|
||||
|
@ -523,7 +533,7 @@ static int findnext( potrace_bitmap_t* bm, int* xp, int* yp )
|
|||
|
||||
for( y = *yp; y >= 0; y-- )
|
||||
{
|
||||
for( x = x0; x<bm->w; x += BM_WORDBITS )
|
||||
for( x = x0; x < bm->w && x >= 0; x += (unsigned) BM_WORDBITS )
|
||||
{
|
||||
if( *bm_index( bm, x, y ) )
|
||||
{
|
||||
|
@ -552,9 +562,7 @@ static int findnext( potrace_bitmap_t* bm, int* xp, int* yp )
|
|||
* in. Returns 0 on success with plistp set, or -1 on error with errno
|
||||
* set. */
|
||||
|
||||
int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||
path_t** plistp,
|
||||
const potrace_param_t* param,
|
||||
int bm_to_pathlist( const potrace_bitmap_t* bm, path_t** plistp, const potrace_param_t* param,
|
||||
progress_t* progress )
|
||||
{
|
||||
int x;
|
||||
|
@ -606,8 +614,9 @@ int bm_to_pathlist( const potrace_bitmap_t* bm,
|
|||
list_insert_beforehook( p, plist_hook );
|
||||
}
|
||||
|
||||
if( bm1->h > 0 ) /* to be sure */
|
||||
if( bm1->h > 0 )
|
||||
{
|
||||
/* to be sure */
|
||||
progress_update( 1 - y / (double) bm1->h, progress );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
||||
#ifndef DECOMPOSE_H
|
||||
#define DECOMPOSE_H
|
||||
|
||||
#include "curve.h"
|
||||
#include "potracelib.h"
|
||||
#include "progress.h"
|
||||
#include "curve.h"
|
||||
|
||||
int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||
path_t** plistp,
|
||||
const potrace_param_t* param,
|
||||
int bm_to_pathlist( const potrace_bitmap_t* bm, path_t** plistp, const potrace_param_t* param,
|
||||
progress_t* progress );
|
||||
|
||||
#endif /* DECOMPOSE_H */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -10,39 +10,91 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "greymap.h"
|
||||
#include "bitops.h"
|
||||
#include "greymap.h"
|
||||
|
||||
#define INTBITS ( 8 * sizeof( int ) )
|
||||
|
||||
#define mod( a, n ) ( (a)>=(n) ? (a) % (n) : (a)>=0 ? (a) : (n) - 1 - ( -1 - (a) ) % (n) )
|
||||
#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 );
|
||||
|
||||
#define TRY( x ) \
|
||||
if( x ) \
|
||||
goto try_error
|
||||
#define TRY_EOF( x ) \
|
||||
if( x ) \
|
||||
goto eof
|
||||
#define TRY_STD( x ) \
|
||||
if( x ) \
|
||||
goto std_error
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* basic greymap routines */
|
||||
|
||||
/* return new un-initialized greymap. NULL with errno on error.
|
||||
/* calculate the size, in bytes, required for the data area of a
|
||||
* greymap of the given dy and h. Assume h >= 0. Return -1 if the size
|
||||
* does not fit into the ptrdiff_t type. */
|
||||
static inline ptrdiff_t getsize( int dy, int h )
|
||||
{
|
||||
ptrdiff_t size;
|
||||
|
||||
if( dy < 0 )
|
||||
{
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
size = (ptrdiff_t) dy * (ptrdiff_t) h * (ptrdiff_t) sizeof( gm_sample_t );
|
||||
|
||||
/* check for overflow error */
|
||||
if( size < 0 || ( h != 0 && dy != 0 && size / h / dy != sizeof( gm_sample_t ) ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* return the size, in bytes, of the data area of the greymap. Return
|
||||
* -1 if the size does not fit into the ptrdiff_t type; however, this
|
||||
* cannot happen if the bitmap is well-formed, i.e., if created with
|
||||
* gm_new or gm_dup. */
|
||||
static inline ptrdiff_t gm_size( const greymap_t* gm )
|
||||
{
|
||||
return getsize( gm->dy, gm->h );
|
||||
}
|
||||
|
||||
|
||||
/* return new greymap initialized to 0. NULL with errno on error.
|
||||
* Assumes w, h >= 0. */
|
||||
greymap_t* gm_new( int w, int h )
|
||||
{
|
||||
greymap_t* gm;
|
||||
ptrdiff_t size = (ptrdiff_t) w * (ptrdiff_t) h * (ptrdiff_t) sizeof(signed short int);
|
||||
int dy = w;
|
||||
ptrdiff_t size;
|
||||
|
||||
/* check for overflow error */
|
||||
if( size < 0 || size / w / h != sizeof(signed short int) )
|
||||
size = getsize( dy, h );
|
||||
|
||||
if( size < 0 )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( size == 0 )
|
||||
{
|
||||
size = 1; /* make surecmalloc() doesn't return NULL */
|
||||
}
|
||||
|
||||
gm = (greymap_t*) malloc( sizeof( greymap_t ) );
|
||||
|
||||
if( !gm )
|
||||
|
@ -52,14 +104,16 @@ greymap_t* gm_new( int w, int h )
|
|||
|
||||
gm->w = w;
|
||||
gm->h = h;
|
||||
gm->map = (signed short int*) malloc( size );
|
||||
gm->dy = dy;
|
||||
gm->base = (gm_sample_t*) calloc( 1, size );
|
||||
|
||||
if( !gm->map )
|
||||
if( !gm->base )
|
||||
{
|
||||
free( gm );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gm->map = gm->base;
|
||||
return gm;
|
||||
}
|
||||
|
||||
|
@ -69,7 +123,7 @@ void gm_free( greymap_t* gm )
|
|||
{
|
||||
if( gm )
|
||||
{
|
||||
free( gm->map );
|
||||
free( gm->base );
|
||||
}
|
||||
|
||||
free( gm );
|
||||
|
@ -80,13 +134,19 @@ void gm_free( greymap_t* gm )
|
|||
greymap_t* gm_dup( greymap_t* gm )
|
||||
{
|
||||
greymap_t* gm1 = gm_new( gm->w, gm->h );
|
||||
int y;
|
||||
|
||||
if( !gm1 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy( gm1->map, gm->map, gm->w * gm->h * sizeof(signed short int) );
|
||||
for( y = 0; y < gm->h; y++ )
|
||||
{
|
||||
memcpy( gm_scanline( gm1, y ), gm_scanline( gm, y ),
|
||||
(size_t) gm1->dy * sizeof( gm_sample_t ) );
|
||||
}
|
||||
|
||||
return gm1;
|
||||
}
|
||||
|
||||
|
@ -94,20 +154,99 @@ greymap_t* gm_dup( greymap_t* gm )
|
|||
/* clear the given greymap to color b. */
|
||||
void gm_clear( greymap_t* gm, int b )
|
||||
{
|
||||
int i;
|
||||
ptrdiff_t size = gm_size( gm );
|
||||
int x, y;
|
||||
|
||||
if( b == 0 )
|
||||
{
|
||||
memset( gm->map, 0, gm->w * gm->h * sizeof(signed short int) );
|
||||
memset( gm->base, 0, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i<gm->w * gm->h; i++ )
|
||||
for( y = 0; y < gm->h; y++ )
|
||||
{
|
||||
gm->map[i] = b;
|
||||
for( x = 0; x < gm->w; x++ )
|
||||
{
|
||||
GM_UPUT( gm, x, y, b );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* turn the given greymap upside down. This does not move the pixel
|
||||
* data or change the base address. */
|
||||
static inline void gm_flip( greymap_t* gm )
|
||||
{
|
||||
int dy = gm->dy;
|
||||
|
||||
if( gm->h == 0 || gm->h == 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gm->map = gm_scanline( gm, gm->h - 1 );
|
||||
gm->dy = -dy;
|
||||
}
|
||||
|
||||
|
||||
/* resize the greymap to the given new height. The pixel data remains
|
||||
* bottom-aligned (truncated at the top) when dy >= 0 and top-aligned
|
||||
* (truncated at the bottom) when dy < 0. Return 0 on success, or 1 on
|
||||
* error with errno set. If the new height is <= the old one, no error
|
||||
* should occur. If the new height is larger, the additional pixel
|
||||
* data is *not* initialized. */
|
||||
static inline int gm_resize( greymap_t* gm, int h )
|
||||
{
|
||||
int dy = gm->dy;
|
||||
ptrdiff_t newsize;
|
||||
gm_sample_t* newbase;
|
||||
|
||||
if( dy < 0 )
|
||||
{
|
||||
gm_flip( gm );
|
||||
}
|
||||
|
||||
newsize = getsize( dy, h );
|
||||
|
||||
if( newsize < 0 )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if( newsize == 0 )
|
||||
{
|
||||
newsize = 1; /* make sure realloc() doesn't return NULL */
|
||||
}
|
||||
|
||||
newbase = (gm_sample_t*) realloc( gm->base, newsize );
|
||||
|
||||
if( newbase == NULL )
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
gm->base = newbase;
|
||||
gm->map = newbase;
|
||||
gm->h = h;
|
||||
|
||||
if( dy < 0 )
|
||||
{
|
||||
gm_flip( gm );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
if( dy < 0 )
|
||||
{
|
||||
gm_flip( gm );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -279,6 +418,8 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
int x, y, i, j, b, b1, sum;
|
||||
int bpr; /* bytes per row (as opposed to 4*gm->c) */
|
||||
int w, h, max;
|
||||
int realheight; /* in case of incomplete file, keeps track of how
|
||||
* many scan lines actually contain data */
|
||||
|
||||
gm = NULL;
|
||||
|
||||
|
@ -301,11 +442,10 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
|
||||
if( !gm )
|
||||
{
|
||||
return -1;
|
||||
goto std_error;
|
||||
}
|
||||
|
||||
/* zero it out */
|
||||
gm_clear( gm, 0 );
|
||||
realheight = 0;
|
||||
|
||||
switch( magic )
|
||||
{
|
||||
|
@ -316,8 +456,10 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
case '1':
|
||||
/* read P1 format: PBM ascii */
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
b = readbit( f );
|
||||
|
@ -343,8 +485,10 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
b = readnum( f );
|
||||
|
@ -370,8 +514,10 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
sum = 0;
|
||||
|
@ -406,8 +552,10 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
|
||||
bpr = ( w + 7 ) / 8;
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( i = 0; i < bpr; i++ )
|
||||
{
|
||||
b = fgetc( f );
|
||||
|
@ -443,8 +591,10 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
b = fgetc( f );
|
||||
|
@ -486,8 +636,10 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
for( y = h - 1; y>=0; y-- )
|
||||
for( y = 0; y < h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
|
||||
for( x = 0; x < w; x++ )
|
||||
{
|
||||
sum = 0;
|
||||
|
@ -522,10 +674,13 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
|||
break;
|
||||
}
|
||||
|
||||
gm_flip( gm );
|
||||
*gmp = gm;
|
||||
return 0;
|
||||
|
||||
eof:
|
||||
TRY_STD( gm_resize( gm, realheight ) );
|
||||
gm_flip( gm );
|
||||
*gmp = gm;
|
||||
return 1;
|
||||
|
||||
|
@ -546,6 +701,10 @@ format_error:
|
|||
}
|
||||
|
||||
return -2;
|
||||
|
||||
std_error:
|
||||
gm_free( gm );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -599,7 +758,7 @@ static int bmp_readint( FILE* f, int n, unsigned int* p )
|
|||
return 1;
|
||||
}
|
||||
|
||||
sum += b << (8 * i);
|
||||
sum += (unsigned) b << ( 8 * i );
|
||||
}
|
||||
|
||||
bmp_count += n;
|
||||
|
@ -662,13 +821,8 @@ static int bmp_forward( FILE* f, int pos )
|
|||
}
|
||||
|
||||
|
||||
#define TRY( x ) if( x ) \
|
||||
goto try_error
|
||||
#define TRY_EOF( x ) if( x ) \
|
||||
goto eof
|
||||
|
||||
/* correct y-coordinate for top-down format */
|
||||
#define ycorr( y ) (bmpinfo.topdown ? bmpinfo.h - 1 - y : y)
|
||||
/* safe colortable access */
|
||||
#define COLTABLE( c ) ( ( c ) < bmpinfo.ncolors ? coltable[( c )] : 0 )
|
||||
|
||||
/* read BMP stream after magic number. Return values as for gm_read.
|
||||
* We choose to be as permissive as possible, since there are many
|
||||
|
@ -689,6 +843,8 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
unsigned int bitbuf;
|
||||
unsigned int n;
|
||||
unsigned int redshift, greenshift, blueshift;
|
||||
int realheight; /* in case of incomplete file, keeps track of how
|
||||
* many scan lines actually contain data */
|
||||
|
||||
gm_read_error = NULL;
|
||||
gm = NULL;
|
||||
|
@ -704,8 +860,8 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
/* info header */
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.InfoSize ) );
|
||||
|
||||
if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64
|
||||
|| bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124 )
|
||||
if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64 || bmpinfo.InfoSize == 108
|
||||
|| bmpinfo.InfoSize == 124 )
|
||||
{
|
||||
/* Windows or new OS/2 format */
|
||||
bmpinfo.ctbits = 32; /* sample size in color table */
|
||||
|
@ -720,8 +876,9 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
|
||||
|
||||
if( bmpinfo.InfoSize >= 108 ) /* V4 and V5 bitmaps */
|
||||
if( bmpinfo.InfoSize >= 108 )
|
||||
{
|
||||
/* V4 and V5 bitmaps */
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.RedMask ) );
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.GreenMask ) );
|
||||
TRY( bmp_readint( f, 4, &bmpinfo.BlueMask ) );
|
||||
|
@ -771,6 +928,11 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
goto format_error;
|
||||
}
|
||||
|
||||
if( bmpinfo.comp > 3 || bmpinfo.bits > 32 )
|
||||
{
|
||||
goto format_error;
|
||||
}
|
||||
|
||||
/* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
|
||||
TRY( bmp_forward( f, 14 + bmpinfo.InfoSize ) );
|
||||
|
||||
|
@ -780,7 +942,7 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
goto format_error; /* can't handle planes */
|
||||
}
|
||||
|
||||
if( bmpinfo.ncolors == 0 )
|
||||
if( bmpinfo.ncolors == 0 && bmpinfo.bits <= 8 )
|
||||
{
|
||||
bmpinfo.ncolors = 1 << bmpinfo.bits;
|
||||
}
|
||||
|
@ -806,8 +968,9 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
}
|
||||
|
||||
/* forward to data */
|
||||
if( bmpinfo.InfoSize != 12 ) /* not old OS/2 format */
|
||||
if( bmpinfo.InfoSize != 12 )
|
||||
{
|
||||
/* not old OS/2 format */
|
||||
TRY( bmp_forward( f, bmpinfo.DataOffset ) );
|
||||
}
|
||||
|
||||
|
@ -819,20 +982,19 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
goto std_error;
|
||||
}
|
||||
|
||||
/* zero it out */
|
||||
gm_clear( gm, 0 );
|
||||
realheight = 0;
|
||||
|
||||
switch( bmpinfo.bits + 0x100 * bmpinfo.comp )
|
||||
{
|
||||
default:
|
||||
goto format_error;
|
||||
break;
|
||||
goto format_error; break;
|
||||
|
||||
case 0x001: /* monochrome palette */
|
||||
|
||||
/* raster data */
|
||||
for( y = 0; y < bmpinfo.h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
bmp_pad_reset();
|
||||
|
||||
for( i = 0; 8 * i < bmpinfo.w; i++ )
|
||||
|
@ -841,8 +1003,7 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
|
||||
for( j = 0; j < 8; j++ )
|
||||
{
|
||||
GM_PUT( gm, i * 8 + j, ycorr( y ),
|
||||
b & (0x80 >> j) ? coltable[1] : coltable[0] );
|
||||
GM_PUT( gm, i * 8 + j, y, b & ( 0x80 >> j ) ? COLTABLE( 1 ) : COLTABLE( 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -861,6 +1022,7 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
|
||||
for( y = 0; y < bmpinfo.h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
bmp_pad_reset();
|
||||
bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
|
||||
n = 0; /* number of bits currently in bitbuffer */
|
||||
|
@ -877,7 +1039,7 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
b = bitbuf >> ( INTBITS - bmpinfo.bits );
|
||||
bitbuf <<= bmpinfo.bits;
|
||||
n -= bmpinfo.bits;
|
||||
GM_UPUT( gm, x, ycorr( y ), coltable[b] );
|
||||
GM_UPUT( gm, x, y, COLTABLE( b ) );
|
||||
}
|
||||
|
||||
TRY( bmp_pad( f ) );
|
||||
|
@ -897,13 +1059,14 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
|
||||
for( y = 0; y < bmpinfo.h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
bmp_pad_reset();
|
||||
|
||||
for( x = 0; x < bmpinfo.w; x++ )
|
||||
{
|
||||
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
||||
c = ( ( c >> 16 ) & 0xff ) + ( ( c >> 8 ) & 0xff ) + ( c & 0xff );
|
||||
GM_UPUT( gm, x, ycorr( y ), c / 3 );
|
||||
GM_UPUT( gm, x, y, c / 3 );
|
||||
}
|
||||
|
||||
TRY( bmp_pad( f ) );
|
||||
|
@ -918,15 +1081,16 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
|
||||
for( y = 0; y < bmpinfo.h; y++ )
|
||||
{
|
||||
realheight = y + 1;
|
||||
bmp_pad_reset();
|
||||
|
||||
for( x = 0; x < bmpinfo.w; x++ )
|
||||
{
|
||||
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
||||
c = ( (c & bmpinfo.RedMask) >> redshift ) +
|
||||
( (c & bmpinfo.GreenMask) >> greenshift ) +
|
||||
( (c & bmpinfo.BlueMask) >> blueshift );
|
||||
GM_UPUT( gm, x, ycorr( y ), c / 3 );
|
||||
c = ( ( c & bmpinfo.RedMask ) >> redshift )
|
||||
+ ( ( c & bmpinfo.GreenMask ) >> greenshift )
|
||||
+ ( ( c & bmpinfo.BlueMask ) >> blueshift );
|
||||
GM_UPUT( gm, x, y, c / 3 );
|
||||
}
|
||||
|
||||
TRY( bmp_pad( f ) );
|
||||
|
@ -946,8 +1110,8 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
if( b > 0 )
|
||||
{
|
||||
/* repeat count */
|
||||
col[0] = coltable[(c >> 4) & 0xf];
|
||||
col[1] = coltable[c & 0xf];
|
||||
col[0] = COLTABLE( ( c >> 4 ) & 0xf );
|
||||
col[1] = COLTABLE( c & 0xf );
|
||||
|
||||
for( i = 0; i < b && x < bmpinfo.w; i++ )
|
||||
{
|
||||
|
@ -957,12 +1121,13 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
y++;
|
||||
}
|
||||
|
||||
if( y>=bmpinfo.h )
|
||||
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
GM_UPUT( gm, x, ycorr( y ), col[i & 1] );
|
||||
realheight = y + 1;
|
||||
GM_PUT( gm, x, y, col[i & 1] );
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
@ -1001,12 +1166,13 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
y++;
|
||||
}
|
||||
|
||||
if( y>=bmpinfo.h )
|
||||
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
GM_PUT( gm, x, ycorr( y ), coltable[( b >> ( 4 - 4 * (i & 1) ) ) & 0xf] );
|
||||
realheight = y + 1;
|
||||
GM_PUT( gm, x, y, COLTABLE( ( b >> ( 4 - 4 * ( i & 1 ) ) ) & 0xf ) );
|
||||
x++;
|
||||
}
|
||||
|
||||
|
@ -1040,12 +1206,13 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
y++;
|
||||
}
|
||||
|
||||
if( y>=bmpinfo.h )
|
||||
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
GM_UPUT( gm, x, ycorr( y ), coltable[c] );
|
||||
realheight = y + 1;
|
||||
GM_PUT( gm, x, y, COLTABLE( c ) );
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
@ -1081,12 +1248,13 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
y++;
|
||||
}
|
||||
|
||||
if( y>=bmpinfo.h )
|
||||
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
GM_PUT( gm, x, ycorr( y ), coltable[b] );
|
||||
realheight = y + 1;
|
||||
GM_PUT( gm, x, y, COLTABLE( b ) );
|
||||
x++;
|
||||
}
|
||||
|
||||
|
@ -1106,18 +1274,31 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
|||
bmp_forward( f, bmpinfo.FileSize );
|
||||
|
||||
free( coltable );
|
||||
|
||||
if( bmpinfo.topdown )
|
||||
{
|
||||
gm_flip( gm );
|
||||
}
|
||||
|
||||
*gmp = gm;
|
||||
return 0;
|
||||
|
||||
eof:
|
||||
TRY_STD( gm_resize( gm, realheight ) );
|
||||
free( coltable );
|
||||
|
||||
if( bmpinfo.topdown )
|
||||
{
|
||||
gm_flip( gm );
|
||||
}
|
||||
|
||||
*gmp = gm;
|
||||
return 1;
|
||||
|
||||
format_error:
|
||||
try_error:
|
||||
free( coltable );
|
||||
free( gm );
|
||||
gm_free( gm );
|
||||
|
||||
if( !gm_read_error )
|
||||
{
|
||||
|
@ -1128,7 +1309,7 @@ try_error:
|
|||
|
||||
std_error:
|
||||
free( coltable );
|
||||
free( gm );
|
||||
gm_free( gm );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1141,7 +1322,7 @@ std_error:
|
|||
* 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 gm_writepgm( FILE* f, greymap_t* gm, const char* comment, int raw, int mode, double gamma )
|
||||
{
|
||||
int x, y, v;
|
||||
int gammatable[256];
|
||||
|
|
|
@ -1,44 +1,50 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
||||
#ifndef GREYMAP_H
|
||||
#define GREYMAP_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* type for greymap samples */
|
||||
typedef signed short int gm_sample_t;
|
||||
|
||||
/* internal format for greymaps. Note: in this format, rows are
|
||||
* ordered from bottom to top. The pixels in each row are given from
|
||||
* left to right. */
|
||||
|
||||
struct greymap_s
|
||||
{
|
||||
int w; /* width, in pixels */
|
||||
int h; /* height, in pixels */
|
||||
signed short int* map; /* raw data, w*h values */
|
||||
int dy; /* offset between scanlines (in samples);
|
||||
* can be negative */
|
||||
gm_sample_t* base; /* root of allocated data */
|
||||
gm_sample_t* map; /* points to the lower left pixel */
|
||||
};
|
||||
typedef struct greymap_s greymap_t;
|
||||
|
||||
/* macros for accessing pixel at index (x,y). Note that the origin is
|
||||
* in the *lower* left corner. U* macros omit the bounds check. */
|
||||
|
||||
#define gm_index( gm, x, y ) (&(gm)->map[(x) + (y) * (ptrdiff_t) (gm)->w])
|
||||
#define gm_safe( gm, x, \
|
||||
y ) ( (int) (x)>=0 && (int) (x)<(gm)->w && (int) (y)>=0 \
|
||||
&& (int) (y)<(gm)->h )
|
||||
#define gm_scanline( gm, y ) ( ( gm )->map + (ptrdiff_t) ( y ) * (ptrdiff_t) ( gm )->dy )
|
||||
#define gm_index( gm, x, y ) ( gm_scanline( gm, y ) + ( x ) )
|
||||
#define gm_safe( gm, x, y ) \
|
||||
( (int) ( x ) >= 0 && (int) ( x ) < ( gm )->w && (int) ( y ) >= 0 && (int) ( y ) < ( gm )->h )
|
||||
#define gm_bound( x, m ) ( ( x ) < 0 ? 0 : ( x ) >= ( m ) ? (m) - 1 : ( x ) )
|
||||
#define GM_UGET( gm, x, y ) ( *gm_index( gm, x, y ) )
|
||||
#define GM_UINC( gm, x, y, b ) ( *gm_index( gm, x, y ) += (short int) (b) )
|
||||
#define GM_UINC( gm, x, y, b ) ( *gm_index( gm, x, y ) += (gm_sample_t) ( b ) )
|
||||
#define GM_UINV( gm, x, y ) ( *gm_index( gm, x, y ) = 255 - *gm_index( gm, x, y ) )
|
||||
#define GM_UPUT( gm, x, y, b ) ( *gm_index( gm, x, y ) = (short int) (b) )
|
||||
#define GM_UPUT( gm, x, y, b ) ( *gm_index( gm, x, y ) = (gm_sample_t) ( b ) )
|
||||
#define GM_GET( gm, x, y ) ( gm_safe( gm, x, y ) ? GM_UGET( gm, x, y ) : 0 )
|
||||
#define GM_INC( gm, x, y, b ) ( gm_safe( gm, x, y ) ? GM_UINC( gm, x, y, b ) : 0 )
|
||||
#define GM_INV( gm, x, y ) ( gm_safe( gm, x, y ) ? GM_UINV( gm, x, y ) : 0 )
|
||||
#define GM_PUT( gm, x, y, b ) ( gm_safe( gm, x, y ) ? GM_UPUT( gm, x, y, b ) : 0 )
|
||||
#define GM_BGET( gm, x, y ) GM_UGET( gm, gm_bound( x, gm->w ), gm_bound( y, gm->h ) )
|
||||
#define GM_BGET( gm, x, y ) \
|
||||
( ( gm )->w == 0 || ( gm )->h == 0 ? 0 : GM_UGET( gm, gm_bound( x, ( gm )->w ), \
|
||||
gm_bound( y, ( gm )->h ) ) )
|
||||
|
||||
/* modes for cutting off out-of-range values. The following names
|
||||
* refer to winding numbers. I.e., make a pixel black if winding
|
||||
|
@ -56,7 +62,12 @@ greymap_t* gm_dup( greymap_t* gm );
|
|||
void gm_free( greymap_t* gm );
|
||||
void gm_clear( greymap_t* gm, int b );
|
||||
int gm_read( FILE* f, greymap_t** gmp );
|
||||
int gm_writepgm( FILE* f, greymap_t* gm, char* comment, int raw, int mode, double gamma );
|
||||
int gm_writepgm( FILE* f,
|
||||
greymap_t* gm,
|
||||
const char* comment,
|
||||
int raw,
|
||||
int mode,
|
||||
double gamma );
|
||||
int gm_print( FILE* f, greymap_t* gm );
|
||||
|
||||
#endif /* GREYMAP_H */
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
||||
#ifndef _PS_LISTS_H
|
||||
#define _PS_LISTS_H
|
||||
|
||||
|
@ -31,8 +30,11 @@
|
|||
* such as "if (...) macro(...); else ...". If we didn't use this obscure
|
||||
* trick, we'd have to omit the ";" in such cases. */
|
||||
|
||||
#define MACRO_BEGIN do {
|
||||
#define MACRO_END } \
|
||||
#define MACRO_BEGIN \
|
||||
do \
|
||||
{
|
||||
#define MACRO_END \
|
||||
} \
|
||||
while( 0 )
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -59,8 +61,7 @@
|
|||
MACRO_END
|
||||
|
||||
/* same, except only use hook. */
|
||||
#define _list_forall_hook( list, hook ) \
|
||||
for( hook = &list; *hook!=NULL; hook = &(*hook)->next )
|
||||
#define _list_forall_hook( list, hook ) for( hook = &list; *hook != NULL; hook = &( *hook )->next )
|
||||
|
||||
/* same, except only use hook. Note: c may only refer to *hook, not elt. */
|
||||
#define _list_find_hook( list, c, hook ) \
|
||||
|
@ -70,17 +71,27 @@
|
|||
|
||||
/* insert element after hook */
|
||||
#define list_insert_athook( elt, hook ) \
|
||||
MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END
|
||||
MACRO_BEGIN elt->next = *hook; \
|
||||
*hook = elt; \
|
||||
MACRO_END
|
||||
|
||||
/* insert element before hook */
|
||||
#define list_insert_beforehook( elt, hook ) \
|
||||
MACRO_BEGIN elt->next = *hook; *hook = elt; hook = &elt->next; MACRO_END
|
||||
MACRO_BEGIN elt->next = *hook; \
|
||||
*hook = elt; \
|
||||
hook = &elt->next; \
|
||||
MACRO_END
|
||||
|
||||
/* unlink element after hook, let elt be unlinked element, or NULL.
|
||||
* hook remains. */
|
||||
#define list_unlink_athook( list, elt, hook ) \
|
||||
MACRO_BEGIN \
|
||||
elt = hook ? *hook : NULL; if( elt ) { *hook = elt->next; elt->next = NULL; } \
|
||||
elt = hook ? *hook : NULL; \
|
||||
if( elt ) \
|
||||
{ \
|
||||
*hook = elt->next; \
|
||||
elt->next = NULL; \
|
||||
} \
|
||||
MACRO_END
|
||||
|
||||
/* unlink the specific element, if it is in the list. Otherwise, set
|
||||
|
@ -94,13 +105,17 @@
|
|||
|
||||
/* prepend elt to list */
|
||||
#define list_prepend( list, elt ) \
|
||||
MACRO_BEGIN elt->next = list; list = elt; MACRO_END
|
||||
MACRO_BEGIN elt->next = list; \
|
||||
list = elt; \
|
||||
MACRO_END
|
||||
|
||||
/* append elt to list. */
|
||||
#define list_append( listtype, list, elt ) \
|
||||
MACRO_BEGIN \
|
||||
listtype * *_hook; \
|
||||
_list_forall_hook( list, _hook ) {} \
|
||||
_list_forall_hook( list, _hook ) \
|
||||
{ \
|
||||
} \
|
||||
list_insert_athook( elt, _hook ); \
|
||||
MACRO_END
|
||||
|
||||
|
@ -117,7 +132,9 @@
|
|||
#define list_nth( elt, list, n ) \
|
||||
MACRO_BEGIN \
|
||||
int _x; /* only evaluate n once */ \
|
||||
for( _x = (n), elt = list; _x && elt; _x--, elt = elt->next ) {} \
|
||||
for( _x = ( n ), elt = list; _x && elt; _x--, elt = elt->next ) \
|
||||
{ \
|
||||
} \
|
||||
MACRO_END
|
||||
|
||||
/* let elt be the nth element of the list, starting to count from 0.
|
||||
|
@ -126,7 +143,9 @@
|
|||
MACRO_BEGIN \
|
||||
int _x; /* only evaluate n once */ \
|
||||
for( _x = ( n ), elt = list, hook = &list; _x && elt; \
|
||||
_x--, hook = &elt->next, elt = elt->next ) {} \
|
||||
_x--, hook = &elt->next, elt = elt->next ) \
|
||||
{ \
|
||||
} \
|
||||
MACRO_END
|
||||
|
||||
/* set n to the length of the list */
|
||||
|
@ -134,8 +153,7 @@
|
|||
MACRO_BEGIN \
|
||||
listtype * _elt; \
|
||||
n = 0; \
|
||||
list_forall( _elt, list ) \
|
||||
n++; \
|
||||
list_forall( _elt, list ) n++; \
|
||||
MACRO_END
|
||||
|
||||
/* set n to the index of the first element satisfying cond, or -1 if
|
||||
|
@ -143,7 +161,8 @@
|
|||
#define list_index( list, n, elt, c ) \
|
||||
MACRO_BEGIN \
|
||||
n = 0; \
|
||||
list_forall( elt, list ) { \
|
||||
list_forall( elt, list ) \
|
||||
{ \
|
||||
if( c ) \
|
||||
break; \
|
||||
n++; \
|
||||
|
@ -156,7 +175,8 @@
|
|||
#define list_count( list, n, elt, c ) \
|
||||
MACRO_BEGIN \
|
||||
n = 0; \
|
||||
list_forall( elt, list ) { \
|
||||
list_forall( elt, list ) \
|
||||
{ \
|
||||
if( c ) \
|
||||
n++; \
|
||||
} \
|
||||
|
@ -170,8 +190,7 @@
|
|||
#define list_reverse( listtype, list ) \
|
||||
MACRO_BEGIN \
|
||||
listtype * _list1 = NULL, *elt; \
|
||||
list_forall_unlink( elt, list ) \
|
||||
list_prepend( _list1, elt ); \
|
||||
list_forall_unlink( elt, list ) list_prepend( _list1, elt ); \
|
||||
list = _list1; \
|
||||
MACRO_END
|
||||
|
||||
|
@ -203,8 +222,7 @@
|
|||
#define list_sort( listtype, list, a, b, cond ) \
|
||||
MACRO_BEGIN \
|
||||
listtype * _newlist = NULL; \
|
||||
list_forall_unlink( a, list ) \
|
||||
list_insert_ordered( listtype, _newlist, a, b, cond ); \
|
||||
list_forall_unlink( a, list ) list_insert_ordered( listtype, _newlist, a, b, cond ); \
|
||||
list = _newlist; \
|
||||
MACRO_END
|
||||
|
||||
|
@ -217,13 +235,16 @@
|
|||
MACRO_BEGIN \
|
||||
listtype * _elt, **_hook1; \
|
||||
\
|
||||
for( _elt = list; _elt; _elt = _elt->next1 ) { \
|
||||
for( _elt = list; _elt; _elt = _elt->next1 ) \
|
||||
{ \
|
||||
_elt->next1 = _elt->next; \
|
||||
_elt->next = NULL; \
|
||||
} \
|
||||
do { \
|
||||
do \
|
||||
{ \
|
||||
_hook1 = &( list ); \
|
||||
while( (a = *_hook1) != NULL && (b = a->next1) != NULL ) { \
|
||||
while( ( a = *_hook1 ) != NULL && ( b = a->next1 ) != NULL ) \
|
||||
{ \
|
||||
_elt = b->next1; \
|
||||
_list_merge_cond( listtype, a, b, cond, *_hook1 ); \
|
||||
_hook1 = &( ( *_hook1 )->next1 ); \
|
||||
|
@ -238,21 +259,26 @@
|
|||
MACRO_BEGIN \
|
||||
listtype * *_hook; \
|
||||
_hook = &( result ); \
|
||||
while( 1 ) { \
|
||||
if( a==NULL ) { \
|
||||
while( 1 ) \
|
||||
{ \
|
||||
if( a == NULL ) \
|
||||
{ \
|
||||
*_hook = b; \
|
||||
break; \
|
||||
} \
|
||||
else if( b==NULL ) { \
|
||||
else if( b == NULL ) \
|
||||
{ \
|
||||
*_hook = a; \
|
||||
break; \
|
||||
} \
|
||||
else if( cond ) { \
|
||||
else if( cond ) \
|
||||
{ \
|
||||
*_hook = a; \
|
||||
_hook = &( a->next ); \
|
||||
a = a->next; \
|
||||
} \
|
||||
else { \
|
||||
else \
|
||||
{ \
|
||||
*_hook = b; \
|
||||
_hook = &( b->next ); \
|
||||
b = b->next; \
|
||||
|
@ -267,10 +293,12 @@
|
|||
MACRO_BEGIN \
|
||||
elt->prev = end; \
|
||||
elt->next = NULL; \
|
||||
if( end ) { \
|
||||
if( end ) \
|
||||
{ \
|
||||
end->next = elt; \
|
||||
} \
|
||||
else { \
|
||||
else \
|
||||
{ \
|
||||
head = elt; \
|
||||
} \
|
||||
end = elt; \
|
||||
|
@ -286,12 +314,15 @@
|
|||
#define dlist_unlink_first( head, end, elt ) \
|
||||
MACRO_BEGIN \
|
||||
elt = head; \
|
||||
if( head ) { \
|
||||
if( head ) \
|
||||
{ \
|
||||
head = head->next; \
|
||||
if( head ) { \
|
||||
if( head ) \
|
||||
{ \
|
||||
head->prev = NULL; \
|
||||
} \
|
||||
else { \
|
||||
else \
|
||||
{ \
|
||||
end = NULL; \
|
||||
} \
|
||||
elt->prev = NULL; \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
|||
#define PLATFORM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
/* in Windows, set all file i/o to binary */
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define POTRACELIB_VERSION "potracelib 1.13"
|
||||
#define POTRACELIB_VERSION "potracelib 1.15"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -9,12 +9,11 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "potracelib.h"
|
||||
#include "curve.h"
|
||||
#include "decompose.h"
|
||||
#include "trace.h"
|
||||
#include "potracelib.h"
|
||||
#include "progress.h"
|
||||
#include <potrace_version.h>
|
||||
#include "trace.h"
|
||||
|
||||
/* default parameters */
|
||||
static const potrace_param_t param_default =
|
||||
|
@ -128,6 +127,7 @@ void potrace_param_free( potrace_param_t* p )
|
|||
}
|
||||
|
||||
|
||||
#include "potrace_version.h"
|
||||
const char* potrace_version( void )
|
||||
{
|
||||
return POTRACELIB_VERSION;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -129,8 +129,7 @@ potrace_param_t* potrace_param_default( void );
|
|||
void potrace_param_free( potrace_param_t* p );
|
||||
|
||||
/* trace a bitmap */
|
||||
potrace_state_t* potrace_trace( const potrace_param_t* param,
|
||||
const potrace_bitmap_t* bm );
|
||||
potrace_state_t* potrace_trace( const potrace_param_t* param, const potrace_bitmap_t* bm );
|
||||
|
||||
/* free a Potrace state */
|
||||
void potrace_state_free( potrace_state_t* st );
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -6,14 +6,14 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "render.h"
|
||||
#include "greymap.h"
|
||||
#include "auxiliary.h"
|
||||
#include "greymap.h"
|
||||
#include "render.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* routines for anti-aliased rendering of curves */
|
||||
|
@ -67,7 +67,6 @@ render_t* render_new( greymap_t* gm )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
memset( rm->incrow_buf, 0, gm->h * sizeof(int) );
|
||||
return rm;
|
||||
}
|
||||
|
||||
|
@ -215,8 +214,8 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
|||
/* render line from r0 to r1 segment of (rm->x1,rm->y1)..(x2,y2) */
|
||||
|
||||
/* move point to r1 */
|
||||
rm->a1 += (r1 - r0) * (y2 - rm->y1) *
|
||||
( rxi + 1 - ( (r0 + r1) / 2.0 * (x2 - rm->x1) + rm->x1 ) );
|
||||
rm->a1 += ( r1 - r0 ) * ( y2 - rm->y1 )
|
||||
* ( rxi + 1 - ( ( r0 + r1 ) / 2.0 * ( x2 - rm->x1 ) + rm->x1 ) );
|
||||
|
||||
/* move point across pixel boundary */
|
||||
if( s && x2 > rm->x1 )
|
||||
|
@ -254,8 +253,8 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
|||
/* move point to (x2,y2) */
|
||||
|
||||
r1 = 1;
|
||||
rm->a1 += (r1 - r0) * (y2 - rm->y1) *
|
||||
( rxi + 1 - ( (r0 + r1) / 2.0 * (x2 - rm->x1) + rm->x1 ) );
|
||||
rm->a1 += ( r1 - r0 ) * ( y2 - rm->y1 )
|
||||
* ( rxi + 1 - ( ( r0 + r1 ) / 2.0 * ( x2 - rm->x1 ) + rm->x1 ) );
|
||||
|
||||
rm->x1i = x2i;
|
||||
rm->y1i = y2i;
|
||||
|
@ -292,10 +291,10 @@ void render_curveto( render_t* rm, double x2, double y2, double x3, double y3, d
|
|||
|
||||
for( t = epsilon; t < 1; t += epsilon )
|
||||
{
|
||||
render_lineto( rm, x1 * cu( 1 - t ) + 3 * x2 * sq( 1 - t ) * t + 3 * x3 * (1 - t) * sq(
|
||||
t ) + x4 * cu( t ),
|
||||
y1 * cu( 1 - t ) + 3 * y2 * sq( 1 - t ) * t + 3 * y3 * (1 - t) * sq( t ) + y4 *
|
||||
cu( t ) );
|
||||
render_lineto( rm, x1 * cu( 1 - t ) + 3 * x2 * sq( 1 - t ) * t
|
||||
+ 3 * x3 * ( 1 - t ) * sq( t ) + x4 * cu( t ),
|
||||
y1 * cu( 1 - t ) + 3 * y2 * sq( 1 - t ) * t + 3 * y3 * ( 1 - t ) * sq( t )
|
||||
+ y4 * cu( t ) );
|
||||
}
|
||||
|
||||
render_lineto( rm, x4, y4 );
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
||||
#ifndef RENDER_H
|
||||
#define RENDER_H
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
@ -8,19 +8,20 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "potracelib.h"
|
||||
#include "auxiliary.h"
|
||||
#include "curve.h"
|
||||
#include "lists.h"
|
||||
#include "auxiliary.h"
|
||||
#include "trace.h"
|
||||
#include "potracelib.h"
|
||||
#include "progress.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define INFTY 10000000 /* it suffices that this is longer than any
|
||||
#define INFTY \
|
||||
10000000 /* it suffices that this is longer than any
|
||||
* path; it need not be really infinite */
|
||||
#define COS179 -0.999847695156 /* the cosine of 179 degrees */
|
||||
|
||||
|
@ -265,8 +266,10 @@ static inline dpoint_t bezier( double t, dpoint_t p0, dpoint_t p1, dpoint_t p2,
|
|||
* following to 16 multiplications, using common subexpression
|
||||
* elimination. */
|
||||
|
||||
res.x = s * s * s * p0.x + 3 * (s * s * t) * p1.x + 3 * (t * t * s) * p2.x + t * t * t * p3.x;
|
||||
res.y = s * s * s * p0.y + 3 * (s * s * t) * p1.y + 3 * (t * t * s) * p2.y + t * t * t * p3.y;
|
||||
res.x = s * s * s * p0.x + 3 * ( s * s * t ) * p1.x + 3 * ( t * t * s ) * p2.x
|
||||
+ t * t * t * p3.x;
|
||||
res.y = s * s * s * p0.y + 3 * ( s * s * t ) * p1.y + 3 * ( t * t * s ) * p2.y
|
||||
+ t * t * t * p3.y;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -341,9 +344,9 @@ static int calc_sums( privpath_t* pp )
|
|||
y = pp->pt[i].y - pp->y0;
|
||||
pp->sums[i + 1].x = pp->sums[i].x + x;
|
||||
pp->sums[i + 1].y = pp->sums[i].y + y;
|
||||
pp->sums[i + 1].x2 = pp->sums[i].x2 + x * x;
|
||||
pp->sums[i + 1].xy = pp->sums[i].xy + x * y;
|
||||
pp->sums[i + 1].y2 = pp->sums[i].y2 + y * y;
|
||||
pp->sums[i + 1].x2 = pp->sums[i].x2 + (double) x * x;
|
||||
pp->sums[i + 1].xy = pp->sums[i].xy + (double) x * y;
|
||||
pp->sums[i + 1].y2 = pp->sums[i].y2 + (double) y * y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -429,7 +432,8 @@ static int calc_lon( privpath_t* pp )
|
|||
ct[0] = ct[1] = ct[2] = ct[3] = 0;
|
||||
|
||||
/* keep track of "directions" that have occurred */
|
||||
dir = ( 3 + 3 * (pt[mod( i + 1, n )].x - pt[i].x) + (pt[mod( i + 1, n )].y - pt[i].y) ) / 2;
|
||||
dir = ( 3 + 3 * ( pt[mod( i + 1, n )].x - pt[i].x ) + ( pt[mod( i + 1, n )].y - pt[i].y ) )
|
||||
/ 2;
|
||||
ct[dir]++;
|
||||
|
||||
constraint[0].x = 0;
|
||||
|
@ -525,8 +529,7 @@ constraint_viol:
|
|||
}
|
||||
|
||||
pivk[i] = mod( k1 + j, n );
|
||||
foundk:
|
||||
;
|
||||
foundk:;
|
||||
} /* for i */
|
||||
|
||||
/* clean up: for each i, let lon[i] be the largest k such that for
|
||||
|
@ -938,8 +941,9 @@ static int adjust_vertices( privpath_t* pp )
|
|||
goto fixx;
|
||||
}
|
||||
|
||||
for( z = 0; z<2; z++ ) /* value of the y-coordinate */
|
||||
for( z = 0; z < 2; z++ )
|
||||
{
|
||||
/* value of the y-coordinate */
|
||||
w.y = s.y - 0.5 + z;
|
||||
w.x = -( Q[0][1] * w.y + Q[0][2] ) / Q[0][0];
|
||||
dx = fabs( w.x - s.x );
|
||||
|
@ -960,8 +964,9 @@ fixx:
|
|||
goto corners;
|
||||
}
|
||||
|
||||
for( z = 0; z<2; z++ ) /* value of the x-coordinate */
|
||||
for( z = 0; z < 2; z++ )
|
||||
{
|
||||
/* value of the x-coordinate */
|
||||
w.x = s.x - 0.5 + z;
|
||||
w.y = -( Q[1][0] * w.x + Q[1][2] ) / Q[1][1];
|
||||
dy = fabs( w.y - s.y );
|
||||
|
@ -1064,8 +1069,9 @@ static void smooth( privcurve_t* curve, double alphamax )
|
|||
|
||||
curve->alpha0[j] = alpha; /* remember "original" value of alpha */
|
||||
|
||||
if( alpha >= alphamax ) /* pointed corner */
|
||||
if( alpha >= alphamax )
|
||||
{
|
||||
/* pointed corner */
|
||||
curve->tag[j] = POTRACE_CORNER;
|
||||
curve->c[j][1] = curve->vertex[j];
|
||||
curve->c[j][2] = p4;
|
||||
|
@ -1130,8 +1136,9 @@ static int opti_penalty( privpath_t* pp,
|
|||
|
||||
/* check convexity, corner-freeness, and maximum bend < 179 degrees */
|
||||
|
||||
if( i==j ) /* sanity - a full loop can never be an opticurve */
|
||||
if( i == j )
|
||||
{
|
||||
/* sanity - a full loop can never be an opticurve */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1158,14 +1165,15 @@ static int opti_penalty( privpath_t* pp,
|
|||
}
|
||||
|
||||
if( sign( cprod( pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
|
||||
pp->curve.vertex[k2] ) ) != conv )
|
||||
pp->curve.vertex[k2] ) )
|
||||
!= conv )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( iprod1( pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
|
||||
pp->curve.vertex[k2] ) <
|
||||
d * ddist( pp->curve.vertex[k1], pp->curve.vertex[k2] ) * COS179 )
|
||||
pp->curve.vertex[k2] )
|
||||
< d * ddist( pp->curve.vertex[k1], pp->curve.vertex[k2] ) * COS179 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -1196,8 +1204,9 @@ static int opti_penalty( privpath_t* pp,
|
|||
/* A4 = dpara(p1, p2, p3); */
|
||||
A4 = A1 + A3 - A2;
|
||||
|
||||
if( A2 == A1 ) /* this should never happen */
|
||||
if( A2 == A1 )
|
||||
{
|
||||
/* this should never happen */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1205,8 +1214,9 @@ static int opti_penalty( privpath_t* pp,
|
|||
s = A2 / ( A2 - A1 );
|
||||
A = A2 * t / 2.0;
|
||||
|
||||
if( A == 0.0 ) /* this should never happen */
|
||||
if( A == 0.0 )
|
||||
{
|
||||
/* this should never happen */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1239,8 +1249,9 @@ static int opti_penalty( privpath_t* pp,
|
|||
pt = bezier( t, p0, p1, p2, p3 );
|
||||
d = ddist( pp->curve.vertex[k], pp->curve.vertex[k1] );
|
||||
|
||||
if( d == 0.0 ) /* this should never happen */
|
||||
if( d == 0.0 )
|
||||
{
|
||||
/* this should never happen */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1251,8 +1262,8 @@ static int opti_penalty( privpath_t* pp,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if( iprod( pp->curve.vertex[k], pp->curve.vertex[k1],
|
||||
pt ) < 0 || iprod( pp->curve.vertex[k1], pp->curve.vertex[k], pt ) < 0 )
|
||||
if( iprod( pp->curve.vertex[k], pp->curve.vertex[k1], pt ) < 0
|
||||
|| iprod( pp->curve.vertex[k1], pp->curve.vertex[k], pt ) < 0 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -1274,8 +1285,9 @@ static int opti_penalty( privpath_t* pp,
|
|||
pt = bezier( t, p0, p1, p2, p3 );
|
||||
d = ddist( pp->curve.c[k][2], pp->curve.c[k1][2] );
|
||||
|
||||
if( d == 0.0 ) /* this should never happen */
|
||||
if( d == 0.0 )
|
||||
{
|
||||
/* this should never happen */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1339,8 +1351,7 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
|||
{
|
||||
if( pp->curve.tag[i] == POTRACE_CURVETO )
|
||||
{
|
||||
convc[i] =
|
||||
sign( dpara( pp->curve.vertex[mod( i - 1, m )], pp->curve.vertex[i],
|
||||
convc[i] = sign( dpara( pp->curve.vertex[mod( i - 1, m )], pp->curve.vertex[i],
|
||||
pp->curve.vertex[mod( i + 1, m )] ) );
|
||||
}
|
||||
else
|
||||
|
@ -1361,9 +1372,8 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
|||
if( pp->curve.tag[i1] == POTRACE_CURVETO )
|
||||
{
|
||||
alpha = pp->curve.alpha[i1];
|
||||
area += 0.3 * alpha * (4 - alpha) * dpara( pp->curve.c[i][2],
|
||||
pp->curve.vertex[i1],
|
||||
pp->curve.c[i1][2] ) / 2;
|
||||
area += 0.3 * alpha * ( 4 - alpha )
|
||||
* dpara( pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2] ) / 2;
|
||||
area += dpara( p0, pp->curve.c[i][2], pp->curve.c[i1][2] ) / 2;
|
||||
}
|
||||
|
||||
|
@ -1436,9 +1446,8 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
|||
pp->ocurve.c[i][0] = opt[j].c[0];
|
||||
pp->ocurve.c[i][1] = opt[j].c[1];
|
||||
pp->ocurve.c[i][2] = pp->curve.c[mod( j, m )][2];
|
||||
pp->ocurve.vertex[i] = interval( opt[j].s, pp->curve.c[mod( j,
|
||||
m )][2],
|
||||
pp->curve.vertex[mod( j, m )] );
|
||||
pp->ocurve.vertex[i] = interval(
|
||||
opt[j].s, pp->curve.c[mod( j, m )][2], pp->curve.vertex[mod( j, m )] );
|
||||
pp->ocurve.alpha[i] = opt[j].alpha;
|
||||
pp->ocurve.alpha0[i] = opt[j].alpha;
|
||||
s[i] = opt[j].s;
|
||||
|
@ -1482,7 +1491,8 @@ calloc_error:
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#define TRY( x ) if( x ) \
|
||||
#define TRY( x ) \
|
||||
if( x ) \
|
||||
goto try_error
|
||||
|
||||
/* return 0 on success, 1 on error with errno set. */
|
||||
|
@ -1508,8 +1518,9 @@ int process_path( path_t* plist, const potrace_param_t* param, progress_t* progr
|
|||
TRY( bestpolygon( p->priv ) );
|
||||
TRY( adjust_vertices( p->priv ) );
|
||||
|
||||
if( p->sign == '-' ) /* reverse orientation of negative paths */
|
||||
if( p->sign == '-' )
|
||||
{
|
||||
/* reverse orientation of negative paths */
|
||||
reverse( &p->priv->curve );
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||
/* Copyright (C) 2001-2017 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. */
|
||||
|
||||
|
||||
#ifndef TRACE_H
|
||||
#define TRACE_H
|
||||
|
||||
#include "curve.h"
|
||||
#include "potracelib.h"
|
||||
#include "progress.h"
|
||||
#include "curve.h"
|
||||
|
||||
int process_path( path_t* plist, const potrace_param_t* param, progress_t* progress );
|
||||
|
||||
|
|
Loading…
Reference in New Issue