2015-12-03 15:46:17 +00:00
|
|
|
/* Copyright (C) 2001-2015 Peter Selinger.
|
2010-06-10 18:43:12 +00:00
|
|
|
* This file is part of Potrace. It is free software and it is covered
|
|
|
|
* by the GNU General Public License. See the file COPYING for details. */
|
|
|
|
|
|
|
|
#ifndef BITMAP_H
|
|
|
|
#define BITMAP_H
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2015-12-03 15:46:17 +00:00
|
|
|
#include <errno.h>
|
2016-02-28 17:04:51 +00:00
|
|
|
#include <stddef.h>
|
2010-06-10 18:43:12 +00:00
|
|
|
|
|
|
|
/* The bitmap type is defined in potracelib.h */
|
2015-12-03 15:46:17 +00:00
|
|
|
#include "potracelib.h"
|
2010-06-10 18:43:12 +00:00
|
|
|
|
|
|
|
/* The present file defines some convenient macros and static inline
|
|
|
|
* functions for accessing bitmaps. Since they only produce inline
|
|
|
|
* code, they can be conveniently shared by the library and frontends,
|
|
|
|
* if desired */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* some measurements */
|
|
|
|
|
|
|
|
#define BM_WORDSIZE ( (int) sizeof(potrace_word) )
|
|
|
|
#define BM_WORDBITS (8 * BM_WORDSIZE)
|
|
|
|
#define BM_HIBIT ( ( (potrace_word) 1 ) << (BM_WORDBITS - 1) )
|
|
|
|
#define BM_ALLBITS (~(potrace_word) 0)
|
|
|
|
|
|
|
|
/* macros for accessing pixel at index (x,y). U* macros omit the
|
|
|
|
* bounds check. */
|
|
|
|
|
2016-02-28 17:04:51 +00:00
|
|
|
#define bm_scanline( bm, y ) ( (bm)->map + (ptrdiff_t) (y) * (ptrdiff_t) (bm)->dy )
|
2015-12-03 15:46:17 +00:00
|
|
|
#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_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_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_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_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_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_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)
|
2010-06-10 18:43:12 +00:00
|
|
|
|
|
|
|
/* free the given bitmap. Leaves errno untouched. */
|
|
|
|
static inline void bm_free( potrace_bitmap_t* bm )
|
|
|
|
{
|
|
|
|
if( bm )
|
|
|
|
{
|
|
|
|
free( bm->map );
|
|
|
|
}
|
2015-12-03 15:46:17 +00:00
|
|
|
|
2010-06-10 18:43:12 +00:00
|
|
|
free( bm );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-03 15:46:17 +00:00
|
|
|
/* return new un-initialized bitmap. NULL with errno on error.
|
|
|
|
* Assumes w, h >= 0. */
|
2010-06-10 18:43:12 +00:00
|
|
|
static inline potrace_bitmap_t* bm_new( int w, int h )
|
|
|
|
{
|
|
|
|
potrace_bitmap_t* bm;
|
2015-12-03 15:46:17 +00:00
|
|
|
int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1;
|
2016-02-28 17:04:51 +00:00
|
|
|
ptrdiff_t size = (ptrdiff_t) dy * (ptrdiff_t) h * (ptrdiff_t) BM_WORDSIZE;
|
2015-12-03 15:46:17 +00:00
|
|
|
|
|
|
|
/* check for overflow error */
|
2016-02-28 17:04:51 +00:00
|
|
|
if( size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE) )
|
2015-12-03 15:46:17 +00:00
|
|
|
{
|
|
|
|
errno = ENOMEM;
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-06-10 18:43:12 +00:00
|
|
|
|
|
|
|
bm = (potrace_bitmap_t*) malloc( sizeof(potrace_bitmap_t) );
|
2015-12-03 15:46:17 +00:00
|
|
|
|
2010-06-10 18:43:12 +00:00
|
|
|
if( !bm )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-12-03 15:46:17 +00:00
|
|
|
|
2010-06-10 18:43:12 +00:00
|
|
|
bm->w = w;
|
|
|
|
bm->h = h;
|
|
|
|
bm->dy = dy;
|
2015-12-03 15:46:17 +00:00
|
|
|
bm->map = (potrace_word*) malloc( size );
|
|
|
|
|
2010-06-10 18:43:12 +00:00
|
|
|
if( !bm->map )
|
|
|
|
{
|
|
|
|
free( bm );
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-12-03 15:46:17 +00:00
|
|
|
|
2010-06-10 18:43:12 +00:00
|
|
|
return bm;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* clear the given bitmap. Set all bits to c. */
|
|
|
|
static inline void bm_clear( potrace_bitmap_t* bm, int c )
|
|
|
|
{
|
2015-12-03 15:46:17 +00:00
|
|
|
/* Note: if the bitmap was created with bm_new, then it is
|
2016-02-28 17:04:51 +00:00
|
|
|
* guaranteed that size will fit into the ptrdiff_t type. */
|
|
|
|
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h * (ptrdiff_t) BM_WORDSIZE;
|
2015-12-03 15:46:17 +00:00
|
|
|
|
|
|
|
memset( bm->map, c ? -1 : 0, size );
|
2010-06-10 18:43:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* duplicate the given bitmap. Return NULL on error with errno set. */
|
|
|
|
static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
|
|
|
{
|
|
|
|
potrace_bitmap_t* bm1 = bm_new( bm->w, bm->h );
|
2016-02-28 17:04:51 +00:00
|
|
|
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h * (ptrdiff_t) BM_WORDSIZE;
|
2010-06-10 18:43:12 +00:00
|
|
|
|
|
|
|
if( !bm1 )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-12-03 15:46:17 +00:00
|
|
|
|
|
|
|
memcpy( bm1->map, bm->map, size );
|
2010-06-10 18:43:12 +00:00
|
|
|
return bm1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* invert the given bitmap. */
|
|
|
|
static inline void bm_invert( potrace_bitmap_t* bm )
|
|
|
|
{
|
2016-02-28 17:04:51 +00:00
|
|
|
ptrdiff_t i;
|
|
|
|
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h;
|
2010-06-10 18:43:12 +00:00
|
|
|
|
2015-12-03 15:46:17 +00:00
|
|
|
for( i = 0; i < size; i++ )
|
2010-06-10 18:43:12 +00:00
|
|
|
{
|
|
|
|
bm->map[i] ^= BM_ALLBITS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* BITMAP_H */
|