Potrace library: update version from 1.8 to 1.12
This commit is contained in:
parent
9b4d12653e
commit
23a0dddea9
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -8,21 +8,23 @@
|
||||||
#ifndef AUXILIARY_H
|
#ifndef AUXILIARY_H
|
||||||
#define AUXILIARY_H
|
#define AUXILIARY_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* point arithmetic */
|
/* point arithmetic */
|
||||||
|
|
||||||
#include <potracelib.h>
|
#include "potracelib.h"
|
||||||
|
|
||||||
struct point_s
|
struct point_s
|
||||||
{
|
{
|
||||||
long x;
|
long x;
|
||||||
long y;
|
long y;
|
||||||
};
|
};
|
||||||
typedef struct point_s point_t;
|
typedef struct point_s point_t;
|
||||||
|
|
||||||
typedef potrace_dpoint_t dpoint_t;
|
typedef potrace_dpoint_t dpoint_t;
|
||||||
|
|
||||||
|
@ -31,8 +33,8 @@ static inline dpoint_t dpoint( point_t p )
|
||||||
{
|
{
|
||||||
dpoint_t res;
|
dpoint_t res;
|
||||||
|
|
||||||
res.x = p.x;
|
res.x = p.x;
|
||||||
res.y = p.y;
|
res.y = p.y;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,14 +44,13 @@ static inline dpoint_t interval( double lambda, dpoint_t a, dpoint_t b )
|
||||||
{
|
{
|
||||||
dpoint_t res;
|
dpoint_t res;
|
||||||
|
|
||||||
res.x = a.x + lambda * (b.x - a.x);
|
res.x = a.x + lambda * (b.x - a.x);
|
||||||
res.y = a.y + lambda * (b.y - a.y);
|
res.y = a.y + lambda * (b.y - a.y);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* some useful macros. Note: the "mod" macro works correctly for
|
/* some useful macros. Note: the "mod" macro works correctly for
|
||||||
* negative a. Also note that the test for a>=n, while redundant,
|
* negative a. Also note that the test for a>=n, while redundant,
|
||||||
* speeds up the mod function by 70% in the average case (significant
|
* speeds up the mod function by 70% in the average case (significant
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
#ifndef BITMAP_H
|
#ifndef BITMAP_H
|
||||||
#define BITMAP_H
|
#define BITMAP_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/* The bitmap type is defined in potracelib.h */
|
/* The bitmap type is defined in potracelib.h */
|
||||||
#include <potracelib.h>
|
#include "potracelib.h"
|
||||||
|
|
||||||
/* The present file defines some convenient macros and static inline
|
/* The present file defines some convenient macros and static inline
|
||||||
* functions for accessing bitmaps. Since they only produce inline
|
* functions for accessing bitmaps. Since they only produce inline
|
||||||
|
@ -31,21 +28,21 @@
|
||||||
/* macros for accessing pixel at index (x,y). U* macros omit the
|
/* macros for accessing pixel at index (x,y). U* macros omit the
|
||||||
* bounds check. */
|
* bounds check. */
|
||||||
|
|
||||||
#define bm_scanline( bm, y ) ( (bm)->map + (y) * (bm)->dy )
|
#define bm_scanline( bm, y ) ( (bm)->map + (ssize_t) (y) * (ssize_t) (bm)->dy )
|
||||||
#define bm_index( bm, x, y ) (&bm_scanline( bm, y )[(x) / BM_WORDBITS])
|
#define bm_index( bm, x, y ) (&bm_scanline( bm, y )[(x) / BM_WORDBITS])
|
||||||
#define bm_mask( x ) ( BM_HIBIT >> ( (x) & (BM_WORDBITS - 1) ) )
|
#define bm_mask( x ) ( BM_HIBIT >> ( (x) & (BM_WORDBITS - 1) ) )
|
||||||
#define bm_range( x, a ) ( (int) (x) >= 0 && (int) (x) < (a) )
|
#define bm_range( x, a ) ( (int) (x) >= 0 && (int) (x) < (a) )
|
||||||
#define bm_safe( bm, x, y ) ( bm_range( x, (bm)->w ) && bm_range( y, (bm)->h ) )
|
#define bm_safe( bm, x, y ) ( bm_range( x, (bm)->w ) && bm_range( y, (bm)->h ) )
|
||||||
#define BM_UGET( bm, x, y ) ( ( *bm_index( bm, x, y ) & bm_mask( x ) ) != 0 )
|
#define BM_UGET( bm, x, y ) ( ( *bm_index( bm, x, y ) & bm_mask( x ) ) != 0 )
|
||||||
#define BM_USET( bm, x, y ) ( *bm_index( bm, x, y ) |= bm_mask( x ) )
|
#define BM_USET( bm, x, y ) ( *bm_index( bm, x, y ) |= bm_mask( x ) )
|
||||||
#define BM_UCLR( bm, x, y ) ( *bm_index( bm, x, y ) &= ~bm_mask( x ) )
|
#define BM_UCLR( bm, x, y ) ( *bm_index( bm, x, y ) &= ~bm_mask( x ) )
|
||||||
#define BM_UINV( bm, x, y ) ( *bm_index( bm, x, y ) ^= bm_mask( x ) )
|
#define BM_UINV( bm, x, y ) ( *bm_index( bm, x, y ) ^= bm_mask( x ) )
|
||||||
#define BM_UPUT( bm, x, y, b ) ( (b) ? BM_USET( bm, x, y ) : BM_UCLR( bm, x, y ) )
|
#define BM_UPUT( bm, x, y, b ) ( (b) ? BM_USET( bm, x, y ) : BM_UCLR( bm, x, y ) )
|
||||||
#define BM_GET( bm, x, y ) (bm_safe( bm, x, y ) ? BM_UGET( bm, x, y ) : 0)
|
#define BM_GET( bm, x, y ) (bm_safe( bm, x, y ) ? BM_UGET( bm, x, y ) : 0)
|
||||||
#define BM_SET( bm, x, y ) (bm_safe( bm, x, y ) ? BM_USET( bm, x, y ) : 0)
|
#define BM_SET( bm, x, y ) (bm_safe( bm, x, y ) ? BM_USET( bm, x, y ) : 0)
|
||||||
#define BM_CLR( bm, x, y ) (bm_safe( bm, x, y ) ? BM_UCLR( bm, x, y ) : 0)
|
#define BM_CLR( bm, x, y ) (bm_safe( bm, x, y ) ? BM_UCLR( bm, x, y ) : 0)
|
||||||
#define BM_INV( bm, x, y ) (bm_safe( bm, x, y ) ? BM_UINV( bm, x, y ) : 0)
|
#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)
|
#define BM_PUT( bm, x, y, b ) (bm_safe( bm, x, y ) ? BM_UPUT( bm, x, y, b ) : 0)
|
||||||
|
|
||||||
/* free the given bitmap. Leaves errno untouched. */
|
/* free the given bitmap. Leaves errno untouched. */
|
||||||
static inline void bm_free( potrace_bitmap_t* bm )
|
static inline void bm_free( potrace_bitmap_t* bm )
|
||||||
|
@ -54,30 +51,44 @@ static inline void bm_free( potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
free( bm->map );
|
free( bm->map );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( bm );
|
free( bm );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* return new un-initialized bitmap. NULL with errno on error */
|
/* return new un-initialized bitmap. NULL with errno on error.
|
||||||
|
* Assumes w, h >= 0. */
|
||||||
static inline potrace_bitmap_t* bm_new( int w, int h )
|
static inline potrace_bitmap_t* bm_new( int w, int h )
|
||||||
{
|
{
|
||||||
potrace_bitmap_t* bm;
|
potrace_bitmap_t* bm;
|
||||||
int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS;
|
int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1;
|
||||||
|
ssize_t size = (ssize_t) dy * (ssize_t) h * (ssize_t) BM_WORDSIZE;
|
||||||
|
|
||||||
|
/* check for overflow error */
|
||||||
|
if( size < 0 || size / h / dy != BM_WORDSIZE )
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bm = (potrace_bitmap_t*) malloc( sizeof(potrace_bitmap_t) );
|
bm = (potrace_bitmap_t*) malloc( sizeof(potrace_bitmap_t) );
|
||||||
|
|
||||||
if( !bm )
|
if( !bm )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bm->w = w;
|
bm->w = w;
|
||||||
bm->h = h;
|
bm->h = h;
|
||||||
bm->dy = dy;
|
bm->dy = dy;
|
||||||
bm->map = (potrace_word*) malloc( dy * h * BM_WORDSIZE );
|
bm->map = (potrace_word*) malloc( size );
|
||||||
|
|
||||||
if( !bm->map )
|
if( !bm->map )
|
||||||
{
|
{
|
||||||
free( bm );
|
free( bm );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bm;
|
return bm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +96,11 @@ 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. */
|
||||||
static inline void bm_clear( potrace_bitmap_t* bm, int c )
|
static inline void bm_clear( potrace_bitmap_t* bm, int c )
|
||||||
{
|
{
|
||||||
memset( bm->map, c ? -1 : 0, bm->dy * bm->h * BM_WORDSIZE );
|
/* Note: if the bitmap was created with bm_new, then it is
|
||||||
|
* guaranteed that size will fit into the ssize_t type. */
|
||||||
|
ssize_t size = (ssize_t) bm->dy * (ssize_t) bm->h * (ssize_t) BM_WORDSIZE;
|
||||||
|
|
||||||
|
memset( bm->map, c ? -1 : 0, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,12 +108,14 @@ static inline void bm_clear( potrace_bitmap_t* bm, int c )
|
||||||
static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
potrace_bitmap_t* bm1 = bm_new( bm->w, bm->h );
|
potrace_bitmap_t* bm1 = bm_new( bm->w, bm->h );
|
||||||
|
ssize_t size = (ssize_t) bm->dy * (ssize_t) bm->h * (ssize_t) BM_WORDSIZE;
|
||||||
|
|
||||||
if( !bm1 )
|
if( !bm1 )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy( bm1->map, bm->map, bm->dy * bm->h * BM_WORDSIZE );
|
|
||||||
|
memcpy( bm1->map, bm->map, size );
|
||||||
return bm1;
|
return bm1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +123,10 @@ static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
||||||
/* invert the given bitmap. */
|
/* invert the given bitmap. */
|
||||||
static inline void bm_invert( potrace_bitmap_t* bm )
|
static inline void bm_invert( potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
int i;
|
ssize_t i;
|
||||||
|
ssize_t size = (ssize_t) bm->dy * (ssize_t) bm->h;
|
||||||
|
|
||||||
for( i = 0; i < bm->dy * bm->h; i++ )
|
for( i = 0; i < size; i++ )
|
||||||
{
|
{
|
||||||
bm->map[i] ^= BM_ALLBITS;
|
bm->map[i] ^= BM_ALLBITS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* 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. */
|
/* Routines for manipulating bitmaps, including reading pbm files. */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <bitmap.h>
|
#include "bitmap.h"
|
||||||
|
#include "bitops.h"
|
||||||
|
|
||||||
#define INTBITS ( 8 * sizeof(int) )
|
#define INTBITS ( 8 * sizeof(int) )
|
||||||
|
|
||||||
static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp );
|
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 );
|
static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, int magic );
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* routines for reading pnm streams */
|
/* routines for reading pnm streams */
|
||||||
|
@ -27,17 +27,20 @@ static int fgetc_ws( FILE* f )
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c=='#' )
|
if( c=='#' )
|
||||||
{
|
{
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c=='\n' || c==EOF )
|
if( c=='\n' || c==EOF )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* space, tab, line feed, carriage return, form-feed */
|
/* space, tab, line feed, carriage return, form-feed */
|
||||||
if( c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12 )
|
if( c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12 )
|
||||||
{
|
{
|
||||||
|
@ -61,10 +64,12 @@ static int readnum( FILE* f )
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc_ws( f );
|
c = fgetc_ws( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c==EOF )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c>='0' && c<='9' )
|
if( c>='0' && c<='9' )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -73,18 +78,22 @@ static int readnum( FILE* f )
|
||||||
|
|
||||||
/* first digit is already in c */
|
/* first digit is already in c */
|
||||||
acc = c - '0';
|
acc = c - '0';
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c==EOF )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c<'0' || c>'9' )
|
if( c<'0' || c>'9' )
|
||||||
{
|
{
|
||||||
ungetc( c, f );
|
ungetc( c, f );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
acc *= 10;
|
acc *= 10;
|
||||||
acc += c - '0';
|
acc += c - '0';
|
||||||
}
|
}
|
||||||
|
@ -104,10 +113,12 @@ static int readbit( FILE* f )
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc_ws( f );
|
c = fgetc_ws( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c==EOF )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c>='0' && c<='1' )
|
if( c>='0' && c<='1' )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -126,7 +137,7 @@ static int readbit( FILE* f )
|
||||||
* error message in bm_read_error), and 1 on premature end of file, -3
|
* error message in bm_read_error), and 1 on premature end of file, -3
|
||||||
* on empty file (including files which contain only whitespace and
|
* on empty file (including files which contain only whitespace and
|
||||||
* comments), -4 if wrong magic number. If the return value is >=0,
|
* comments), -4 if wrong magic number. If the return value is >=0,
|
||||||
*bmp is valid. */
|
* bmp is valid. */
|
||||||
|
|
||||||
const char* bm_read_error = NULL;
|
const char* bm_read_error = NULL;
|
||||||
|
|
||||||
|
@ -140,19 +151,24 @@ int bm_read( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
* by the PNM standard, but there is no harm in being lenient. */
|
* by the PNM standard, but there is no harm in being lenient. */
|
||||||
|
|
||||||
magic[0] = fgetc_ws( f );
|
magic[0] = fgetc_ws( f );
|
||||||
|
|
||||||
if( magic[0] == EOF )
|
if( magic[0] == EOF )
|
||||||
{
|
{
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
magic[1] = fgetc( f );
|
magic[1] = fgetc( f );
|
||||||
|
|
||||||
if( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' )
|
if( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' )
|
||||||
{
|
{
|
||||||
return bm_readbody_pnm( f, threshold, bmp, magic[1] );
|
return bm_readbody_pnm( f, threshold, bmp, magic[1] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( magic[0] == 'B' && magic[1] == 'M' )
|
if( magic[0] == 'B' && magic[1] == 'M' )
|
||||||
{
|
{
|
||||||
return bm_readbody_bmp( f, threshold, bmp );
|
return bm_readbody_bmp( f, threshold, bmp );
|
||||||
}
|
}
|
||||||
|
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,12 +187,14 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
bm = NULL;
|
bm = NULL;
|
||||||
|
|
||||||
w = readnum( f );
|
w = readnum( f );
|
||||||
|
|
||||||
if( w<0 )
|
if( w<0 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
h = readnum( f );
|
h = readnum( f );
|
||||||
|
|
||||||
if( h<0 )
|
if( h<0 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -184,6 +202,7 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
|
|
||||||
/* allocate bitmap */
|
/* allocate bitmap */
|
||||||
bm = bm_new( w, h );
|
bm = bm_new( w, h );
|
||||||
|
|
||||||
if( !bm )
|
if( !bm )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -206,10 +225,12 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
b = readbit( f );
|
b = readbit( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b<0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_UPUT( bm, x, y, b );
|
BM_UPUT( bm, x, y, b );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,6 +241,7 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
/* read P2 format: PGM ascii */
|
/* read P2 format: PGM ascii */
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max<1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -230,10 +252,12 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
b = readnum( f );
|
b = readnum( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b<0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_UPUT( bm, x, y, b > threshold * max ? 0 : 1 );
|
BM_UPUT( bm, x, y, b > threshold * max ? 0 : 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,6 +268,7 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
/* read P3 format: PPM ascii */
|
/* read P3 format: PPM ascii */
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max<1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -254,13 +279,16 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
for( i = 0; i<3; i++ )
|
for( i = 0; i<3; i++ )
|
||||||
{
|
{
|
||||||
b = readnum( f );
|
b = readnum( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b<0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += b;
|
sum += b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +302,7 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
/* read P4 format: PBM raw */
|
/* read P4 format: PBM raw */
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after height */
|
b = fgetc( f ); /* read single white-space character after height */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -286,13 +315,15 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
for( i = 0; i<bpr; i++ )
|
for( i = 0; i<bpr; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
*bm_index( bm, i * 8,
|
*bm_index( bm, i * 8,
|
||||||
y ) |= ( (potrace_word) b ) <<
|
y ) |= ( (potrace_word) b ) <<
|
||||||
( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) );
|
( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,12 +333,14 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
/* read P5 format: PGM raw */
|
/* read P5 format: PGM raw */
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max<1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after max */
|
b = fgetc( f ); /* read single white-space character after max */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -318,16 +351,21 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
if( max>=256 )
|
if( max>=256 )
|
||||||
{
|
{
|
||||||
b <<= 8;
|
b <<= 8;
|
||||||
b1 = fgetc( f );
|
b1 = fgetc( f );
|
||||||
|
|
||||||
if( b1==EOF )
|
if( b1==EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
b |= b1;
|
b |= b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_UPUT( bm, x, y, b > threshold * max ? 0 : 1 );
|
BM_UPUT( bm, x, y, b > threshold * max ? 0 : 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,12 +376,14 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
/* read P6 format: PPM raw */
|
/* read P6 format: PPM raw */
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max<1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after max */
|
b = fgetc( f ); /* read single white-space character after max */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -354,21 +394,27 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
for( i = 0; i<3; i++ )
|
for( i = 0; i<3; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( max>=256 )
|
if( max>=256 )
|
||||||
{
|
{
|
||||||
b <<= 8;
|
b <<= 8;
|
||||||
b1 = fgetc( f );
|
b1 = fgetc( f );
|
||||||
|
|
||||||
if( b1==EOF )
|
if( b1==EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
b |= b1;
|
b |= b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += b;
|
sum += b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,6 +434,7 @@ eof:
|
||||||
|
|
||||||
format_error:
|
format_error:
|
||||||
bm_free( bm );
|
bm_free( bm );
|
||||||
|
|
||||||
if( magic == '1' || magic == '4' )
|
if( magic == '1' || magic == '4' )
|
||||||
{
|
{
|
||||||
bm_read_error = "invalid pbm file";
|
bm_read_error = "invalid pbm file";
|
||||||
|
@ -400,6 +447,7 @@ format_error:
|
||||||
{
|
{
|
||||||
bm_read_error = "invalid ppm file";
|
bm_read_error = "invalid ppm file";
|
||||||
}
|
}
|
||||||
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,49 +457,56 @@ format_error:
|
||||||
|
|
||||||
struct bmp_info_s
|
struct bmp_info_s
|
||||||
{
|
{
|
||||||
unsigned int FileSize;
|
unsigned int FileSize;
|
||||||
unsigned int reserved;
|
unsigned int reserved;
|
||||||
unsigned int DataOffset;
|
unsigned int DataOffset;
|
||||||
unsigned int InfoSize;
|
unsigned int InfoSize;
|
||||||
unsigned int w; /* width */
|
unsigned int w; /* width */
|
||||||
unsigned int h; /* height */
|
unsigned int h; /* height */
|
||||||
unsigned int Planes;
|
unsigned int Planes;
|
||||||
unsigned int bits; /* bits per sample */
|
unsigned int bits; /* bits per sample */
|
||||||
unsigned int comp; /* compression mode */
|
unsigned int comp; /* compression mode */
|
||||||
unsigned int ImageSize;
|
unsigned int ImageSize;
|
||||||
unsigned int XpixelsPerM;
|
unsigned int XpixelsPerM;
|
||||||
unsigned int YpixelsPerM;
|
unsigned int YpixelsPerM;
|
||||||
unsigned int ncolors; /* number of colors in palette */
|
unsigned int ncolors; /* number of colors in palette */
|
||||||
unsigned int ColorsImportant;
|
unsigned int ColorsImportant;
|
||||||
unsigned int ctbits; /* sample size for color table */
|
unsigned int RedMask;
|
||||||
|
unsigned int GreenMask;
|
||||||
|
unsigned int BlueMask;
|
||||||
|
unsigned int AlphaMask;
|
||||||
|
unsigned int ctbits; /* sample size for color table */
|
||||||
|
int topdown; /* top-down mode? */
|
||||||
};
|
};
|
||||||
typedef struct bmp_info_s bmp_info_t;
|
typedef struct bmp_info_s bmp_info_t;
|
||||||
|
|
||||||
/* auxiliary */
|
/* auxiliary */
|
||||||
|
|
||||||
static int bmp_count = 0; /* counter for byte padding */
|
static int bmp_count = 0; /* counter for byte padding */
|
||||||
static int bmp_pos = 0; /* counter from start of BMP data */
|
static int bmp_pos = 0; /* counter from start of BMP data */
|
||||||
|
|
||||||
/* read n-byte little-endian integer. Return 1 on EOF or error, else
|
/* read n-byte little-endian integer. Return 1 on EOF or error, else
|
||||||
* 0. Assume n<=4. */
|
* 0. Assume n<=4. */
|
||||||
static int bmp_readint( FILE* f, int n, unsigned int* p )
|
static int bmp_readint( FILE* f, int n, unsigned int* p )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned int sum = 0;
|
unsigned int sum = 0;
|
||||||
int b;
|
int b;
|
||||||
|
|
||||||
for( i = 0; i<n; i++ )
|
for( i = 0; i<n; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += b << (8 * i);
|
sum += b << (8 * i);
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp_count += n;
|
bmp_count += n;
|
||||||
bmp_pos += n;
|
bmp_pos += n;
|
||||||
*p = sum;
|
*p = sum;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -471,16 +526,18 @@ static int bmp_pad( FILE* f )
|
||||||
int c, i, b;
|
int c, i, b;
|
||||||
|
|
||||||
c = (-bmp_count) & 3;
|
c = (-bmp_count) & 3;
|
||||||
|
|
||||||
for( i = 0; i<c; i++ )
|
for( i = 0; i<c; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp_pos += c;
|
bmp_pos += c;
|
||||||
bmp_count = 0;
|
bmp_count = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -494,10 +551,12 @@ static int bmp_forward( FILE* f, int pos )
|
||||||
while( bmp_pos < pos )
|
while( bmp_pos < pos )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp_pos++;
|
bmp_pos++;
|
||||||
bmp_count++;
|
bmp_count++;
|
||||||
}
|
}
|
||||||
|
@ -506,11 +565,14 @@ static int bmp_forward( FILE* f, int pos )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define TRY( x ) if( x ) \
|
#define TRY( x ) if( x ) \
|
||||||
goto try_error
|
goto try_error
|
||||||
#define TRY_EOF( x ) if( x ) \
|
#define TRY_EOF( x ) if( x ) \
|
||||||
goto eof
|
goto eof
|
||||||
|
|
||||||
|
/* correct y-coordinate for top-down format */
|
||||||
|
#define ycorr( y ) (bmpinfo.topdown ? bmpinfo.h - 1 - y : y)
|
||||||
|
|
||||||
/* read BMP stream after magic number. Return values as for bm_read.
|
/* read BMP stream after magic number. Return values as for bm_read.
|
||||||
* We choose to be as permissive as possible, since there are many
|
* We choose to be as permissive as possible, since there are many
|
||||||
* programs out there which produce BMP. For instance, ppmtobmp can
|
* programs out there which produce BMP. For instance, ppmtobmp can
|
||||||
|
@ -520,16 +582,17 @@ static int bmp_forward( FILE* f, int pos )
|
||||||
* Windows BMP format. */
|
* Windows BMP format. */
|
||||||
static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
{
|
{
|
||||||
bmp_info_t bmpinfo;
|
bmp_info_t bmpinfo;
|
||||||
int* coltable;
|
int* coltable;
|
||||||
unsigned int b, c;
|
unsigned int b, c;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
potrace_bitmap_t* bm;
|
potrace_bitmap_t* bm;
|
||||||
int mask;
|
int mask;
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
int col[2];
|
int col[2];
|
||||||
unsigned int bitbuf;
|
unsigned int bitbuf;
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
|
unsigned int redshift, greenshift, blueshift;
|
||||||
int col1[2];
|
int col1[2];
|
||||||
|
|
||||||
bm_read_error = NULL;
|
bm_read_error = NULL;
|
||||||
|
@ -545,7 +608,9 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
|
|
||||||
/* info header */
|
/* info header */
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.InfoSize ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.InfoSize ) );
|
||||||
if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64 )
|
|
||||||
|
if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64
|
||||||
|
|| bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124 )
|
||||||
{
|
{
|
||||||
/* Windows or new OS/2 format */
|
/* Windows or new OS/2 format */
|
||||||
bmpinfo.ctbits = 32; /* sample size in color table */
|
bmpinfo.ctbits = 32; /* sample size in color table */
|
||||||
|
@ -559,6 +624,34 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.YpixelsPerM ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.YpixelsPerM ) );
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
|
||||||
|
|
||||||
|
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 ) );
|
||||||
|
TRY( bmp_readint( f, 4, &bmpinfo.AlphaMask ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bmpinfo.w > 0x7fffffff )
|
||||||
|
{
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bmpinfo.h > 0x7fffffff )
|
||||||
|
{
|
||||||
|
bmpinfo.h = (-bmpinfo.h) & 0xffffffff;
|
||||||
|
bmpinfo.topdown = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bmpinfo.topdown = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bmpinfo.h > 0x7fffffff )
|
||||||
|
{
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( bmpinfo.InfoSize == 12 )
|
else if( bmpinfo.InfoSize == 12 )
|
||||||
{
|
{
|
||||||
|
@ -568,15 +661,22 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
TRY( bmp_readint( f, 2, &bmpinfo.h ) );
|
TRY( bmp_readint( f, 2, &bmpinfo.h ) );
|
||||||
TRY( bmp_readint( f, 2, &bmpinfo.Planes ) );
|
TRY( bmp_readint( f, 2, &bmpinfo.Planes ) );
|
||||||
TRY( bmp_readint( f, 2, &bmpinfo.bits ) );
|
TRY( bmp_readint( f, 2, &bmpinfo.bits ) );
|
||||||
bmpinfo.comp = 0;
|
bmpinfo.comp = 0;
|
||||||
bmpinfo.ncolors = 0;
|
bmpinfo.ncolors = 0;
|
||||||
|
bmpinfo.topdown = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forward to color table (i.e., if bmpinfo.InfoSize == 64) */
|
if( bmpinfo.comp == 3 && bmpinfo.InfoSize < 108 )
|
||||||
|
{
|
||||||
|
/* bitfield feature is only understood with V4 and V5 format */
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
|
||||||
TRY( bmp_forward( f, 14 + bmpinfo.InfoSize ) );
|
TRY( bmp_forward( f, 14 + bmpinfo.InfoSize ) );
|
||||||
|
|
||||||
if( bmpinfo.Planes != 1 )
|
if( bmpinfo.Planes != 1 )
|
||||||
|
@ -593,7 +693,8 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
/* color table, present only if bmpinfo.bits <= 8. */
|
/* color table, present only if bmpinfo.bits <= 8. */
|
||||||
if( bmpinfo.bits <= 8 )
|
if( bmpinfo.bits <= 8 )
|
||||||
{
|
{
|
||||||
coltable = (int*) malloc( bmpinfo.ncolors * sizeof(int) );
|
coltable = (int*) calloc( bmpinfo.ncolors, sizeof(int) );
|
||||||
|
|
||||||
if( !coltable )
|
if( !coltable )
|
||||||
{
|
{
|
||||||
goto std_error;
|
goto std_error;
|
||||||
|
@ -606,6 +707,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
TRY( bmp_readint( f, bmpinfo.ctbits / 8, &c ) );
|
TRY( bmp_readint( f, bmpinfo.ctbits / 8, &c ) );
|
||||||
c = ( (c >> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff);
|
c = ( (c >> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff);
|
||||||
coltable[i] = (c > 3 * threshold * 255 ? 0 : 1);
|
coltable[i] = (c > 3 * threshold * 255 ? 0 : 1);
|
||||||
|
|
||||||
if( i<2 )
|
if( i<2 )
|
||||||
{
|
{
|
||||||
col1[i] = c;
|
col1[i] = c;
|
||||||
|
@ -621,6 +723,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
|
|
||||||
/* allocate bitmap */
|
/* allocate bitmap */
|
||||||
bm = bm_new( bmpinfo.w, bmpinfo.h );
|
bm = bm_new( bmpinfo.w, bmpinfo.h );
|
||||||
|
|
||||||
if( !bm )
|
if( !bm )
|
||||||
{
|
{
|
||||||
goto std_error;
|
goto std_error;
|
||||||
|
@ -636,6 +739,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x001: /* monochrome palette */
|
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;
|
mask = 0xff;
|
||||||
|
@ -649,13 +753,14 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y<bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
|
|
||||||
for( i = 0; 8 * i<bmpinfo.w; i++ )
|
for( i = 0; 8 * i<bmpinfo.w; i++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
b ^= mask;
|
b ^= mask;
|
||||||
*bm_index( bm, i * 8,
|
*bm_index( bm, i * 8,
|
||||||
y ) |= ( (potrace_word) b ) <<
|
ycorr( y ) ) |= ( (potrace_word) b ) <<
|
||||||
( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) );
|
( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -670,11 +775,13 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
case 0x006:
|
case 0x006:
|
||||||
case 0x007:
|
case 0x007:
|
||||||
case 0x008:
|
case 0x008:
|
||||||
|
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y<bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
|
bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
|
||||||
n = 0; /* number of bits currently in bitbuffer */
|
n = 0; /* number of bits currently in bitbuffer */
|
||||||
|
|
||||||
for( x = 0; x<bmpinfo.w; x++ )
|
for( x = 0; x<bmpinfo.w; x++ )
|
||||||
{
|
{
|
||||||
if( n < bmpinfo.bits )
|
if( n < bmpinfo.bits )
|
||||||
|
@ -683,10 +790,11 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
bitbuf |= b << (INTBITS - 8 - n);
|
bitbuf |= b << (INTBITS - 8 - n);
|
||||||
n += 8;
|
n += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = bitbuf >> (INTBITS - bmpinfo.bits);
|
b = bitbuf >> (INTBITS - bmpinfo.bits);
|
||||||
bitbuf <<= bmpinfo.bits;
|
bitbuf <<= bmpinfo.bits;
|
||||||
n -= bmpinfo.bits;
|
n -= bmpinfo.bits;
|
||||||
BM_UPUT( bm, x, y, coltable[b] );
|
BM_UPUT( bm, x, ycorr( y ), coltable[b] );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -695,7 +803,6 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x010: /* 16-bit encoding */
|
case 0x010: /* 16-bit encoding */
|
||||||
|
|
||||||
/* can't do this format because it is not well-documented and I
|
/* can't do this format because it is not well-documented and I
|
||||||
* don't have any samples */
|
* don't have any samples */
|
||||||
bm_read_error = "cannot handle bmp 16-bit coding";
|
bm_read_error = "cannot handle bmp 16-bit coding";
|
||||||
|
@ -704,14 +811,39 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
|
|
||||||
case 0x018: /* 24-bit encoding */
|
case 0x018: /* 24-bit encoding */
|
||||||
case 0x020: /* 32-bit encoding */
|
case 0x020: /* 32-bit encoding */
|
||||||
|
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y<bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
|
|
||||||
for( x = 0; x<bmpinfo.w; x++ )
|
for( x = 0; x<bmpinfo.w; x++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
||||||
c = ( (c >> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff);
|
c = ( (c >> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff);
|
||||||
BM_UPUT( bm, x, y, c > 3 * threshold * 255 ? 0 : 1 );
|
BM_UPUT( bm, x, ycorr( y ), c > 3 * threshold * 255 ? 0 : 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
TRY( bmp_pad( f ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x320: /* 32-bit encoding with bitfields */
|
||||||
|
redshift = lobit( bmpinfo.RedMask );
|
||||||
|
greenshift = lobit( bmpinfo.GreenMask );
|
||||||
|
blueshift = lobit( bmpinfo.BlueMask );
|
||||||
|
|
||||||
|
for( y = 0; y<bmpinfo.h; y++ )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -720,17 +852,20 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
|
case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
||||||
|
|
||||||
if( b>0 )
|
if( b>0 )
|
||||||
{
|
{
|
||||||
/* repeat count */
|
/* repeat count */
|
||||||
col[0] = coltable[(c >> 4) & 0xf];
|
col[0] = coltable[(c >> 4) & 0xf];
|
||||||
col[1] = coltable[c & 0xf];
|
col[1] = coltable[c & 0xf];
|
||||||
|
|
||||||
for( i = 0; i<b && x<bmpinfo.w; i++ )
|
for( i = 0; i<b && x<bmpinfo.w; i++ )
|
||||||
{
|
{
|
||||||
if( x>=bmpinfo.w )
|
if( x>=bmpinfo.w )
|
||||||
|
@ -738,11 +873,13 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( y>=bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BM_UPUT( bm, x, y, col[i & 1] );
|
|
||||||
|
BM_UPUT( bm, x, ycorr( y ), col[i & 1] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -762,8 +899,8 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
/* "delta": skip pixels in x and y directions */
|
/* "delta": skip pixels in x and y directions */
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
|
||||||
x += b;
|
x += b;
|
||||||
y += c;
|
y += c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -774,16 +911,19 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( x>=bmpinfo.w )
|
if( x>=bmpinfo.w )
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( y>=bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BM_PUT( bm, x, y, coltable[( b >> ( 4 - 4 * (i & 1) ) ) & 0xf] );
|
|
||||||
|
BM_PUT( bm, x, ycorr( y ), coltable[( b >> ( 4 - 4 * (i & 1) ) ) & 0xf] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,12 +938,14 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
|
case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
||||||
|
|
||||||
if( b>0 )
|
if( b>0 )
|
||||||
{
|
{
|
||||||
/* repeat count */
|
/* repeat count */
|
||||||
|
@ -814,11 +956,13 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( y>=bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BM_UPUT( bm, x, y, coltable[c] );
|
|
||||||
|
BM_UPUT( bm, x, ycorr( y ), coltable[c] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -838,8 +982,8 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
/* "delta": skip pixels in x and y directions */
|
/* "delta": skip pixels in x and y directions */
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
|
||||||
x += b;
|
x += b;
|
||||||
y += c;
|
y += c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -847,16 +991,19 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
for( i = 0; i<c; i++ )
|
for( i = 0; i<c; i++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
|
|
||||||
if( x>=bmpinfo.w )
|
if( x>=bmpinfo.w )
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( y>=bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BM_PUT( bm, x, y, coltable[b] );
|
|
||||||
|
BM_PUT( bm, x, ycorr( y ), coltable[b] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,10 +1035,12 @@ format_error:
|
||||||
try_error:
|
try_error:
|
||||||
free( coltable );
|
free( coltable );
|
||||||
free( bm );
|
free( bm );
|
||||||
|
|
||||||
if( !bm_read_error )
|
if( !bm_read_error )
|
||||||
{
|
{
|
||||||
bm_read_error = "invalid bmp file";
|
bm_read_error = "invalid bmp file";
|
||||||
}
|
}
|
||||||
|
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
std_error:
|
std_error:
|
||||||
|
@ -908,24 +1057,23 @@ void bm_writepbm( FILE* f, potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
int w, h, bpr, y, i, c;
|
int w, h, bpr, y, i, c;
|
||||||
|
|
||||||
w = bm->w;
|
w = bm->w;
|
||||||
h = bm->h;
|
h = bm->h;
|
||||||
|
|
||||||
bpr = (w + 7) / 8;
|
bpr = (w + 7) / 8;
|
||||||
|
|
||||||
fprintf( f, "P4\n%d %d\n", w, h );
|
fprintf( f, "P4\n%d %d\n", w, h );
|
||||||
|
|
||||||
for( y = h - 1; y>=0; y-- )
|
for( y = h - 1; y>=0; y-- )
|
||||||
{
|
{
|
||||||
for( i = 0; i<bpr; i++ )
|
for( i = 0; i<bpr; i++ )
|
||||||
{
|
{
|
||||||
c =
|
c =
|
||||||
( *bm_index( bm, i * 8,
|
( *bm_index( bm, i * 8,
|
||||||
y ) >> ( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) ) ) & 0xff;
|
y ) >> ( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) ) ) & 0xff;
|
||||||
fputc( c, f );
|
fputc( c, f );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -940,14 +1088,15 @@ int bm_print( FILE* f, potrace_bitmap_t* bm )
|
||||||
int d;
|
int d;
|
||||||
int sw, sh;
|
int sw, sh;
|
||||||
|
|
||||||
sw = bm->w < 79 ? bm->w : 79;
|
sw = bm->w < 79 ? bm->w : 79;
|
||||||
sh = bm->w < 79 ? bm->h : bm->h * sw * 44 / (79 * bm->w);
|
sh = bm->w < 79 ? bm->h : bm->h * sw * 44 / (79 * bm->w);
|
||||||
|
|
||||||
for( yy = sh - 1; yy>=0; yy-- )
|
for( yy = sh - 1; yy>=0; yy-- )
|
||||||
{
|
{
|
||||||
for( xx = 0; xx<sw; xx++ )
|
for( xx = 0; xx<sw; xx++ )
|
||||||
{
|
{
|
||||||
d = 0;
|
d = 0;
|
||||||
|
|
||||||
for( x = xx * bm->w / sw; x<(xx + 1) * bm->w / sw; x++ )
|
for( x = xx * bm->w / sw; x<(xx + 1) * bm->w / sw; x++ )
|
||||||
{
|
{
|
||||||
for( y = yy * bm->h / sh; y<(yy + 1) * bm->h / sh; y++ )
|
for( y = yy * bm->h / sh; y<(yy + 1) * bm->h / sh; y++ )
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: bitmap_io.h 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
/* bitmap input/output functions */
|
/* bitmap input/output functions */
|
||||||
|
|
||||||
#ifndef BITMAP_IO_H
|
#ifndef BITMAP_IO_H
|
||||||
#define BITMAP_IO_H
|
#define BITMAP_IO_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <bitmap.h>
|
#include "bitmap.h"
|
||||||
|
|
||||||
/* Note that bitmaps are stored bottom to top, i.e., the first
|
/* Note that bitmaps are stored bottom to top, i.e., the first
|
||||||
* scanline is the bottom-most one */
|
* scanline is the bottom-most one */
|
||||||
|
|
||||||
extern char* bm_read_error;
|
extern const char* bm_read_error;
|
||||||
|
|
||||||
int bm_read( FILE* f, double blacklevel, potrace_bitmap_t** bmp );
|
int bm_read( FILE* f, double blacklevel, potrace_bitmap_t** bmp );
|
||||||
void bm_writepbm( FILE* f, potrace_bitmap_t* bm );
|
void bm_writepbm( FILE* f, potrace_bitmap_t* bm );
|
||||||
int bm_print( FILE* f, potrace_bitmap_t* bm );
|
int bm_print( FILE* f, potrace_bitmap_t* bm );
|
||||||
|
|
||||||
#endif /* BITMAP_IO_H */
|
#endif /* BITMAP_IO_H */
|
||||||
|
|
116
potrace/bitops.h
116
potrace/bitops.h
|
@ -1,50 +1,102 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: bitops.h 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
|
|
||||||
/* bits.h: this file defines some macros for bit manipulations. We
|
/* bits.h: this file defines some macros for bit manipulations. We
|
||||||
provide a generic implementation */
|
* provide a generic implementation, as well as machine- and
|
||||||
|
* compiler-specific fast implementations */
|
||||||
|
|
||||||
/* lobit: return the position of the rightmost "1" bit of an int, or
|
/* lobit: return the position of the rightmost "1" bit of an int, or
|
||||||
32 if none. hibit: return 1 + the position of the leftmost "1" bit
|
* 32 if none. hibit: return 1 + the position of the leftmost "1" bit
|
||||||
of an int, or 0 if none. Note: these functions work on 32-bit
|
* of an int, or 0 if none. Note: these functions work on 32-bit
|
||||||
integers. */
|
* integers. */
|
||||||
|
|
||||||
#ifndef BITOPS_H
|
#ifndef BITOPS_H
|
||||||
#define BITOPS_H
|
#define BITOPS_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* generic macros */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
/* machine specific macros */
|
||||||
|
|
||||||
static inline unsigned int lobit(unsigned int x) {
|
#if defined(HAVE_I386)
|
||||||
unsigned int res = 32;
|
|
||||||
while (x & 0xffffff) {
|
static inline unsigned int lobit( unsigned int x )
|
||||||
x <<= 8;
|
{
|
||||||
res -= 8;
|
unsigned int res;
|
||||||
}
|
|
||||||
while (x) {
|
asm ("bsf %1,%0\n\t"
|
||||||
x <<= 1;
|
"jnz 0f\n\t"
|
||||||
res -= 1;
|
"movl $32,%0\n"
|
||||||
}
|
"0:"
|
||||||
return res;
|
: "=r" (res)
|
||||||
|
: "r" (x)
|
||||||
|
: "cc");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int hibit(unsigned int x) {
|
|
||||||
unsigned int res = 0;
|
static inline unsigned int hibit( unsigned int x )
|
||||||
while (x > 0xff) {
|
{
|
||||||
x >>= 8;
|
unsigned int res;
|
||||||
res += 8;
|
|
||||||
}
|
asm ("bsr %1,%0\n\t"
|
||||||
while (x) {
|
"jnz 0f\n\t"
|
||||||
x >>= 1;
|
"movl $-1,%0\n"
|
||||||
res += 1;
|
"0:"
|
||||||
}
|
: "=r" (res)
|
||||||
return res;
|
: "r" (x)
|
||||||
|
: "cc");
|
||||||
|
return res + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
#else /* generic macros */
|
||||||
|
|
||||||
|
static inline unsigned int lobit( unsigned int x )
|
||||||
|
{
|
||||||
|
unsigned int res = 32;
|
||||||
|
|
||||||
|
while( x & 0xffffff )
|
||||||
|
{
|
||||||
|
x <<= 8;
|
||||||
|
res -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( x )
|
||||||
|
{
|
||||||
|
x <<= 1;
|
||||||
|
res -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline unsigned int hibit( unsigned int x )
|
||||||
|
{
|
||||||
|
unsigned int res = 0;
|
||||||
|
|
||||||
|
while( x > 0xff )
|
||||||
|
{
|
||||||
|
x >>= 8;
|
||||||
|
res += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( x )
|
||||||
|
{
|
||||||
|
x >>= 1;
|
||||||
|
res += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* BITOPS_H */
|
#endif /* BITOPS_H */
|
||||||
|
|
|
@ -1,38 +1,37 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: curve.c 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
/* private part of the path and curve data structures */
|
/* private part of the path and curve data structures */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <potracelib.h>
|
#include "potracelib.h"
|
||||||
#include <lists.h>
|
#include "lists.h"
|
||||||
#include <curve.h>
|
#include "curve.h"
|
||||||
|
|
||||||
#define SAFE_MALLOC( var, n, typ ) \
|
#define SAFE_CALLOC( var, n, typ ) \
|
||||||
if( ( var = (typ*) malloc( (n)* sizeof(typ) ) ) == NULL ) \
|
if( ( var = (typ*) calloc( n, sizeof(typ) ) ) == NULL ) \
|
||||||
goto malloc_error
|
goto calloc_error
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* allocate and free path objects */
|
/* allocate and free path objects */
|
||||||
|
|
||||||
path_t* path_new( void )
|
path_t* path_new( void )
|
||||||
{
|
{
|
||||||
path_t* p = NULL;
|
path_t* p = NULL;
|
||||||
privpath_t* priv = NULL;
|
privpath_t* priv = NULL;
|
||||||
|
|
||||||
SAFE_MALLOC( p, 1, path_t );
|
SAFE_CALLOC( p, 1, path_t );
|
||||||
memset( p, 0, sizeof(path_t) );
|
memset( p, 0, sizeof(path_t) );
|
||||||
SAFE_MALLOC( priv, 1, privpath_t );
|
SAFE_CALLOC( priv, 1, privpath_t );
|
||||||
memset( priv, 0, sizeof(privpath_t) );
|
memset( priv, 0, sizeof(privpath_t) );
|
||||||
p->priv = priv;
|
p->priv = priv;
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
malloc_error:
|
calloc_error:
|
||||||
free( p );
|
free( p );
|
||||||
free( priv );
|
free( priv );
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -65,9 +64,11 @@ void path_free( path_t* p )
|
||||||
privcurve_free_members( &p->priv->curve );
|
privcurve_free_members( &p->priv->curve );
|
||||||
privcurve_free_members( &p->priv->ocurve );
|
privcurve_free_members( &p->priv->ocurve );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( p->priv );
|
free( p->priv );
|
||||||
/* do not free p->fcurve ! */
|
/* do not free p->fcurve ! */
|
||||||
}
|
}
|
||||||
|
|
||||||
free( p );
|
free( p );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,15 +95,15 @@ int privcurve_init( privcurve_t* curve, int n )
|
||||||
{
|
{
|
||||||
memset( curve, 0, sizeof(privcurve_t) );
|
memset( curve, 0, sizeof(privcurve_t) );
|
||||||
curve->n = n;
|
curve->n = n;
|
||||||
SAFE_MALLOC( curve->tag, n, int );
|
SAFE_CALLOC( curve->tag, n, int );
|
||||||
SAFE_MALLOC( curve->c, n, dpoint3_t );
|
SAFE_CALLOC( curve->c, n, dpoint3_t );
|
||||||
SAFE_MALLOC( curve->vertex, n, dpoint_t );
|
SAFE_CALLOC( curve->vertex, n, dpoint_t );
|
||||||
SAFE_MALLOC( curve->alpha, n, double );
|
SAFE_CALLOC( curve->alpha, n, double );
|
||||||
SAFE_MALLOC( curve->alpha0, n, double );
|
SAFE_CALLOC( curve->alpha0, n, double );
|
||||||
SAFE_MALLOC( curve->beta, n, double );
|
SAFE_CALLOC( curve->beta, n, double );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
malloc_error:
|
calloc_error:
|
||||||
free( curve->tag );
|
free( curve->tag );
|
||||||
free( curve->c );
|
free( curve->c );
|
||||||
free( curve->vertex );
|
free( curve->vertex );
|
||||||
|
@ -116,7 +117,7 @@ malloc_error:
|
||||||
/* copy private to public curve structure */
|
/* copy private to public curve structure */
|
||||||
void privcurve_to_curve( privcurve_t* pc, potrace_curve_t* c )
|
void privcurve_to_curve( privcurve_t* pc, potrace_curve_t* c )
|
||||||
{
|
{
|
||||||
c->n = pc->n;
|
c->n = pc->n;
|
||||||
c->tag = pc->tag;
|
c->tag = pc->tag;
|
||||||
c->c = pc->c;
|
c->c = pc->c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
#ifndef CURVE_H
|
#ifndef CURVE_H
|
||||||
#define CURVE_H
|
#define CURVE_H
|
||||||
|
|
||||||
#include <auxiliary.h>
|
#include "auxiliary.h"
|
||||||
|
|
||||||
/* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of
|
/* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of
|
||||||
* .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only
|
* .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only
|
||||||
|
@ -17,29 +17,28 @@
|
||||||
|
|
||||||
struct privcurve_s
|
struct privcurve_s
|
||||||
{
|
{
|
||||||
int n; /* number of segments */
|
int n; /* number of segments */
|
||||||
int* tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
|
int* tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
|
||||||
dpoint_t( * c )[3]; /* c[n][i]: control points.
|
dpoint_t( *c )[3]; /* c[n][i]: control points.
|
||||||
* c[n][0] is unused for tag[n]=POTRACE_CORNER */
|
* c[n][0] is unused for tag[n]=POTRACE_CORNER */
|
||||||
|
|
||||||
/* the remainder of this structure is special to privcurve, and is
|
/* the remainder of this structure is special to privcurve, and is
|
||||||
* used in EPS debug output and special EPS "short coding". These
|
* used in EPS debug output and special EPS "short coding". These
|
||||||
* fields are valid only if "alphacurve" is set. */
|
* fields are valid only if "alphacurve" is set. */
|
||||||
int alphacurve; /* have the following fields been initialized? */
|
int alphacurve; /* have the following fields been initialized? */
|
||||||
dpoint_t* vertex; /* for POTRACE_CORNER, this equals c[1] */
|
dpoint_t* vertex; /* for POTRACE_CORNER, this equals c[1] */
|
||||||
double* alpha; /* only for POTRACE_CURVETO */
|
double* alpha; /* only for POTRACE_CURVETO */
|
||||||
double* alpha0; /* "uncropped" alpha parameter - for debug output only */
|
double* alpha0; /* "uncropped" alpha parameter - for debug output only */
|
||||||
double* beta;
|
double* beta;
|
||||||
};
|
};
|
||||||
typedef struct privcurve_s privcurve_t;
|
typedef struct privcurve_s privcurve_t;
|
||||||
|
|
||||||
struct sums_s
|
struct sums_s
|
||||||
{
|
{
|
||||||
double x;
|
double x;
|
||||||
double y;
|
double y;
|
||||||
double x2;
|
double x2;
|
||||||
double xy;
|
double xy;
|
||||||
double y2;
|
double y2;
|
||||||
};
|
};
|
||||||
typedef struct sums_s sums_t;
|
typedef struct sums_s sums_t;
|
||||||
|
|
||||||
|
@ -50,26 +49,26 @@ typedef struct sums_s sums_t;
|
||||||
* other fields. */
|
* other fields. */
|
||||||
struct potrace_privpath_s
|
struct potrace_privpath_s
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
point_t* pt; /* pt[len]: path as extracted from bitmap */
|
point_t* pt; /* pt[len]: path as extracted from bitmap */
|
||||||
int* lon; /* lon[len]: (i,lon[i]) = longest straight line from i */
|
int* lon; /* lon[len]: (i,lon[i]) = longest straight line from i */
|
||||||
|
|
||||||
int x0, y0; /* origin for sums */
|
int x0, y0; /* origin for sums */
|
||||||
sums_t* sums; /* sums[len+1]: cache for fast summing */
|
sums_t* sums; /* sums[len+1]: cache for fast summing */
|
||||||
|
|
||||||
int m; /* length of optimal polygon */
|
int m; /* length of optimal polygon */
|
||||||
int* po; /* po[m]: optimal polygon */
|
int* po; /* po[m]: optimal polygon */
|
||||||
|
|
||||||
privcurve_t curve; /* curve[m]: array of curve elements */
|
privcurve_t curve; /* curve[m]: array of curve elements */
|
||||||
privcurve_t ocurve; /* ocurve[om]: array of curve elements */
|
privcurve_t ocurve; /* ocurve[om]: array of curve elements */
|
||||||
privcurve_t* fcurve; /* final curve: this points to either curve or
|
privcurve_t* fcurve; /* final curve: this points to either curve or
|
||||||
* ocurve. Do not free this separately. */
|
* ocurve. Do not free this separately. */
|
||||||
};
|
};
|
||||||
typedef struct potrace_privpath_s potrace_privpath_t;
|
typedef struct potrace_privpath_s potrace_privpath_t;
|
||||||
|
|
||||||
/* shorter names */
|
/* shorter names */
|
||||||
typedef potrace_privpath_t privpath_t;
|
typedef potrace_privpath_t privpath_t;
|
||||||
typedef potrace_path_t path_t;
|
typedef potrace_path_t path_t;
|
||||||
|
|
||||||
path_t* path_new( void );
|
path_t* path_new( void );
|
||||||
void path_free( path_t* p );
|
void path_free( path_t* p );
|
||||||
|
|
|
@ -1,21 +1,50 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: decompose.c 146 2007-04-09 00:43:46Z selinger $ */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include <potracelib.h>
|
#include "potracelib.h"
|
||||||
#include <curve.h>
|
#include "curve.h"
|
||||||
#include <lists.h>
|
#include "lists.h"
|
||||||
#include <auxiliary.h>
|
#include "bitmap.h"
|
||||||
#include <bitmap.h>
|
#include "decompose.h"
|
||||||
#include <decompose.h>
|
#include "progress.h"
|
||||||
#include <progress.h>
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
|
||||||
|
|
||||||
|
static inline int detrand( int x, int y )
|
||||||
|
{
|
||||||
|
unsigned int z;
|
||||||
|
static const unsigned char t[256] =
|
||||||
|
{
|
||||||
|
/* 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
|
||||||
|
* 5-bit sequence */
|
||||||
|
z = ( (0x04b3e375 * x) ^ y ) * 0x05a8ef93;
|
||||||
|
z = t[z & 0xff] ^ t[(z >> 8) & 0xff] ^ t[(z >> 16) & 0xff] ^ t[(z >> 24) & 0xff];
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* auxiliary bitmap manipulations */
|
/* auxiliary bitmap manipulations */
|
||||||
|
@ -24,11 +53,12 @@
|
||||||
static void bm_clearexcess( potrace_bitmap_t* bm )
|
static void bm_clearexcess( potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
potrace_word mask;
|
potrace_word mask;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
if( bm->w % BM_WORDBITS != 0 )
|
if( bm->w % BM_WORDBITS != 0 )
|
||||||
{
|
{
|
||||||
mask = BM_ALLBITS << ( BM_WORDBITS - (bm->w % BM_WORDBITS) );
|
mask = BM_ALLBITS << ( BM_WORDBITS - (bm->w % BM_WORDBITS) );
|
||||||
|
|
||||||
for( y = 0; y<bm->h; y++ )
|
for( y = 0; y<bm->h; y++ )
|
||||||
{
|
{
|
||||||
*bm_index( bm, bm->w, y ) &= mask;
|
*bm_index( bm, bm->w, y ) &= mask;
|
||||||
|
@ -64,35 +94,6 @@ static void clear_bm_with_bbox( potrace_bitmap_t* bm, bbox_t* bbox )
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* auxiliary functions */
|
/* auxiliary functions */
|
||||||
|
|
||||||
/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
|
|
||||||
static inline int detrand( int x, int y )
|
|
||||||
{
|
|
||||||
unsigned int z;
|
|
||||||
static const unsigned char t[256] =
|
|
||||||
{
|
|
||||||
/* 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
|
|
||||||
* 5-bit sequence */
|
|
||||||
z = ( (0x04b3e375 * x) ^ y ) * 0x05a8ef93;
|
|
||||||
z = t[z & 0xff] ^ t[(z >> 8) & 0xff] ^ t[(z >> 16) & 0xff] ^ t[(z >> 24) & 0xff];
|
|
||||||
return z & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* return the "majority" value of bitmap bm at intersection (x,y). We
|
/* return the "majority" value of bitmap bm at intersection (x,y). We
|
||||||
* assume that the bitmap is balanced at "radius" 1. */
|
* assume that the bitmap is balanced at "radius" 1. */
|
||||||
static int majority( potrace_bitmap_t* bm, int x, int y )
|
static int majority( potrace_bitmap_t* bm, int x, int y )
|
||||||
|
@ -102,12 +103,13 @@ static int majority( potrace_bitmap_t* bm, int x, int y )
|
||||||
for( i = 2; i<5; i++ ) /* check at "radius" i */
|
for( i = 2; i<5; i++ ) /* check at "radius" i */
|
||||||
{
|
{
|
||||||
ct = 0;
|
ct = 0;
|
||||||
|
|
||||||
for( a = -i + 1; a<=i - 1; a++ )
|
for( a = -i + 1; a<=i - 1; a++ )
|
||||||
{
|
{
|
||||||
ct += BM_GET( bm, x + a, y + i - 1 ) ? 1 : -1;
|
ct += BM_GET( bm, x + a, y + i - 1 ) ? 1 : -1;
|
||||||
ct += BM_GET( bm, x + i - 1, y + a - 1 ) ? 1 : -1;
|
ct += BM_GET( bm, x + i - 1, y + a - 1 ) ? 1 : -1;
|
||||||
ct += BM_GET( bm, x + a - 1, y - i ) ? 1 : -1;
|
ct += BM_GET( bm, x + a - 1, y - i ) ? 1 : -1;
|
||||||
ct += BM_GET( bm, x - i, y + a ) ? 1 : -1;
|
ct += BM_GET( bm, x - i, y + a ) ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ct>0 )
|
if( ct>0 )
|
||||||
|
@ -179,6 +181,7 @@ static void xor_path( potrace_bitmap_t* bm, path_t* p )
|
||||||
y1 = p->priv->pt[p->priv->len - 1].y;
|
y1 = p->priv->pt[p->priv->len - 1].y;
|
||||||
|
|
||||||
xa = p->priv->pt[0].x & - BM_WORDBITS;
|
xa = p->priv->pt[0].x & - BM_WORDBITS;
|
||||||
|
|
||||||
for( k = 0; k<p->priv->len; k++ )
|
for( k = 0; k<p->priv->len; k++ )
|
||||||
{
|
{
|
||||||
x = p->priv->pt[k].x;
|
x = p->priv->pt[k].x;
|
||||||
|
@ -215,14 +218,17 @@ static void setbbox_path( bbox_t* bbox, path_t* p )
|
||||||
{
|
{
|
||||||
bbox->x0 = x;
|
bbox->x0 = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( x > bbox->x1 )
|
if( x > bbox->x1 )
|
||||||
{
|
{
|
||||||
bbox->x1 = x;
|
bbox->x1 = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y < bbox->y0 )
|
if( y < bbox->y0 )
|
||||||
{
|
{
|
||||||
bbox->y0 = y;
|
bbox->y0 = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y > bbox->y1 )
|
if( y > bbox->y1 )
|
||||||
{
|
{
|
||||||
bbox->y1 = y;
|
bbox->y1 = y;
|
||||||
|
@ -239,18 +245,18 @@ static void setbbox_path( bbox_t* bbox, path_t* p )
|
||||||
* of turnpolicies. */
|
* of turnpolicies. */
|
||||||
static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int turnpolicy )
|
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, area;
|
||||||
int c, d, tmp;
|
int c, d, tmp;
|
||||||
point_t* pt, * pt1;
|
point_t* pt, * pt1;
|
||||||
path_t* p = NULL;
|
path_t* p = NULL;
|
||||||
|
|
||||||
x = x0;
|
x = x0;
|
||||||
y = y0;
|
y = y0;
|
||||||
dirx = 0;
|
dirx = 0;
|
||||||
diry = -1;
|
diry = -1;
|
||||||
|
|
||||||
len = size = 0;
|
len = size = 0;
|
||||||
pt = NULL;
|
pt = NULL;
|
||||||
area = 0;
|
area = 0;
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
|
@ -259,21 +265,24 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
||||||
if( len>=size )
|
if( len>=size )
|
||||||
{
|
{
|
||||||
size += 100;
|
size += 100;
|
||||||
size = (int) ( 1.3 * size );
|
size = (int) (1.3 * size);
|
||||||
pt1 = (point_t*) realloc( pt, size * sizeof(point_t) );
|
pt1 = (point_t*) realloc( pt, size * sizeof(point_t) );
|
||||||
|
|
||||||
if( !pt1 )
|
if( !pt1 )
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
pt = pt1;
|
pt = pt1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pt[len].x = x;
|
pt[len].x = x;
|
||||||
pt[len].y = y;
|
pt[len].y = y;
|
||||||
len++;
|
len++;
|
||||||
|
|
||||||
/* move to next point */
|
/* move to next point */
|
||||||
x += dirx;
|
x += dirx;
|
||||||
y += diry;
|
y += diry;
|
||||||
area += x * diry;
|
area += x * diry;
|
||||||
|
|
||||||
/* path complete? */
|
/* path complete? */
|
||||||
|
@ -289,32 +298,32 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
||||||
if( c && !d ) /* ambiguous turn */
|
if( c && !d ) /* ambiguous turn */
|
||||||
{
|
{
|
||||||
if( turnpolicy == POTRACE_TURNPOLICY_RIGHT
|
if( turnpolicy == POTRACE_TURNPOLICY_RIGHT
|
||||||
|| (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
|
|| (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
|
||||||
|| (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
|
|| (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
|
||||||
|| ( turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand( x, y ) )
|
|| ( turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand( x, y ) )
|
||||||
|| ( turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority( bm, x, y ) )
|
|| ( turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority( bm, x, y ) )
|
||||||
|| ( turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority( bm, x, y ) ) )
|
|| ( turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority( bm, x, y ) ) )
|
||||||
{
|
{
|
||||||
tmp = dirx; /* right turn */
|
tmp = dirx; /* right turn */
|
||||||
dirx = diry;
|
dirx = diry;
|
||||||
diry = -tmp;
|
diry = -tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tmp = dirx; /* left turn */
|
tmp = dirx; /* left turn */
|
||||||
dirx = -diry;
|
dirx = -diry;
|
||||||
diry = tmp;
|
diry = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( c ) /* right turn */
|
else if( c ) /* right turn */
|
||||||
{
|
{
|
||||||
tmp = dirx;
|
tmp = dirx;
|
||||||
dirx = diry;
|
dirx = diry;
|
||||||
diry = -tmp;
|
diry = -tmp;
|
||||||
}
|
}
|
||||||
else if( !d ) /* left turn */
|
else if( !d ) /* left turn */
|
||||||
{
|
{
|
||||||
tmp = dirx;
|
tmp = dirx;
|
||||||
dirx = -diry;
|
dirx = -diry;
|
||||||
diry = tmp;
|
diry = tmp;
|
||||||
}
|
}
|
||||||
|
@ -322,12 +331,13 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
||||||
|
|
||||||
/* allocate new path object */
|
/* allocate new path object */
|
||||||
p = path_new();
|
p = path_new();
|
||||||
|
|
||||||
if( !p )
|
if( !p )
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->priv->pt = pt;
|
p->priv->pt = pt;
|
||||||
p->priv->len = len;
|
p->priv->len = len;
|
||||||
p->area = area;
|
p->area = area;
|
||||||
p->sign = sign;
|
p->sign = sign;
|
||||||
|
@ -358,18 +368,19 @@ error:
|
||||||
|
|
||||||
static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
path_t* p, * p1;
|
path_t* p, * p1;
|
||||||
path_t* heap, * heap1;
|
path_t* heap, * heap1;
|
||||||
path_t* cur;
|
path_t* cur;
|
||||||
path_t* head;
|
path_t* head;
|
||||||
path_t** hook, ** hook_in, ** hook_out; /* for fast appending to linked list */
|
path_t** plist_hook; /* for fast appending to linked list */
|
||||||
bbox_t bbox;
|
path_t** hook_in, ** hook_out; /* for fast appending to linked list */
|
||||||
|
bbox_t bbox;
|
||||||
|
|
||||||
bm_clear( bm, 0 );
|
bm_clear( bm, 0 );
|
||||||
|
|
||||||
/* save original "next" pointers */
|
/* save original "next" pointers */
|
||||||
list_forall( p, plist ) {
|
list_forall( p, plist ) {
|
||||||
p->sibling = p->next;
|
p->sibling = p->next;
|
||||||
p->childlist = NULL;
|
p->childlist = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,13 +396,13 @@ static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
||||||
while( heap )
|
while( heap )
|
||||||
{
|
{
|
||||||
/* unlink first sublist */
|
/* unlink first sublist */
|
||||||
cur = heap;
|
cur = heap;
|
||||||
heap = heap->childlist;
|
heap = heap->childlist;
|
||||||
cur->childlist = NULL;
|
cur->childlist = NULL;
|
||||||
|
|
||||||
/* unlink first path */
|
/* unlink first path */
|
||||||
head = cur;
|
head = cur;
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
head->next = NULL;
|
head->next = NULL;
|
||||||
|
|
||||||
/* render path */
|
/* render path */
|
||||||
|
@ -401,7 +412,7 @@ static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
||||||
/* now do insideness test for each element of cur; append it to
|
/* now do insideness test for each element of cur; append it to
|
||||||
* head->childlist if it's inside head, else append it to
|
* head->childlist if it's inside head, else append it to
|
||||||
* head->next. */
|
* head->next. */
|
||||||
hook_in = &head->childlist;
|
hook_in = &head->childlist;
|
||||||
hook_out = &head->next;
|
hook_out = &head->next;
|
||||||
list_forall_unlink( p, cur ) {
|
list_forall_unlink( p, cur ) {
|
||||||
if( p->priv->pt[0].y <= bbox.y0 )
|
if( p->priv->pt[0].y <= bbox.y0 )
|
||||||
|
@ -411,6 +422,7 @@ static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
||||||
*hook_out = cur;
|
*hook_out = cur;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( BM_GET( bm, p->priv->pt[0].x, p->priv->pt[0].y - 1 ) )
|
if( BM_GET( bm, p->priv->pt[0].x, p->priv->pt[0].y - 1 ) )
|
||||||
{
|
{
|
||||||
list_insert_beforehook( p, hook_in );
|
list_insert_beforehook( p, hook_in );
|
||||||
|
@ -431,6 +443,7 @@ static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
||||||
head->next->childlist = heap;
|
head->next->childlist = heap;
|
||||||
heap = head->next;
|
heap = head->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( head->childlist )
|
if( head->childlist )
|
||||||
{
|
{
|
||||||
head->childlist->childlist = heap;
|
head->childlist->childlist = heap;
|
||||||
|
@ -440,6 +453,7 @@ static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
||||||
|
|
||||||
/* copy sibling structure from "next" to "sibling" component */
|
/* copy sibling structure from "next" to "sibling" component */
|
||||||
p = plist;
|
p = plist;
|
||||||
|
|
||||||
while( p )
|
while( p )
|
||||||
{
|
{
|
||||||
p1 = p->sibling;
|
p1 = p->sibling;
|
||||||
|
@ -453,26 +467,31 @@ static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
||||||
* contains a list of childlists which still need to be
|
* contains a list of childlists which still need to be
|
||||||
* processed. */
|
* processed. */
|
||||||
heap = plist;
|
heap = plist;
|
||||||
|
|
||||||
if( heap )
|
if( heap )
|
||||||
{
|
{
|
||||||
heap->next = NULL; /* heap is a linked list of childlists */
|
heap->next = NULL; /* heap is a linked list of childlists */
|
||||||
}
|
}
|
||||||
|
|
||||||
plist = NULL;
|
plist = NULL;
|
||||||
hook = &plist;
|
plist_hook = &plist;
|
||||||
|
|
||||||
while( heap )
|
while( heap )
|
||||||
{
|
{
|
||||||
heap1 = heap->next;
|
heap1 = heap->next;
|
||||||
|
|
||||||
for( p = heap; p; p = p->sibling )
|
for( p = heap; p; p = p->sibling )
|
||||||
{
|
{
|
||||||
/* p is a positive path */
|
/* p is a positive path */
|
||||||
/* append to linked list */
|
/* append to linked list */
|
||||||
list_insert_beforehook( p, hook );
|
list_insert_beforehook( p, plist_hook );
|
||||||
|
|
||||||
/* go through its children */
|
/* go through its children */
|
||||||
for( p1 = p->childlist; p1; p1 = p1->sibling )
|
for( p1 = p->childlist; p1; p1 = p1->sibling )
|
||||||
{
|
{
|
||||||
/* append to linked list */
|
/* append to linked list */
|
||||||
list_insert_beforehook( p1, hook );
|
list_insert_beforehook( p1, plist_hook );
|
||||||
|
|
||||||
/* append its childlist to heap, if non-empty */
|
/* append its childlist to heap, if non-empty */
|
||||||
if( p1->childlist )
|
if( p1->childlist )
|
||||||
{
|
{
|
||||||
|
@ -483,8 +502,6 @@ static void pathlist_to_tree( path_t* plist, potrace_bitmap_t* bm )
|
||||||
|
|
||||||
heap = heap1;
|
heap = heap1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -497,10 +514,13 @@ static int findnext( potrace_bitmap_t* bm, int* xp, int* yp )
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
int x0;
|
||||||
|
|
||||||
|
x0 = (*xp) & ~(BM_WORDBITS - 1);
|
||||||
|
|
||||||
for( y = *yp; y>=0; y-- )
|
for( y = *yp; y>=0; y-- )
|
||||||
{
|
{
|
||||||
for( x = 0; x<bm->w; x += BM_WORDBITS )
|
for( x = x0; x<bm->w; x += BM_WORDBITS )
|
||||||
{
|
{
|
||||||
if( *bm_index( bm, x, y ) )
|
if( *bm_index( bm, x, y ) )
|
||||||
{
|
{
|
||||||
|
@ -515,6 +535,8 @@ static int findnext( potrace_bitmap_t* bm, int* xp, int* yp )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x0 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not found */
|
/* not found */
|
||||||
|
@ -528,19 +550,20 @@ static int findnext( potrace_bitmap_t* bm, int* xp, int* yp )
|
||||||
* set. */
|
* set. */
|
||||||
|
|
||||||
int bm_to_pathlist( const potrace_bitmap_t* bm,
|
int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||||
path_t** plistp,
|
path_t** plistp,
|
||||||
const potrace_param_t* param,
|
const potrace_param_t* param,
|
||||||
progress_t* progress )
|
progress_t* progress )
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
path_t* p;
|
path_t* p;
|
||||||
path_t* plist = NULL; /* linked list of path objects */
|
path_t* plist = NULL; /* linked list of path objects */
|
||||||
path_t** hook = &plist; /* used to speed up appending to linked list */
|
path_t** plist_hook = &plist; /* used to speed up appending to linked list */
|
||||||
potrace_bitmap_t* bm1 = NULL;
|
potrace_bitmap_t* bm1 = NULL;
|
||||||
int sign;
|
int sign;
|
||||||
|
|
||||||
bm1 = bm_dup( bm );
|
bm1 = bm_dup( bm );
|
||||||
|
|
||||||
if( !bm1 )
|
if( !bm1 )
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -551,7 +574,9 @@ int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||||
bm_clearexcess( bm1 );
|
bm_clearexcess( bm1 );
|
||||||
|
|
||||||
/* iterate through components */
|
/* iterate through components */
|
||||||
|
x = 0;
|
||||||
y = bm1->h - 1;
|
y = bm1->h - 1;
|
||||||
|
|
||||||
while( findnext( bm1, &x, &y ) == 0 )
|
while( findnext( bm1, &x, &y ) == 0 )
|
||||||
{
|
{
|
||||||
/* calculate the sign by looking at the original */
|
/* calculate the sign by looking at the original */
|
||||||
|
@ -559,6 +584,7 @@ int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||||
|
|
||||||
/* calculate the path */
|
/* calculate the path */
|
||||||
p = findpath( bm1, x, y + 1, sign, param->turnpolicy );
|
p = findpath( bm1, x, y + 1, sign, param->turnpolicy );
|
||||||
|
|
||||||
if( p==NULL )
|
if( p==NULL )
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -574,7 +600,7 @@ int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
list_insert_beforehook( p, hook );
|
list_insert_beforehook( p, plist_hook );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bm1->h > 0 ) /* to be sure */
|
if( bm1->h > 0 ) /* to be sure */
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: decompose.h 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
|
|
||||||
#ifndef DECOMPOSE_H
|
#ifndef DECOMPOSE_H
|
||||||
#define DECOMPOSE_H
|
#define DECOMPOSE_H
|
||||||
|
|
||||||
#include <potracelib.h>
|
#include "potracelib.h"
|
||||||
#include <progress.h>
|
#include "progress.h"
|
||||||
|
#include "curve.h"
|
||||||
|
|
||||||
int bm_to_pathlist( const potrace_bitmap_t* bm,
|
int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||||
path_t** plistp,
|
path_t** plistp,
|
||||||
const potrace_param_t* param,
|
const potrace_param_t* param,
|
||||||
progress_t* progress );
|
progress_t* progress );
|
||||||
|
|
||||||
#endif /* DECOMPOSE_H */
|
#endif /* DECOMPOSE_H */
|
||||||
|
|
|
@ -1,51 +1,60 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* 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
|
/* Routines for manipulating greymaps, including reading pgm files. We
|
||||||
* only deal with greymaps of depth 8 bits. */
|
* only deal with greymaps of depth 8 bits. */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include <greymap.h>
|
#include "greymap.h"
|
||||||
|
#include "bitops.h"
|
||||||
|
|
||||||
#define INTBITS ( 8 * sizeof(int) )
|
#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_pnm( FILE* f, greymap_t** gmp, int magic );
|
||||||
static int gm_readbody_bmp( FILE* f, greymap_t** gmp );
|
static int gm_readbody_bmp( FILE* f, greymap_t** gmp );
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* basic greymap routines */
|
/* basic greymap routines */
|
||||||
|
|
||||||
/* return new un-initialized greymap. NULL with errno on error */
|
/* return new un-initialized greymap. NULL with errno on error.
|
||||||
|
* Assumes w, h >= 0. */
|
||||||
greymap_t* gm_new( int w, int h )
|
greymap_t* gm_new( int w, int h )
|
||||||
{
|
{
|
||||||
greymap_t* gm;
|
greymap_t* gm;
|
||||||
int errno_save;
|
ssize_t size = (ssize_t) w * (ssize_t) h * (ssize_t) sizeof(signed short int);
|
||||||
|
|
||||||
|
/* check for overflow error */
|
||||||
|
if( size < 0 || size / w / h != sizeof(signed short int) )
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gm = (greymap_t*) malloc( sizeof(greymap_t) );
|
gm = (greymap_t*) malloc( sizeof(greymap_t) );
|
||||||
|
|
||||||
if( !gm )
|
if( !gm )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gm->w = w;
|
gm->w = w;
|
||||||
gm->h = h;
|
gm->h = h;
|
||||||
gm->map = (signed short int*) malloc( w * h * sizeof(signed short int) );
|
gm->map = (signed short int*) malloc( size );
|
||||||
|
|
||||||
if( !gm->map )
|
if( !gm->map )
|
||||||
{
|
{
|
||||||
errno_save = errno;
|
|
||||||
free( gm );
|
free( gm );
|
||||||
errno = errno_save;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gm;
|
return gm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +66,7 @@ void gm_free( greymap_t* gm )
|
||||||
{
|
{
|
||||||
free( gm->map );
|
free( gm->map );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( gm );
|
free( gm );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +80,8 @@ greymap_t* gm_dup( greymap_t* gm )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy( gm1->map, gm->map, gm->w * gm->h * 2 );
|
|
||||||
|
memcpy( gm1->map, gm->map, gm->w * gm->h * sizeof(signed short int) );
|
||||||
return gm1;
|
return gm1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +93,7 @@ void gm_clear( greymap_t* gm, int b )
|
||||||
|
|
||||||
if( b==0 )
|
if( b==0 )
|
||||||
{
|
{
|
||||||
memset( gm->map, 0, gm->w * gm->h * 2 );
|
memset( gm->map, 0, gm->w * gm->h * sizeof(signed short int) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -106,17 +117,20 @@ static int fgetc_ws( FILE* f )
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c=='#' )
|
if( c=='#' )
|
||||||
{
|
{
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c=='\n' || c==EOF )
|
if( c=='\n' || c==EOF )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* space, tab, line feed, carriage return, form-feed */
|
/* space, tab, line feed, carriage return, form-feed */
|
||||||
if( c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12 )
|
if( c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12 )
|
||||||
{
|
{
|
||||||
|
@ -140,10 +154,12 @@ static int readnum( FILE* f )
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc_ws( f );
|
c = fgetc_ws( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c==EOF )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c>='0' && c<='9' )
|
if( c>='0' && c<='9' )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -152,18 +168,22 @@ static int readnum( FILE* f )
|
||||||
|
|
||||||
/* first digit is already in c */
|
/* first digit is already in c */
|
||||||
acc = c - '0';
|
acc = c - '0';
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c==EOF )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c<'0' || c>'9' )
|
if( c<'0' || c>'9' )
|
||||||
{
|
{
|
||||||
ungetc( c, f );
|
ungetc( c, f );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
acc *= 10;
|
acc *= 10;
|
||||||
acc += c - '0';
|
acc += c - '0';
|
||||||
}
|
}
|
||||||
|
@ -183,10 +203,12 @@ static int readbit( FILE* f )
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc_ws( f );
|
c = fgetc_ws( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c==EOF )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c>='0' && c<='1' )
|
if( c>='0' && c<='1' )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -219,20 +241,25 @@ int gm_read( FILE* f, greymap_t** gmp )
|
||||||
* by the PNM standard, but there is no harm in being lenient. */
|
* by the PNM standard, but there is no harm in being lenient. */
|
||||||
|
|
||||||
magic[0] = fgetc_ws( f );
|
magic[0] = fgetc_ws( f );
|
||||||
|
|
||||||
if( magic[0] == EOF )
|
if( magic[0] == EOF )
|
||||||
{
|
{
|
||||||
/* files which contain only comments and whitespace count as "empty" */
|
/* files which contain only comments and whitespace count as "empty" */
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
magic[1] = fgetc( f );
|
magic[1] = fgetc( f );
|
||||||
|
|
||||||
if( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' )
|
if( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' )
|
||||||
{
|
{
|
||||||
return gm_readbody_pnm( f, gmp, magic[1] );
|
return gm_readbody_pnm( f, gmp, magic[1] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( magic[0] == 'B' && magic[1] == 'M' )
|
if( magic[0] == 'B' && magic[1] == 'M' )
|
||||||
{
|
{
|
||||||
return gm_readbody_bmp( f, gmp );
|
return gm_readbody_bmp( f, gmp );
|
||||||
}
|
}
|
||||||
|
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,19 +271,21 @@ int gm_read( FILE* f, greymap_t** gmp )
|
||||||
static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
{
|
{
|
||||||
greymap_t* gm;
|
greymap_t* gm;
|
||||||
int x, y, i, j, b, b1, sum;
|
int x, y, i, j, b, b1, sum;
|
||||||
int bpr; /* bytes per row (as opposed to 4*gm->c) */
|
int bpr; /* bytes per row (as opposed to 4*gm->c) */
|
||||||
int w, h, max;
|
int w, h, max;
|
||||||
|
|
||||||
gm = NULL;
|
gm = NULL;
|
||||||
|
|
||||||
w = readnum( f );
|
w = readnum( f );
|
||||||
|
|
||||||
if( w<0 )
|
if( w<0 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
h = readnum( f );
|
h = readnum( f );
|
||||||
|
|
||||||
if( h<0 )
|
if( h<0 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -264,6 +293,7 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
|
|
||||||
/* allocate greymap */
|
/* allocate greymap */
|
||||||
gm = gm_new( w, h );
|
gm = gm_new( w, h );
|
||||||
|
|
||||||
if( !gm )
|
if( !gm )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -286,10 +316,12 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
b = readbit( f );
|
b = readbit( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b<0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
GM_UPUT( gm, x, y, b ? 0 : 255 );
|
GM_UPUT( gm, x, y, b ? 0 : 255 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,6 +332,7 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
/* read P2 format: PGM ascii */
|
/* read P2 format: PGM ascii */
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max<1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -310,10 +343,12 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
b = readnum( f );
|
b = readnum( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b<0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
GM_UPUT( gm, x, y, b * 255 / max );
|
GM_UPUT( gm, x, y, b * 255 / max );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,6 +359,7 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
/* read P3 format: PPM ascii */
|
/* read P3 format: PPM ascii */
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max<1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -334,13 +370,16 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
for( i = 0; i<3; i++ )
|
for( i = 0; i<3; i++ )
|
||||||
{
|
{
|
||||||
b = readnum( f );
|
b = readnum( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b<0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += b;
|
sum += b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,6 +393,7 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
/* read P4 format: PBM raw */
|
/* read P4 format: PBM raw */
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after height */
|
b = fgetc( f ); /* read single white-space character after height */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -366,13 +406,15 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
for( i = 0; i<bpr; i++ )
|
for( i = 0; i<bpr; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( j = 0; j<8; j++ )
|
for( j = 0; j<8; j++ )
|
||||||
{
|
{
|
||||||
GM_PUT( gm, i * 8 + j, y, b & (0x80 >> j) ? 0 : 255 );
|
GM_PUT( gm, i * 8 + j, y, (b & (0x80 >> j)) ? 0 : 255 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,12 +425,14 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
/* read P5 format: PGM raw */
|
/* read P5 format: PGM raw */
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max<1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after max */
|
b = fgetc( f ); /* read single white-space character after max */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -399,16 +443,21 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
if( max>=256 )
|
if( max>=256 )
|
||||||
{
|
{
|
||||||
b <<= 8;
|
b <<= 8;
|
||||||
b1 = fgetc( f );
|
b1 = fgetc( f );
|
||||||
|
|
||||||
if( b1==EOF )
|
if( b1==EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
b |= b1;
|
b |= b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GM_UPUT( gm, x, y, b * 255 / max );
|
GM_UPUT( gm, x, y, b * 255 / max );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,12 +468,14 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
/* read P6 format: PPM raw */
|
/* read P6 format: PPM raw */
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max<1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after max */
|
b = fgetc( f ); /* read single white-space character after max */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
@ -435,21 +486,27 @@ static int gm_readbody_pnm( FILE* f, greymap_t** gmp, int magic )
|
||||||
for( x = 0; x<w; x++ )
|
for( x = 0; x<w; x++ )
|
||||||
{
|
{
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
for( i = 0; i<3; i++ )
|
for( i = 0; i<3; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( max>=256 )
|
if( max>=256 )
|
||||||
{
|
{
|
||||||
b <<= 8;
|
b <<= 8;
|
||||||
b1 = fgetc( f );
|
b1 = fgetc( f );
|
||||||
|
|
||||||
if( b1==EOF )
|
if( b1==EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
b |= b1;
|
b |= b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += b;
|
sum += b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,6 +526,7 @@ eof:
|
||||||
|
|
||||||
format_error:
|
format_error:
|
||||||
gm_free( gm );
|
gm_free( gm );
|
||||||
|
|
||||||
if( magic == '1' || magic == '4' )
|
if( magic == '1' || magic == '4' )
|
||||||
{
|
{
|
||||||
gm_read_error = "invalid pbm file";
|
gm_read_error = "invalid pbm file";
|
||||||
|
@ -481,6 +539,7 @@ format_error:
|
||||||
{
|
{
|
||||||
gm_read_error = "invalid ppm file";
|
gm_read_error = "invalid ppm file";
|
||||||
}
|
}
|
||||||
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,49 +549,56 @@ format_error:
|
||||||
|
|
||||||
struct bmp_info_s
|
struct bmp_info_s
|
||||||
{
|
{
|
||||||
unsigned int FileSize;
|
unsigned int FileSize;
|
||||||
unsigned int reserved;
|
unsigned int reserved;
|
||||||
unsigned int DataOffset;
|
unsigned int DataOffset;
|
||||||
unsigned int InfoSize;
|
unsigned int InfoSize;
|
||||||
unsigned int w; /* width */
|
unsigned int w; /* width */
|
||||||
unsigned int h; /* height */
|
unsigned int h; /* height */
|
||||||
unsigned int Planes;
|
unsigned int Planes;
|
||||||
unsigned int bits; /* bits per sample */
|
unsigned int bits; /* bits per sample */
|
||||||
unsigned int comp; /* compression mode */
|
unsigned int comp; /* compression mode */
|
||||||
unsigned int ImageSize;
|
unsigned int ImageSize;
|
||||||
unsigned int XpixelsPerM;
|
unsigned int XpixelsPerM;
|
||||||
unsigned int YpixelsPerM;
|
unsigned int YpixelsPerM;
|
||||||
unsigned int ncolors; /* number of colors in palette */
|
unsigned int ncolors; /* number of colors in palette */
|
||||||
unsigned int ColorsImportant;
|
unsigned int ColorsImportant;
|
||||||
unsigned int ctbits; /* sample size for color table */
|
unsigned int RedMask;
|
||||||
|
unsigned int GreenMask;
|
||||||
|
unsigned int BlueMask;
|
||||||
|
unsigned int AlphaMask;
|
||||||
|
unsigned int ctbits; /* sample size for color table */
|
||||||
|
int topdown; /* top-down mode? */
|
||||||
};
|
};
|
||||||
typedef struct bmp_info_s bmp_info_t;
|
typedef struct bmp_info_s bmp_info_t;
|
||||||
|
|
||||||
/* auxiliary */
|
/* auxiliary */
|
||||||
|
|
||||||
static int bmp_count = 0; /* counter for byte padding */
|
static int bmp_count = 0; /* counter for byte padding */
|
||||||
static int bmp_pos = 0; /* counter from start of BMP data */
|
static int bmp_pos = 0; /* counter from start of BMP data */
|
||||||
|
|
||||||
/* read n-byte little-endian integer. Return 1 on EOF or error, else
|
/* read n-byte little-endian integer. Return 1 on EOF or error, else
|
||||||
* 0. Assume n<=4. */
|
* 0. Assume n<=4. */
|
||||||
static int bmp_readint( FILE* f, int n, unsigned int* p )
|
static int bmp_readint( FILE* f, int n, unsigned int* p )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned int sum = 0;
|
unsigned int sum = 0;
|
||||||
int b;
|
int b;
|
||||||
|
|
||||||
for( i = 0; i<n; i++ )
|
for( i = 0; i<n; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += b << (8 * i);
|
sum += b << (8 * i);
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp_count += n;
|
bmp_count += n;
|
||||||
bmp_pos += n;
|
bmp_pos += n;
|
||||||
*p = sum;
|
*p = sum;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -552,16 +618,18 @@ static int bmp_pad( FILE* f )
|
||||||
int c, i, b;
|
int c, i, b;
|
||||||
|
|
||||||
c = (-bmp_count) & 3;
|
c = (-bmp_count) & 3;
|
||||||
|
|
||||||
for( i = 0; i<c; i++ )
|
for( i = 0; i<c; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp_pos += c;
|
bmp_pos += c;
|
||||||
bmp_count = 0;
|
bmp_count = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -575,10 +643,12 @@ static int bmp_forward( FILE* f, int pos )
|
||||||
while( bmp_pos < pos )
|
while( bmp_pos < pos )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b==EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp_pos++;
|
bmp_pos++;
|
||||||
bmp_count++;
|
bmp_count++;
|
||||||
}
|
}
|
||||||
|
@ -587,11 +657,14 @@ static int bmp_forward( FILE* f, int pos )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define TRY( x ) if( x ) \
|
#define TRY( x ) if( x ) \
|
||||||
goto try_error
|
goto try_error
|
||||||
#define TRY_EOF( x ) if( x ) \
|
#define TRY_EOF( x ) if( x ) \
|
||||||
goto eof
|
goto eof
|
||||||
|
|
||||||
|
/* correct y-coordinate for top-down format */
|
||||||
|
#define ycorr( y ) (bmpinfo.topdown ? bmpinfo.h - 1 - y : y)
|
||||||
|
|
||||||
/* read BMP stream after magic number. Return values as for gm_read.
|
/* read BMP stream after magic number. Return values as for gm_read.
|
||||||
* We choose to be as permissive as possible, since there are many
|
* We choose to be as permissive as possible, since there are many
|
||||||
* programs out there which produce BMP. For instance, ppmtobmp can
|
* programs out there which produce BMP. For instance, ppmtobmp can
|
||||||
|
@ -601,15 +674,16 @@ static int bmp_forward( FILE* f, int pos )
|
||||||
* Windows BMP format. */
|
* Windows BMP format. */
|
||||||
static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
{
|
{
|
||||||
bmp_info_t bmpinfo;
|
bmp_info_t bmpinfo;
|
||||||
int* coltable;
|
int* coltable;
|
||||||
unsigned int b, c;
|
unsigned int b, c;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
greymap_t* gm;
|
greymap_t* gm;
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
int col[2];
|
int col[2];
|
||||||
unsigned int bitbuf;
|
unsigned int bitbuf;
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
|
unsigned int redshift, greenshift, blueshift;
|
||||||
|
|
||||||
gm_read_error = NULL;
|
gm_read_error = NULL;
|
||||||
gm = NULL;
|
gm = NULL;
|
||||||
|
@ -624,7 +698,9 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
|
|
||||||
/* info header */
|
/* info header */
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.InfoSize ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.InfoSize ) );
|
||||||
if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64 )
|
|
||||||
|
if( bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64
|
||||||
|
|| bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124 )
|
||||||
{
|
{
|
||||||
/* Windows or new OS/2 format */
|
/* Windows or new OS/2 format */
|
||||||
bmpinfo.ctbits = 32; /* sample size in color table */
|
bmpinfo.ctbits = 32; /* sample size in color table */
|
||||||
|
@ -638,6 +714,34 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.YpixelsPerM ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.YpixelsPerM ) );
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
|
||||||
|
|
||||||
|
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 ) );
|
||||||
|
TRY( bmp_readint( f, 4, &bmpinfo.AlphaMask ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bmpinfo.w > 0x7fffffff )
|
||||||
|
{
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bmpinfo.h > 0x7fffffff )
|
||||||
|
{
|
||||||
|
bmpinfo.h = (-bmpinfo.h) & 0xffffffff;
|
||||||
|
bmpinfo.topdown = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bmpinfo.topdown = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bmpinfo.h > 0x7fffffff )
|
||||||
|
{
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( bmpinfo.InfoSize == 12 )
|
else if( bmpinfo.InfoSize == 12 )
|
||||||
{
|
{
|
||||||
|
@ -647,15 +751,22 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
TRY( bmp_readint( f, 2, &bmpinfo.h ) );
|
TRY( bmp_readint( f, 2, &bmpinfo.h ) );
|
||||||
TRY( bmp_readint( f, 2, &bmpinfo.Planes ) );
|
TRY( bmp_readint( f, 2, &bmpinfo.Planes ) );
|
||||||
TRY( bmp_readint( f, 2, &bmpinfo.bits ) );
|
TRY( bmp_readint( f, 2, &bmpinfo.bits ) );
|
||||||
bmpinfo.comp = 0;
|
bmpinfo.comp = 0;
|
||||||
bmpinfo.ncolors = 0;
|
bmpinfo.ncolors = 0;
|
||||||
|
bmpinfo.topdown = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forward to color table (i.e., if bmpinfo.InfoSize == 64) */
|
if( bmpinfo.comp == 3 && bmpinfo.InfoSize < 108 )
|
||||||
|
{
|
||||||
|
/* bitfield feature is only understood with V4 and V5 format */
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
|
||||||
TRY( bmp_forward( f, 14 + bmpinfo.InfoSize ) );
|
TRY( bmp_forward( f, 14 + bmpinfo.InfoSize ) );
|
||||||
|
|
||||||
if( bmpinfo.Planes != 1 )
|
if( bmpinfo.Planes != 1 )
|
||||||
|
@ -672,7 +783,8 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
/* color table, present only if bmpinfo.bits <= 8. */
|
/* color table, present only if bmpinfo.bits <= 8. */
|
||||||
if( bmpinfo.bits <= 8 )
|
if( bmpinfo.bits <= 8 )
|
||||||
{
|
{
|
||||||
coltable = (int*) malloc( bmpinfo.ncolors * sizeof(int) );
|
coltable = (int*) calloc( bmpinfo.ncolors, sizeof(int) );
|
||||||
|
|
||||||
if( !coltable )
|
if( !coltable )
|
||||||
{
|
{
|
||||||
goto std_error;
|
goto std_error;
|
||||||
|
@ -696,6 +808,7 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
|
|
||||||
/* allocate greymap */
|
/* allocate greymap */
|
||||||
gm = gm_new( bmpinfo.w, bmpinfo.h );
|
gm = gm_new( bmpinfo.w, bmpinfo.h );
|
||||||
|
|
||||||
if( !gm )
|
if( !gm )
|
||||||
{
|
{
|
||||||
goto std_error;
|
goto std_error;
|
||||||
|
@ -716,12 +829,15 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y<bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
|
|
||||||
for( i = 0; 8 * i<bmpinfo.w; i++ )
|
for( i = 0; 8 * i<bmpinfo.w; i++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
|
|
||||||
for( j = 0; j<8; j++ )
|
for( j = 0; j<8; j++ )
|
||||||
{
|
{
|
||||||
GM_PUT( gm, i * 8 + j, y, b & (0x80 >> j) ? coltable[1] : coltable[0] );
|
GM_PUT( gm, i * 8 + j, ycorr( y ),
|
||||||
|
(b & (0x80 >> j)) ? coltable[1] : coltable[0] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,11 +853,13 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
case 0x006:
|
case 0x006:
|
||||||
case 0x007:
|
case 0x007:
|
||||||
case 0x008:
|
case 0x008:
|
||||||
|
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y<bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
|
bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
|
||||||
n = 0; /* number of bits currently in bitbuffer */
|
n = 0; /* number of bits currently in bitbuffer */
|
||||||
|
|
||||||
for( x = 0; x<bmpinfo.w; x++ )
|
for( x = 0; x<bmpinfo.w; x++ )
|
||||||
{
|
{
|
||||||
if( n < bmpinfo.bits )
|
if( n < bmpinfo.bits )
|
||||||
|
@ -750,10 +868,11 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
bitbuf |= b << (INTBITS - 8 - n);
|
bitbuf |= b << (INTBITS - 8 - n);
|
||||||
n += 8;
|
n += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = bitbuf >> (INTBITS - bmpinfo.bits);
|
b = bitbuf >> (INTBITS - bmpinfo.bits);
|
||||||
bitbuf <<= bmpinfo.bits;
|
bitbuf <<= bmpinfo.bits;
|
||||||
n -= bmpinfo.bits;
|
n -= bmpinfo.bits;
|
||||||
GM_UPUT( gm, x, y, coltable[b] );
|
GM_UPUT( gm, x, ycorr( y ), coltable[b] );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -762,7 +881,6 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x010: /* 16-bit encoding */
|
case 0x010: /* 16-bit encoding */
|
||||||
|
|
||||||
/* can't do this format because it is not well-documented and I
|
/* can't do this format because it is not well-documented and I
|
||||||
* don't have any samples */
|
* don't have any samples */
|
||||||
gm_read_error = "cannot handle bmp 16-bit coding";
|
gm_read_error = "cannot handle bmp 16-bit coding";
|
||||||
|
@ -771,14 +889,39 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
|
|
||||||
case 0x018: /* 24-bit encoding */
|
case 0x018: /* 24-bit encoding */
|
||||||
case 0x020: /* 32-bit encoding */
|
case 0x020: /* 32-bit encoding */
|
||||||
|
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y<bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
|
|
||||||
for( x = 0; x<bmpinfo.w; x++ )
|
for( x = 0; x<bmpinfo.w; x++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
||||||
c = ( (c >> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff);
|
c = ( (c >> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff);
|
||||||
GM_UPUT( gm, x, y, c / 3 );
|
GM_UPUT( gm, x, ycorr( y ), c / 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
TRY( bmp_pad( f ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x320: /* 32-bit encoding with bitfields */
|
||||||
|
redshift = lobit( bmpinfo.RedMask );
|
||||||
|
greenshift = lobit( bmpinfo.GreenMask );
|
||||||
|
blueshift = lobit( bmpinfo.BlueMask );
|
||||||
|
|
||||||
|
for( y = 0; y<bmpinfo.h; y++ )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -787,17 +930,20 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
|
case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
||||||
|
|
||||||
if( b>0 )
|
if( b>0 )
|
||||||
{
|
{
|
||||||
/* repeat count */
|
/* repeat count */
|
||||||
col[0] = coltable[(c >> 4) & 0xf];
|
col[0] = coltable[(c >> 4) & 0xf];
|
||||||
col[1] = coltable[c & 0xf];
|
col[1] = coltable[c & 0xf];
|
||||||
|
|
||||||
for( i = 0; i<b && x<bmpinfo.w; i++ )
|
for( i = 0; i<b && x<bmpinfo.w; i++ )
|
||||||
{
|
{
|
||||||
if( x>=bmpinfo.w )
|
if( x>=bmpinfo.w )
|
||||||
|
@ -805,11 +951,13 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( y>=bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GM_UPUT( gm, x, y, col[i & 1] );
|
|
||||||
|
GM_UPUT( gm, x, ycorr( y ), col[i & 1] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,8 +977,8 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
/* "delta": skip pixels in x and y directions */
|
/* "delta": skip pixels in x and y directions */
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
|
||||||
x += b;
|
x += b;
|
||||||
y += c;
|
y += c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -841,16 +989,19 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( x>=bmpinfo.w )
|
if( x>=bmpinfo.w )
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( y>=bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GM_PUT( gm, x, y, coltable[( b >> ( 4 - 4 * (i & 1) ) ) & 0xf] );
|
|
||||||
|
GM_PUT( gm, x, ycorr( y ), coltable[( b >> ( 4 - 4 * (i & 1) ) ) & 0xf] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,12 +1016,14 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
|
case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
||||||
|
|
||||||
if( b>0 )
|
if( b>0 )
|
||||||
{
|
{
|
||||||
/* repeat count */
|
/* repeat count */
|
||||||
|
@ -881,11 +1034,13 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( y>=bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GM_UPUT( gm, x, y, coltable[c] );
|
|
||||||
|
GM_UPUT( gm, x, ycorr( y ), coltable[c] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -905,8 +1060,8 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
/* "delta": skip pixels in x and y directions */
|
/* "delta": skip pixels in x and y directions */
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* x offset */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* y offset */
|
||||||
x += b;
|
x += b;
|
||||||
y += c;
|
y += c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -914,16 +1069,19 @@ static int gm_readbody_bmp( FILE* f, greymap_t** gmp )
|
||||||
for( i = 0; i<c; i++ )
|
for( i = 0; i<c; i++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
|
|
||||||
if( x>=bmpinfo.w )
|
if( x>=bmpinfo.w )
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( y>=bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GM_PUT( gm, x, y, coltable[b] );
|
|
||||||
|
GM_PUT( gm, x, ycorr( y ), coltable[b] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,10 +1113,12 @@ format_error:
|
||||||
try_error:
|
try_error:
|
||||||
free( coltable );
|
free( coltable );
|
||||||
free( gm );
|
free( gm );
|
||||||
|
|
||||||
if( !gm_read_error )
|
if( !gm_read_error )
|
||||||
{
|
{
|
||||||
gm_read_error = "invalid bmp file";
|
gm_read_error = "invalid bmp file";
|
||||||
}
|
}
|
||||||
|
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
std_error:
|
std_error:
|
||||||
|
@ -985,9 +1145,10 @@ int gm_writepgm( FILE* f, greymap_t* gm, char* comment, int raw, int mode, doubl
|
||||||
if( gamma != 1.0 )
|
if( gamma != 1.0 )
|
||||||
{
|
{
|
||||||
gammatable[0] = 0;
|
gammatable[0] = 0;
|
||||||
|
|
||||||
for( v = 1; v<256; v++ )
|
for( v = 1; v<256; v++ )
|
||||||
{
|
{
|
||||||
gammatable[v] = (int) ( 255 * exp( log( v / 255.0 ) / gamma ) + 0.5 );
|
gammatable[v] = (int) (255 * exp( log( v / 255.0 ) / gamma ) + 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -999,22 +1160,27 @@ int gm_writepgm( FILE* f, greymap_t* gm, char* comment, int raw, int mode, doubl
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf( f, raw ? "P5\n" : "P2\n" );
|
fprintf( f, raw ? "P5\n" : "P2\n" );
|
||||||
|
|
||||||
if( comment && *comment )
|
if( comment && *comment )
|
||||||
{
|
{
|
||||||
fprintf( f, "# %s\n", comment );
|
fprintf( f, "# %s\n", comment );
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf( f, "%d %d 255\n", gm->w, gm->h );
|
fprintf( f, "%d %d 255\n", gm->w, gm->h );
|
||||||
|
|
||||||
for( y = gm->h - 1; y>=0; y-- )
|
for( y = gm->h - 1; y>=0; y-- )
|
||||||
{
|
{
|
||||||
for( x = 0; x<gm->w; x++ )
|
for( x = 0; x<gm->w; x++ )
|
||||||
{
|
{
|
||||||
v = GM_UGET( gm, x, y );
|
v = GM_UGET( gm, x, y );
|
||||||
|
|
||||||
if( mode == GM_MODE_NONZERO )
|
if( mode == GM_MODE_NONZERO )
|
||||||
{
|
{
|
||||||
if( v > 255 )
|
if( v > 255 )
|
||||||
{
|
{
|
||||||
v = 510 - v;
|
v = 510 - v;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( v < 0 )
|
if( v < 0 )
|
||||||
{
|
{
|
||||||
v = 0;
|
v = 0;
|
||||||
|
@ -1023,6 +1189,7 @@ int gm_writepgm( FILE* f, greymap_t* gm, char* comment, int raw, int mode, doubl
|
||||||
else if( mode == GM_MODE_ODD )
|
else if( mode == GM_MODE_ODD )
|
||||||
{
|
{
|
||||||
v = mod( v, 510 );
|
v = mod( v, 510 );
|
||||||
|
|
||||||
if( v > 255 )
|
if( v > 255 )
|
||||||
{
|
{
|
||||||
v = 510 - v;
|
v = 510 - v;
|
||||||
|
@ -1042,6 +1209,7 @@ int gm_writepgm( FILE* f, greymap_t* gm, char* comment, int raw, int mode, doubl
|
||||||
else if( mode == GM_MODE_NEGATIVE )
|
else if( mode == GM_MODE_NEGATIVE )
|
||||||
{
|
{
|
||||||
v = 510 - v;
|
v = 510 - v;
|
||||||
|
|
||||||
if( v < 0 )
|
if( v < 0 )
|
||||||
{
|
{
|
||||||
v = 0;
|
v = 0;
|
||||||
|
@ -1051,6 +1219,7 @@ int gm_writepgm( FILE* f, greymap_t* gm, char* comment, int raw, int mode, doubl
|
||||||
v = 255;
|
v = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v = gammatable[v];
|
v = gammatable[v];
|
||||||
|
|
||||||
if( raw )
|
if( raw )
|
||||||
|
@ -1079,26 +1248,26 @@ int gm_print( FILE* f, greymap_t* gm )
|
||||||
int d, t;
|
int d, t;
|
||||||
int sw, sh;
|
int sw, sh;
|
||||||
|
|
||||||
sw = gm->w < 79 ? gm->w : 79;
|
sw = gm->w < 79 ? gm->w : 79;
|
||||||
sh = gm->w < 79 ? gm->h : gm->h * sw * 44 / (79 * gm->w);
|
sh = gm->w < 79 ? gm->h : gm->h * sw * 44 / (79 * gm->w);
|
||||||
|
|
||||||
for( yy = sh - 1; yy>=0; yy-- )
|
for( yy = sh - 1; yy>=0; yy-- )
|
||||||
{
|
{
|
||||||
for( xx = 0; xx<sw; xx++ )
|
for( xx = 0; xx<sw; xx++ )
|
||||||
{
|
{
|
||||||
d = 0;
|
d = 0;
|
||||||
t = 0;
|
t = 0;
|
||||||
|
|
||||||
for( x = xx * gm->w / sw; x<(xx + 1) * gm->w / sw; x++ )
|
for( x = xx * gm->w / sw; x<(xx + 1) * gm->w / sw; x++ )
|
||||||
{
|
{
|
||||||
for( y = yy * gm->h / sh; y<(yy + 1) * gm->h / sh; y++ )
|
for( y = yy * gm->h / sh; y<(yy + 1) * gm->h / sh; y++ )
|
||||||
{
|
{
|
||||||
d += GM_GET( gm, x, y );
|
d += GM_GET( gm, x, y );
|
||||||
t += 256;
|
t += 256;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( t )
|
fputc( "*#=- "[5 * d / t], f ); /* what a cute trick :) */
|
||||||
fputc( "*#=- "[5 * d / t], f ); /* what a cute trick :) */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fputc( '\n', f );
|
fputc( '\n', f );
|
||||||
|
|
|
@ -1,58 +1,61 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: greymap.h 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
|
|
||||||
#ifndef PGM_H
|
#ifndef GREYMAP_H
|
||||||
#define PGM_H
|
#define GREYMAP_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* internal format for greymaps. Note: in this format, rows are
|
/* internal format for greymaps. Note: in this format, rows are
|
||||||
ordered from bottom to top. The pixels in each row are given from
|
* ordered from bottom to top. The pixels in each row are given from
|
||||||
left to right. */
|
* left to right. */
|
||||||
|
|
||||||
struct greymap_s {
|
struct greymap_s
|
||||||
int w; /* width, in pixels */
|
{
|
||||||
int h; /* height, in pixels */
|
int w; /* width, in pixels */
|
||||||
signed short int *map; /* raw data, w*h values */
|
int h; /* height, in pixels */
|
||||||
|
signed short int* map; /* raw data, w*h values */
|
||||||
};
|
};
|
||||||
typedef struct greymap_s greymap_t;
|
typedef struct greymap_s greymap_t;
|
||||||
|
|
||||||
/* macros for accessing pixel at index (x,y). Note that the origin is
|
/* macros for accessing pixel at index (x,y). Note that the origin is
|
||||||
in the *lower* left corner. U* macros omit the bounds check. */
|
* in the *lower* left corner. U* macros omit the bounds check. */
|
||||||
|
|
||||||
#define gm_index(gm, x, y) (&(gm)->map[(x)+(y)*(gm)->w])
|
#define gm_index( gm, x, y ) (&(gm)->map[(x) + (y) * (ssize_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_safe( gm, x, \
|
||||||
#define gm_bound(x, m) ((x)<0 ? 0 : (x)>=(m) ? (m)-1 : (x))
|
y ) ( (int) (x)>=0 && (int) (x)<(gm)->w && (int) (y)>=0 \
|
||||||
#define GM_UGET(gm, x, y) (*gm_index(gm, x, y))
|
&& (int) (y)<(gm)->h )
|
||||||
#define GM_UINC(gm, x, y, b) (*gm_index(gm, x, y) += (short int)(b))
|
#define gm_bound( x, m ) ( (x)<0 ? 0 : (x)>=(m) ? (m) - 1 : (x) )
|
||||||
#define GM_UINV(gm, x, y) (*gm_index(gm, x, y) = 255 - *gm_index(gm, x, y))
|
#define GM_UGET( gm, x, y ) ( *gm_index( gm, x, y ) )
|
||||||
#define GM_UPUT(gm, x, y, b) (*gm_index(gm, x, y) = (short int)(b))
|
#define GM_UINC( gm, x, y, b ) ( *gm_index( gm, x, y ) += (short int) (b) )
|
||||||
#define GM_GET(gm, x, y) (gm_safe(gm, x, y) ? GM_UGET(gm, x, y) : 0)
|
#define GM_UINV( gm, x, y ) ( *gm_index( gm, x, y ) = 255 - *gm_index( gm, x, y ) )
|
||||||
#define GM_INC(gm, x, y, b) (gm_safe(gm, x, y) ? GM_UINC(gm, x, y, b) : 0)
|
#define GM_UPUT( gm, x, y, b ) ( *gm_index( gm, x, y ) = (short int) (b) )
|
||||||
#define GM_INV(gm, x, y) (gm_safe(gm, x, y) ? GM_UINV(gm, x, y) : 0)
|
#define GM_GET( gm, x, y ) (gm_safe( gm, x, y ) ? GM_UGET( 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_INC( gm, x, y, b ) (gm_safe( gm, x, y ) ? GM_UINC( 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_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 ) )
|
||||||
|
|
||||||
/* modes for cutting off out-of-range values. The following names
|
/* modes for cutting off out-of-range values. The following names
|
||||||
refer to winding numbers. I.e., make a pixel black if winding
|
* refer to winding numbers. I.e., make a pixel black if winding
|
||||||
number is nonzero, odd, or positive, respectively. We assume that 0
|
* number is nonzero, odd, or positive, respectively. We assume that 0
|
||||||
winding number corresponds to white (255). */
|
* winding number corresponds to white (255). */
|
||||||
#define GM_MODE_NONZERO 1
|
#define GM_MODE_NONZERO 1
|
||||||
#define GM_MODE_ODD 2
|
#define GM_MODE_ODD 2
|
||||||
#define GM_MODE_POSITIVE 3
|
#define GM_MODE_POSITIVE 3
|
||||||
#define GM_MODE_NEGATIVE 4
|
#define GM_MODE_NEGATIVE 4
|
||||||
|
|
||||||
extern const char *gm_read_error;
|
extern const char* gm_read_error;
|
||||||
|
|
||||||
greymap_t *gm_new(int w, int h);
|
greymap_t* gm_new( int w, int h );
|
||||||
greymap_t *gm_dup(greymap_t *gm);
|
greymap_t* gm_dup( greymap_t* gm );
|
||||||
void gm_free(greymap_t *gm);
|
void gm_free( greymap_t* gm );
|
||||||
void gm_clear(greymap_t *gm, int b);
|
void gm_clear( greymap_t* gm, int b );
|
||||||
int gm_read(FILE *f, greymap_t **gmp);
|
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, char* comment, int raw, int mode, double gamma );
|
||||||
int gm_print(FILE *f, greymap_t *gm);
|
int gm_print( FILE* f, greymap_t* gm );
|
||||||
|
|
||||||
#endif /* PGM_H */
|
#endif /* GREYMAP_H */
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: lists.h 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
|
|
||||||
#ifndef _PS_LISTS_H
|
#ifndef _PS_LISTS_H
|
||||||
#define _PS_LISTS_H
|
#define _PS_LISTS_H
|
||||||
|
@ -33,7 +32,8 @@
|
||||||
* trick, we'd have to omit the ";" in such cases. */
|
* trick, we'd have to omit the ";" in such cases. */
|
||||||
|
|
||||||
#define MACRO_BEGIN do {
|
#define MACRO_BEGIN do {
|
||||||
#define MACRO_END } while( 0 )
|
#define MACRO_END } \
|
||||||
|
while( 0 )
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* macros for singly-linked lists */
|
/* macros for singly-linked lists */
|
||||||
|
@ -45,7 +45,8 @@
|
||||||
* c, or NULL if not found */
|
* c, or NULL if not found */
|
||||||
#define list_find( elt, list, c ) \
|
#define list_find( elt, list, c ) \
|
||||||
MACRO_BEGIN list_forall( elt, list ) if( c ) \
|
MACRO_BEGIN list_forall( elt, list ) if( c ) \
|
||||||
break;MACRO_END
|
break; \
|
||||||
|
MACRO_END
|
||||||
|
|
||||||
/* like forall, except also set hook for elt. */
|
/* like forall, except also set hook for elt. */
|
||||||
#define list_forall2( elt, list, hook ) \
|
#define list_forall2( elt, list, hook ) \
|
||||||
|
@ -54,7 +55,8 @@
|
||||||
/* same as list_find, except also set hook for elt. */
|
/* same as list_find, except also set hook for elt. */
|
||||||
#define list_find2( elt, list, c, hook ) \
|
#define list_find2( elt, list, c, hook ) \
|
||||||
MACRO_BEGIN list_forall2( elt, list, hook ) if( c ) \
|
MACRO_BEGIN list_forall2( elt, list, hook ) if( c ) \
|
||||||
break;MACRO_END
|
break; \
|
||||||
|
MACRO_END
|
||||||
|
|
||||||
/* same, except only use hook. */
|
/* same, except only use hook. */
|
||||||
#define _list_forall_hook( list, hook ) \
|
#define _list_forall_hook( list, hook ) \
|
||||||
|
@ -63,7 +65,8 @@
|
||||||
/* same, except only use hook. Note: c may only refer to *hook, not elt. */
|
/* same, except only use hook. Note: c may only refer to *hook, not elt. */
|
||||||
#define _list_find_hook( list, c, hook ) \
|
#define _list_find_hook( list, c, hook ) \
|
||||||
MACRO_BEGIN _list_forall_hook( list, hook ) if( c ) \
|
MACRO_BEGIN _list_forall_hook( list, hook ) if( c ) \
|
||||||
break;MACRO_END
|
break; \
|
||||||
|
MACRO_END
|
||||||
|
|
||||||
/* insert element after hook */
|
/* insert element after hook */
|
||||||
#define list_insert_athook( elt, hook ) \
|
#define list_insert_athook( elt, hook ) \
|
||||||
|
@ -113,7 +116,7 @@
|
||||||
* Return NULL if out of bounds. */
|
* Return NULL if out of bounds. */
|
||||||
#define list_nth( elt, list, n ) \
|
#define list_nth( elt, list, n ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
int _x; /* only evaluate n once */ \
|
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
|
MACRO_END
|
||||||
|
|
||||||
|
@ -121,9 +124,9 @@
|
||||||
* Return NULL if out of bounds. */
|
* Return NULL if out of bounds. */
|
||||||
#define list_nth_hook( elt, list, n, hook ) \
|
#define list_nth_hook( elt, list, n, hook ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
int _x; /* only evaluate n once */ \
|
int _x; /* only evaluate n once */ \
|
||||||
for( _x = (n), elt = list, hook = &list; _x && elt; _x--, hook = &elt->next, elt =\
|
for( _x = (n), elt = list, hook = &list; _x && elt; \
|
||||||
elt->next ) {} \
|
_x--, hook = &elt->next, elt = elt->next ) {} \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* set n to the length of the list */
|
/* set n to the length of the list */
|
||||||
|
@ -142,11 +145,11 @@
|
||||||
n = 0; \
|
n = 0; \
|
||||||
list_forall( elt, list ) { \
|
list_forall( elt, list ) { \
|
||||||
if( c ) \
|
if( c ) \
|
||||||
break;\
|
break; \
|
||||||
n++; \
|
n++; \
|
||||||
} \
|
} \
|
||||||
if( !elt ) \
|
if( !elt ) \
|
||||||
n = -1;\
|
n = -1; \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* set n to the number of elements in the list that satisfy condition c */
|
/* set n to the number of elements in the list that satisfy condition c */
|
||||||
|
@ -155,7 +158,7 @@
|
||||||
n = 0; \
|
n = 0; \
|
||||||
list_forall( elt, list ) { \
|
list_forall( elt, list ) { \
|
||||||
if( c ) \
|
if( c ) \
|
||||||
n++;\
|
n++; \
|
||||||
} \
|
} \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
|
@ -221,13 +224,14 @@
|
||||||
do { \
|
do { \
|
||||||
_hook1 = &(list); \
|
_hook1 = &(list); \
|
||||||
while( (a = *_hook1) != NULL && (b = a->next1) != NULL ) { \
|
while( (a = *_hook1) != NULL && (b = a->next1) != NULL ) { \
|
||||||
_elt = b->next1; \
|
_elt = b->next1; \
|
||||||
_list_merge_cond( listtype, a, b, cond, *_hook1 ); \
|
_list_merge_cond( listtype, a, b, cond, *_hook1 ); \
|
||||||
_hook1 = &( (*_hook1)->next1 ); \
|
_hook1 = &( (*_hook1)->next1 ); \
|
||||||
*_hook1 = _elt; \
|
*_hook1 = _elt; \
|
||||||
} \
|
} \
|
||||||
} while( _hook1 != &(list) ); \
|
} \
|
||||||
MACRO_END
|
while( _hook1 != &(list) ); \
|
||||||
|
MACRO_END
|
||||||
|
|
||||||
/* merge two sorted lists. Store result at &result */
|
/* merge two sorted lists. Store result at &result */
|
||||||
#define _list_merge_cond( listtype, a, b, cond, result ) \
|
#define _list_merge_cond( listtype, a, b, cond, result ) \
|
||||||
|
@ -238,16 +242,19 @@
|
||||||
if( a==NULL ) { \
|
if( a==NULL ) { \
|
||||||
*_hook = b; \
|
*_hook = b; \
|
||||||
break; \
|
break; \
|
||||||
} else if( b==NULL ) { \
|
} \
|
||||||
|
else if( b==NULL ) { \
|
||||||
*_hook = a; \
|
*_hook = a; \
|
||||||
break; \
|
break; \
|
||||||
} else if( cond ) { \
|
} \
|
||||||
*_hook = a; \
|
else if( cond ) { \
|
||||||
_hook = &(a->next); \
|
*_hook = a; \
|
||||||
|
_hook = &(a->next); \
|
||||||
a = a->next; \
|
a = a->next; \
|
||||||
} else { \
|
} \
|
||||||
*_hook = b; \
|
else { \
|
||||||
_hook = &(b->next); \
|
*_hook = b; \
|
||||||
|
_hook = &(b->next); \
|
||||||
b = b->next; \
|
b = b->next; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
@ -262,7 +269,8 @@
|
||||||
elt->next = NULL; \
|
elt->next = NULL; \
|
||||||
if( end ) { \
|
if( end ) { \
|
||||||
end->next = elt; \
|
end->next = elt; \
|
||||||
} else { \
|
} \
|
||||||
|
else { \
|
||||||
head = elt; \
|
head = elt; \
|
||||||
} \
|
} \
|
||||||
end = elt; \
|
end = elt; \
|
||||||
|
@ -270,7 +278,7 @@
|
||||||
|
|
||||||
/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
|
/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
|
||||||
#define dlist_forall_unlink( elt, head, end ) \
|
#define dlist_forall_unlink( elt, head, end ) \
|
||||||
for( elt = head;\
|
for( elt = head; \
|
||||||
elt ? (head = elt->next, elt->next = NULL, elt->prev = NULL), 1 : (end = NULL, 0); \
|
elt ? (head = elt->next, elt->next = NULL, elt->prev = NULL), 1 : (end = NULL, 0); \
|
||||||
elt = head )
|
elt = head )
|
||||||
|
|
||||||
|
@ -282,7 +290,8 @@
|
||||||
head = head->next; \
|
head = head->next; \
|
||||||
if( head ) { \
|
if( head ) { \
|
||||||
head->prev = NULL; \
|
head->prev = NULL; \
|
||||||
} else { \
|
} \
|
||||||
|
else { \
|
||||||
end = NULL; \
|
end = NULL; \
|
||||||
} \
|
} \
|
||||||
elt->prev = NULL; \
|
elt->prev = NULL; \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -8,14 +8,21 @@
|
||||||
#define PLATFORM_H
|
#define PLATFORM_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* in Windows, set all file i/o to binary */
|
/* in Windows, set all file i/o to binary */
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
unsigned int _CRT_fmode = _O_BINARY;
|
unsigned int _CRT_fmode = _O_BINARY;
|
||||||
#endif
|
static inline void platform_init( void )
|
||||||
|
{
|
||||||
|
_setmode( _fileno( stdin ), _O_BINARY );
|
||||||
|
_setmode( _fileno( stdout ), _O_BINARY );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -34,6 +41,7 @@ static inline void platform_init( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* PLATFORM_H */
|
#endif /* PLATFORM_H */
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
#define POTRACELIB_VERSION "potracelib 1.8"
|
#define POTRACELIB_VERSION "potracelib 1.12"
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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.
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <potracelib.h>
|
#include "potracelib.h"
|
||||||
#include <curve.h>
|
#include "curve.h"
|
||||||
#include <decompose.h>
|
#include "decompose.h"
|
||||||
#include <trace.h>
|
#include "trace.h"
|
||||||
#include <progress.h>
|
#include "progress.h"
|
||||||
#include <potrace_version.h>
|
#include <potrace_version.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* default parameters */
|
/* default parameters */
|
||||||
|
@ -40,10 +39,12 @@ potrace_param_t* potrace_param_default( void )
|
||||||
potrace_param_t* p;
|
potrace_param_t* p;
|
||||||
|
|
||||||
p = (potrace_param_t*) malloc( sizeof(potrace_param_t) );
|
p = (potrace_param_t*) malloc( sizeof(potrace_param_t) );
|
||||||
|
|
||||||
if( !p )
|
if( !p )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy( p, ¶m_default, sizeof(potrace_param_t) );
|
memcpy( p, ¶m_default, sizeof(potrace_param_t) );
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -52,26 +53,28 @@ potrace_param_t* potrace_param_default( void )
|
||||||
/* On success, returns a Potrace state st with st->status ==
|
/* On success, returns a Potrace state st with st->status ==
|
||||||
* POTRACE_STATUS_OK. On failure, returns NULL if no Potrace state
|
* POTRACE_STATUS_OK. On failure, returns NULL if no Potrace state
|
||||||
* could be created (with errno set), or returns an incomplete Potrace
|
* could be created (with errno set), or returns an incomplete Potrace
|
||||||
* state (with st->status == POTRACE_STATUS_INCOMPLETE). Complete or
|
* state (with st->status == POTRACE_STATUS_INCOMPLETE, and with errno
|
||||||
* incomplete Potrace state can be freed with potrace_state_free(). */
|
* set). Complete or incomplete Potrace state can be freed with
|
||||||
|
* potrace_state_free(). */
|
||||||
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 )
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
path_t* plist = NULL;
|
path_t* plist = NULL;
|
||||||
potrace_state_t* st;
|
potrace_state_t* st;
|
||||||
progress_t prog;
|
progress_t prog;
|
||||||
progress_t subprog;
|
progress_t subprog;
|
||||||
|
|
||||||
/* prepare private progress bar state */
|
/* prepare private progress bar state */
|
||||||
prog.callback = param->progress.callback;
|
prog.callback = param->progress.callback;
|
||||||
prog.data = param->progress.data;
|
prog.data = param->progress.data;
|
||||||
prog.min = param->progress.min;
|
prog.min = param->progress.min;
|
||||||
prog.max = param->progress.max;
|
prog.max = param->progress.max;
|
||||||
prog.epsilon = param->progress.epsilon;
|
prog.epsilon = param->progress.epsilon;
|
||||||
prog.d_prev = param->progress.min;
|
prog.d_prev = param->progress.min;
|
||||||
|
|
||||||
/* allocate state object */
|
/* allocate state object */
|
||||||
st = (potrace_state_t*) malloc( sizeof(potrace_state_t) );
|
st = (potrace_state_t*) malloc( sizeof(potrace_state_t) );
|
||||||
|
|
||||||
if( !st )
|
if( !st )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -81,15 +84,16 @@ potrace_state_t* potrace_trace( const potrace_param_t* param, const potrace_bitm
|
||||||
|
|
||||||
/* process the image */
|
/* process the image */
|
||||||
r = bm_to_pathlist( bm, &plist, param, &subprog );
|
r = bm_to_pathlist( bm, &plist, param, &subprog );
|
||||||
|
|
||||||
if( r )
|
if( r )
|
||||||
{
|
{
|
||||||
free( st );
|
free( st );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
st->status = POTRACE_STATUS_OK;
|
st->status = POTRACE_STATUS_OK;
|
||||||
st->plist = plist;
|
st->plist = plist;
|
||||||
st->priv = NULL; /* private state currently unused */
|
st->priv = NULL; /* private state currently unused */
|
||||||
|
|
||||||
progress_subrange_end( &prog, &subprog );
|
progress_subrange_end( &prog, &subprog );
|
||||||
|
|
||||||
|
@ -97,6 +101,7 @@ potrace_state_t* potrace_trace( const potrace_param_t* param, const potrace_bitm
|
||||||
|
|
||||||
/* partial success. */
|
/* partial success. */
|
||||||
r = process_path( plist, param, &subprog );
|
r = process_path( plist, param, &subprog );
|
||||||
|
|
||||||
if( r )
|
if( r )
|
||||||
{
|
{
|
||||||
st->status = POTRACE_STATUS_INCOMPLETE;
|
st->status = POTRACE_STATUS_INCOMPLETE;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -6,7 +6,11 @@
|
||||||
#define POTRACELIB_H
|
#define POTRACELIB_H
|
||||||
|
|
||||||
/* this file defines the API for the core Potrace library. For a more
|
/* this file defines the API for the core Potrace library. For a more
|
||||||
* detailed description of the API, see doc/potracelib.txt */
|
* detailed description of the API, see potracelib.pdf */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* tracing parameters */
|
/* tracing parameters */
|
||||||
|
@ -23,22 +27,22 @@
|
||||||
/* structure to hold progress bar callback data */
|
/* structure to hold progress bar callback data */
|
||||||
struct potrace_progress_s
|
struct potrace_progress_s
|
||||||
{
|
{
|
||||||
void (* callback)( double progress, void* privdata ); /* callback fn */
|
void (* callback)( double progress, void* privdata ); /* callback fn */
|
||||||
void* data; /* callback function's private data */
|
void* data; /* callback function's private data */
|
||||||
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
|
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
|
||||||
double epsilon; /* granularity: can skip smaller increments */
|
double epsilon; /* granularity: can skip smaller increments */
|
||||||
};
|
};
|
||||||
typedef struct potrace_progress_s potrace_progress_t;
|
typedef struct potrace_progress_s potrace_progress_t;
|
||||||
|
|
||||||
/* structure to hold tracing parameters */
|
/* structure to hold tracing parameters */
|
||||||
struct potrace_param_s
|
struct potrace_param_s
|
||||||
{
|
{
|
||||||
int turdsize; /* area of largest path to be ignored */
|
int turdsize; /* area of largest path to be ignored */
|
||||||
int turnpolicy; /* resolves ambiguous turns in path decomposition */
|
int turnpolicy; /* resolves ambiguous turns in path decomposition */
|
||||||
double alphamax; /* corner threshold */
|
double alphamax; /* corner threshold */
|
||||||
int opticurve; /* use curve optimization? */
|
int opticurve; /* use curve optimization? */
|
||||||
double opttolerance; /* curve optimization tolerance */
|
double opttolerance; /* curve optimization tolerance */
|
||||||
potrace_progress_t progress; /* progress callback function */
|
potrace_progress_t progress; /* progress callback function */
|
||||||
};
|
};
|
||||||
typedef struct potrace_param_s potrace_param_t;
|
typedef struct potrace_param_s potrace_param_t;
|
||||||
|
|
||||||
|
@ -54,8 +58,8 @@ typedef unsigned long potrace_word;
|
||||||
* bit of scanline(n)[0]. */
|
* bit of scanline(n)[0]. */
|
||||||
struct potrace_bitmap_s
|
struct potrace_bitmap_s
|
||||||
{
|
{
|
||||||
int w, h; /* width and height, in pixels */
|
int w, h; /* width and height, in pixels */
|
||||||
int dy; /* words per scanline (not bytes) */
|
int dy; /* words per scanline (not bytes) */
|
||||||
potrace_word* map; /* raw data, dy*h words */
|
potrace_word* map; /* raw data, dy*h words */
|
||||||
};
|
};
|
||||||
typedef struct potrace_bitmap_s potrace_bitmap_t;
|
typedef struct potrace_bitmap_s potrace_bitmap_t;
|
||||||
|
@ -77,25 +81,24 @@ typedef struct potrace_dpoint_s potrace_dpoint_t;
|
||||||
/* closed curve segment */
|
/* closed curve segment */
|
||||||
struct potrace_curve_s
|
struct potrace_curve_s
|
||||||
{
|
{
|
||||||
int n; // number of segments
|
int n; /* number of segments */
|
||||||
int* tag; // tag[n]: POTRACE_CURVETO or POTRACE_CORNER
|
int* tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */
|
||||||
potrace_dpoint_t( * c )[3]; /* c[n][3]: control points.
|
potrace_dpoint_t( *c )[3]; /* c[n][3]: control points.
|
||||||
* c[n][0] is unused for tag[n]=POTRACE_CORNER
|
* c[n][0] is unused for tag[n]=POTRACE_CORNER */
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
typedef struct potrace_curve_s potrace_curve_t;
|
typedef struct potrace_curve_s potrace_curve_t;
|
||||||
|
|
||||||
/* Linked list of signed curve segments. Also carries a tree structure. */
|
/* Linked list of signed curve segments. Also carries a tree structure. */
|
||||||
struct potrace_path_s
|
struct potrace_path_s
|
||||||
{
|
{
|
||||||
int area; /* area of the bitmap path */
|
int area; /* area of the bitmap path */
|
||||||
int sign; /* '+' or '-', depending on orientation */
|
int sign; /* '+' or '-', depending on orientation */
|
||||||
potrace_curve_t curve; /* this path's vector data */
|
potrace_curve_t curve; /* this path's vector data */
|
||||||
|
|
||||||
struct potrace_path_s* next; /* linked list structure */
|
struct potrace_path_s* next; /* linked list structure */
|
||||||
|
|
||||||
struct potrace_path_s* childlist; /* tree structure */
|
struct potrace_path_s* childlist; /* tree structure */
|
||||||
struct potrace_path_s* sibling; /* tree structure */
|
struct potrace_path_s* sibling; /* tree structure */
|
||||||
|
|
||||||
struct potrace_privpath_s* priv; /* private state */
|
struct potrace_privpath_s* priv; /* private state */
|
||||||
};
|
};
|
||||||
|
@ -104,12 +107,12 @@ typedef struct potrace_path_s potrace_path_t;
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* Potrace state */
|
/* Potrace state */
|
||||||
|
|
||||||
#define POTRACE_STATUS_OK 0
|
#define POTRACE_STATUS_OK 0
|
||||||
#define POTRACE_STATUS_INCOMPLETE 1
|
#define POTRACE_STATUS_INCOMPLETE 1
|
||||||
|
|
||||||
struct potrace_state_s
|
struct potrace_state_s
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
potrace_path_t* plist; /* vector data */
|
potrace_path_t* plist; /* vector data */
|
||||||
|
|
||||||
struct potrace_privstate_s* priv; /* private state */
|
struct potrace_privstate_s* priv; /* private state */
|
||||||
|
@ -123,17 +126,21 @@ typedef struct potrace_state_s potrace_state_t;
|
||||||
potrace_param_t* potrace_param_default( void );
|
potrace_param_t* potrace_param_default( void );
|
||||||
|
|
||||||
/* free parameter set */
|
/* free parameter set */
|
||||||
void potrace_param_free( potrace_param_t* p );
|
void potrace_param_free( potrace_param_t* p );
|
||||||
|
|
||||||
/* trace a bitmap*/
|
/* trace a bitmap*/
|
||||||
potrace_state_t* potrace_trace( const potrace_param_t* param,
|
potrace_state_t* potrace_trace( const potrace_param_t* param,
|
||||||
const potrace_bitmap_t* bm );
|
const potrace_bitmap_t* bm );
|
||||||
|
|
||||||
/* free a Potrace state */
|
/* free a Potrace state */
|
||||||
void potrace_state_free( potrace_state_t* st );
|
void potrace_state_free( potrace_state_t* st );
|
||||||
|
|
||||||
/* return a static plain text version string identifying this version
|
/* return a static plain text version string identifying this version
|
||||||
* of potracelib */
|
* of potracelib */
|
||||||
const char* potrace_version( void );
|
const char* potrace_version( void );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* end of extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* POTRACELIB_H */
|
#endif /* POTRACELIB_H */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@
|
||||||
/* structure to hold progress bar callback data */
|
/* structure to hold progress bar callback data */
|
||||||
struct progress_s
|
struct progress_s
|
||||||
{
|
{
|
||||||
void (* callback)( double progress, void* privdata ); /* callback fn */
|
void (* callback)( double progress, void* privdata ); /* callback fn */
|
||||||
void* data; /* callback function's private data */
|
void* data; /* callback function's private data */
|
||||||
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
|
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
|
||||||
double epsilon; /* granularity: can skip smaller increments */
|
double epsilon; /* granularity: can skip smaller increments */
|
||||||
double b; /* upper limit of subrange in superrange units */
|
double b; /* upper limit of subrange in superrange units */
|
||||||
|
@ -30,9 +30,10 @@ static inline void progress_update( double d, progress_t* prog )
|
||||||
{
|
{
|
||||||
double d_scaled;
|
double d_scaled;
|
||||||
|
|
||||||
if( prog->callback != NULL )
|
if( prog != NULL && prog->callback != NULL )
|
||||||
{
|
{
|
||||||
d_scaled = prog->min * (1 - d) + prog->max * d;
|
d_scaled = prog->min * (1 - d) + prog->max * d;
|
||||||
|
|
||||||
if( d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon )
|
if( d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon )
|
||||||
{
|
{
|
||||||
prog->callback( prog->min * (1 - d) + prog->max * d, prog->data );
|
prog->callback( prog->min * (1 - d) + prog->max * d, prog->data );
|
||||||
|
@ -45,14 +46,14 @@ static inline void progress_update( double d, progress_t* prog )
|
||||||
/* start a subrange of the given progress object. The range is
|
/* start a subrange of the given progress object. The range is
|
||||||
* narrowed to [a..b], relative to 0.0-1.0 coordinates. If new range
|
* narrowed to [a..b], relative to 0.0-1.0 coordinates. If new range
|
||||||
* is below granularity threshold, disable further subdivisions. */
|
* is below granularity threshold, disable further subdivisions. */
|
||||||
static inline void progress_subrange_start( double a,
|
static inline void progress_subrange_start( double a,
|
||||||
double b,
|
double b,
|
||||||
const progress_t* prog,
|
const progress_t* prog,
|
||||||
progress_t* sub )
|
progress_t* sub )
|
||||||
{
|
{
|
||||||
double min, max;
|
double min, max;
|
||||||
|
|
||||||
if( prog->callback == NULL )
|
if( prog == NULL || prog->callback == NULL )
|
||||||
{
|
{
|
||||||
sub->callback = NULL;
|
sub->callback = NULL;
|
||||||
return;
|
return;
|
||||||
|
@ -67,19 +68,19 @@ static inline void progress_subrange_start( double a,
|
||||||
sub->b = b;
|
sub->b = b;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub->callback = prog->callback;
|
sub->callback = prog->callback;
|
||||||
sub->data = prog->data;
|
sub->data = prog->data;
|
||||||
sub->epsilon = prog->epsilon;
|
sub->epsilon = prog->epsilon;
|
||||||
sub->min = min;
|
sub->min = min;
|
||||||
sub->max = max;
|
sub->max = max;
|
||||||
sub->d_prev = prog->d_prev;
|
sub->d_prev = prog->d_prev;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void progress_subrange_end( progress_t* prog, progress_t* sub )
|
static inline void progress_subrange_end( progress_t* prog, progress_t* sub )
|
||||||
{
|
{
|
||||||
if( prog->callback != NULL )
|
if( prog != NULL && prog->callback != NULL )
|
||||||
{
|
{
|
||||||
if( sub->callback == NULL )
|
if( sub->callback == NULL )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: render.c 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cmath>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <render.h>
|
#include "render.h"
|
||||||
#include <greymap.h>
|
#include "greymap.h"
|
||||||
#include <auxiliary.h>
|
#include "auxiliary.h"
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* routines for anti-aliased rendering of curves */
|
/* routines for anti-aliased rendering of curves */
|
||||||
|
@ -49,18 +48,22 @@ render_t* render_new( greymap_t* gm )
|
||||||
render_t* rm;
|
render_t* rm;
|
||||||
|
|
||||||
rm = (render_t*) malloc( sizeof(render_t) );
|
rm = (render_t*) malloc( sizeof(render_t) );
|
||||||
|
|
||||||
if( !rm )
|
if( !rm )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset( rm, 0, sizeof(render_t) );
|
memset( rm, 0, sizeof(render_t) );
|
||||||
rm->gm = gm;
|
rm->gm = gm;
|
||||||
rm->incrow_buf = (int*) malloc( gm->h * sizeof(int) );
|
rm->incrow_buf = (int*) calloc( gm->h, sizeof(int) );
|
||||||
|
|
||||||
if( !rm->incrow_buf )
|
if( !rm->incrow_buf )
|
||||||
{
|
{
|
||||||
free( rm );
|
free( rm );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset( rm->incrow_buf, 0, gm->h * sizeof(int) );
|
memset( rm->incrow_buf, 0, gm->h * sizeof(int) );
|
||||||
return rm;
|
return rm;
|
||||||
}
|
}
|
||||||
|
@ -82,6 +85,7 @@ void render_close( render_t* rm )
|
||||||
{
|
{
|
||||||
render_lineto( rm, rm->x0, rm->y0 );
|
render_lineto( rm, rm->x0, rm->y0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
GM_INC( rm->gm, rm->x0i, rm->y0i, (rm->a0 + rm->a1) * 255 );
|
GM_INC( rm->gm, rm->x0i, rm->y0i, (rm->a0 + rm->a1) * 255 );
|
||||||
|
|
||||||
/* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */
|
/* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */
|
||||||
|
@ -125,13 +129,16 @@ static void incrow( render_t* rm, int x, int y, int b )
|
||||||
{
|
{
|
||||||
x = rm->gm->w;
|
x = rm->gm->w;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rm->incrow_buf[y] == 0 )
|
if( rm->incrow_buf[y] == 0 )
|
||||||
{
|
{
|
||||||
rm->incrow_buf[y] = x + 1; /* store x+1 so that we can use 0 for "vacant" */
|
rm->incrow_buf[y] = x + 1; /* store x+1 so that we can use 0 for "vacant" */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
x0 = rm->incrow_buf[y] - 1;
|
x0 = rm->incrow_buf[y] - 1;
|
||||||
rm->incrow_buf[y] = 0;
|
rm->incrow_buf[y] = 0;
|
||||||
|
|
||||||
if( x0 < x )
|
if( x0 < x )
|
||||||
{
|
{
|
||||||
for( i = x0; i<x; i++ )
|
for( i = x0; i<x; i++ )
|
||||||
|
@ -152,30 +159,31 @@ static void incrow( render_t* rm, int x, int y, int b )
|
||||||
/* render a straight line */
|
/* render a straight line */
|
||||||
void render_lineto( render_t* rm, double x2, double y2 )
|
void render_lineto( render_t* rm, double x2, double y2 )
|
||||||
{
|
{
|
||||||
int x2i, y2i;
|
int x2i, y2i;
|
||||||
double t0 = 2, s0 = 2;
|
double t0 = 2, s0 = 2;
|
||||||
int sn, tn;
|
int sn, tn;
|
||||||
double ss = 2, ts = 2;
|
double ss = 2, ts = 2;
|
||||||
double r0, r1;
|
double r0, r1;
|
||||||
int i, j;
|
int i, j;
|
||||||
int rxi, ryi;
|
int rxi, ryi;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
x2i = (int) floor( x2 );
|
x2i = (int) floor( x2 );
|
||||||
y2i = (int) floor( y2 );
|
y2i = (int) floor( y2 );
|
||||||
|
|
||||||
sn = abs( x2i - rm->x1i );
|
sn = abs( x2i - rm->x1i );
|
||||||
tn = abs( y2i - rm->y1i );
|
tn = abs( y2i - rm->y1i );
|
||||||
|
|
||||||
if( sn )
|
if( sn )
|
||||||
{
|
{
|
||||||
s0 = ( (x2>rm->x1 ? rm->x1i + 1 : rm->x1i) - rm->x1 ) / (x2 - rm->x1);
|
s0 = ( (x2>rm->x1 ? rm->x1i + 1 : rm->x1i) - rm->x1 ) / (x2 - rm->x1);
|
||||||
ss = fabs( 1.0 / (x2 - rm->x1) );
|
ss = fabs( 1.0 / (x2 - rm->x1) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( tn )
|
if( tn )
|
||||||
{
|
{
|
||||||
t0 = ( (y2>rm->y1 ? rm->y1i + 1 : rm->y1i) - rm->y1 ) / (y2 - rm->y1);
|
t0 = ( (y2>rm->y1 ? rm->y1i + 1 : rm->y1i) - rm->y1 ) / (y2 - rm->y1);
|
||||||
ts = fabs( 1.0 / (y2 - rm->y1) );
|
ts = fabs( 1.0 / (y2 - rm->y1) );
|
||||||
}
|
}
|
||||||
|
|
||||||
r0 = 0;
|
r0 = 0;
|
||||||
|
@ -200,11 +208,12 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
||||||
j++;
|
j++;
|
||||||
s = 0;
|
s = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* render line from r0 to r1 segment of (rm->x1,rm->y1)..(x2,y2) */
|
/* render line from r0 to r1 segment of (rm->x1,rm->y1)..(x2,y2) */
|
||||||
|
|
||||||
/* move point to r1 */
|
/* move point to r1 */
|
||||||
rm->a1 +=
|
rm->a1 += (r1 - r0) * (y2 - rm->y1) *
|
||||||
(r1 - r0) * (y2 - rm->y1) * ( rxi + 1 - ( (r0 + r1) / 2.0 * (x2 - rm->x1) + rm->x1 ) );
|
( rxi + 1 - ( (r0 + r1) / 2.0 * (x2 - rm->x1) + rm->x1 ) );
|
||||||
|
|
||||||
/* move point across pixel boundary */
|
/* move point across pixel boundary */
|
||||||
if( s && x2>rm->x1 )
|
if( s && x2>rm->x1 )
|
||||||
|
@ -241,8 +250,9 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
||||||
|
|
||||||
/* move point to (x2,y2) */
|
/* move point to (x2,y2) */
|
||||||
|
|
||||||
r1 = 1;
|
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->x1i = x2i;
|
||||||
rm->y1i = y2i;
|
rm->y1i = y2i;
|
||||||
|
@ -254,18 +264,13 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
||||||
|
|
||||||
|
|
||||||
/* render a Bezier curve. */
|
/* render a Bezier curve. */
|
||||||
void render_curveto( render_t* rm,
|
void render_curveto( render_t* rm, double x2, double y2, double x3, double y3, double x4,
|
||||||
double x2,
|
double y4 )
|
||||||
double y2,
|
|
||||||
double x3,
|
|
||||||
double y3,
|
|
||||||
double x4,
|
|
||||||
double y4 )
|
|
||||||
{
|
{
|
||||||
double x1, y1, dd0, dd1, dd, delta, e2, epsilon, t;
|
double x1, y1, dd0, dd1, dd, delta, e2, epsilon, t;
|
||||||
|
|
||||||
x1 = rm->x1; /* starting point */
|
x1 = rm->x1; /* starting point */
|
||||||
y1 = rm->y1;
|
y1 = rm->y1;
|
||||||
|
|
||||||
/* we approximate the curve by small line segments. The interval
|
/* we approximate the curve by small line segments. The interval
|
||||||
* size, epsilon, is determined on the fly so that the distance
|
* size, epsilon, is determined on the fly so that the distance
|
||||||
|
@ -276,18 +281,18 @@ void render_curveto( render_t* rm,
|
||||||
|
|
||||||
/* let dd = maximal value of 2nd derivative over curve - this must
|
/* let dd = maximal value of 2nd derivative over curve - this must
|
||||||
* occur at an endpoint. */
|
* occur at an endpoint. */
|
||||||
dd0 = sq( x1 - 2 * x2 + x3 ) + sq( y1 - 2 * y2 + y3 );
|
dd0 = sq( x1 - 2 * x2 + x3 ) + sq( y1 - 2 * y2 + y3 );
|
||||||
dd1 = sq( x2 - 2 * x3 + x4 ) + sq( y2 - 2 * y3 + y4 );
|
dd1 = sq( x2 - 2 * x3 + x4 ) + sq( y2 - 2 * y3 + y4 );
|
||||||
dd = 6 * sqrt( max( dd0, dd1 ) );
|
dd = 6 * sqrt( max( dd0, dd1 ) );
|
||||||
e2 = 8 * delta <= dd ? 8 * delta / dd : 1;
|
e2 = 8 * delta <= dd ? 8 * delta / dd : 1;
|
||||||
epsilon = sqrt( e2 ); /* necessary interval size */
|
epsilon = sqrt( e2 ); /* necessary interval size */
|
||||||
|
|
||||||
for( t = epsilon; t<1; t += epsilon )
|
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(
|
render_lineto( rm, x1 * cu( 1 - t ) + 3 * x2 * sq( 1 - t ) * t + 3 * x3 * (1 - t) * sq(
|
||||||
t ) + x4 * cu( t ),
|
t ) + x4 * cu( t ),
|
||||||
y1 * cu( 1 - t ) + 3 * y2 * sq( 1 - t ) * t + 3 * y3 * (1 - t) * sq(
|
y1 * cu( 1 - t ) + 3 * y2 * sq( 1 - t ) * t + 3 * y3 * (1 - t) * sq( t ) + y4 *
|
||||||
t ) + y4 * cu( t ) );
|
cu( t ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
render_lineto( rm, x4, y4 );
|
render_lineto( rm, x4, y4 );
|
||||||
|
|
|
@ -1,35 +1,34 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: render.h 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
|
|
||||||
#ifndef RENDER_H
|
#ifndef RENDER_H
|
||||||
#define RENDER_H
|
#define RENDER_H
|
||||||
|
|
||||||
#include <greymap.h>
|
#include "greymap.h"
|
||||||
|
|
||||||
struct render_s
|
struct render_s
|
||||||
{
|
{
|
||||||
greymap_t* gm;
|
greymap_t* gm;
|
||||||
double x0, y0, x1, y1;
|
double x0, y0, x1, y1;
|
||||||
int x0i, y0i, x1i, y1i;
|
int x0i, y0i, x1i, y1i;
|
||||||
double a0, a1;
|
double a0, a1;
|
||||||
int* incrow_buf;
|
int* incrow_buf;
|
||||||
};
|
};
|
||||||
typedef struct render_s render_t;
|
typedef struct render_s render_t;
|
||||||
|
|
||||||
render_t* render_new( greymap_t* gm );
|
render_t* render_new( greymap_t* gm );
|
||||||
void render_free( render_t* rm );
|
void render_free( render_t* rm );
|
||||||
void render_close( render_t* rm );
|
void render_close( render_t* rm );
|
||||||
void render_moveto( render_t* rm, double x, double y );
|
void render_moveto( render_t* rm, double x, double y );
|
||||||
void render_lineto( render_t* rm, double x, double y );
|
void render_lineto( render_t* rm, double x, double y );
|
||||||
void render_curveto( render_t* rm,
|
void render_curveto( render_t* rm,
|
||||||
double x2,
|
double x2,
|
||||||
double y2,
|
double y2,
|
||||||
double x3,
|
double x3,
|
||||||
double y3,
|
double y3,
|
||||||
double x4,
|
double x4,
|
||||||
double y4 );
|
double y4 );
|
||||||
|
|
||||||
#endif /* RENDER_H */
|
#endif /* RENDER_H */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,14 @@
|
||||||
/* Copyright (C) 2001-2007 Peter Selinger.
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
/* $Id: trace.h 147 2007-04-09 00:44:09Z selinger $ */
|
|
||||||
|
|
||||||
#ifndef TRACE_H
|
#ifndef TRACE_H
|
||||||
#define TRACE_H
|
#define TRACE_H
|
||||||
|
|
||||||
#include <potracelib.h>
|
#include "potracelib.h"
|
||||||
#include <progress.h>
|
#include "progress.h"
|
||||||
|
#include "curve.h"
|
||||||
|
|
||||||
int process_path( path_t* plist, const potrace_param_t* param, progress_t* progress );
|
int process_path( path_t* plist, const potrace_param_t* param, progress_t* progress );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue