more flood speedups
This commit is contained in:
parent
1b5dd8524a
commit
3d959dbe3b
@ -187,27 +187,12 @@ buffer_add( Buffer *buf, Flood *flood, int x1, int x2, int y, int dir )
|
|||||||
/* Is p "connected"? ie. is equal to or not equal to flood->edge, depending on
|
/* Is p "connected"? ie. is equal to or not equal to flood->edge, depending on
|
||||||
* whether we are flooding to the edge boundary or flooding edge-coloured
|
* whether we are flooding to the edge boundary or flooding edge-coloured
|
||||||
* pixels.
|
* pixels.
|
||||||
*
|
|
||||||
* If test and mark are different images, we also need to check ink to make
|
|
||||||
* sure we haven't painted this pixel before. Otherwise we can get stuck in
|
|
||||||
* loops.
|
|
||||||
*/
|
*/
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
flood_connected( Flood *flood, PEL *tp, PEL *mp )
|
flood_connected( Flood *flood, PEL *tp )
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if( flood->test != flood->mark ) {
|
|
||||||
for( j = 0; j < flood->msize; j++ )
|
|
||||||
if( mp[j] != flood->ink[j] )
|
|
||||||
break;
|
|
||||||
|
|
||||||
if( j == flood->msize )
|
|
||||||
/* We've painted this before, can't be connected now.
|
|
||||||
*/
|
|
||||||
return( FALSE );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( j = 0; j < flood->tsize; j++ )
|
for( j = 0; j < flood->tsize; j++ )
|
||||||
if( tp[j] != flood->edge[j] )
|
if( tp[j] != flood->edge[j] )
|
||||||
break;
|
break;
|
||||||
@ -217,6 +202,20 @@ flood_connected( Flood *flood, PEL *tp, PEL *mp )
|
|||||||
return( flood->equal ^ (j < flood->tsize) );
|
return( flood->equal ^ (j < flood->tsize) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is p painted?
|
||||||
|
*/
|
||||||
|
static inline gboolean
|
||||||
|
flood_painted( Flood *flood, PEL *mp )
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for( j = 0; j < flood->msize; j++ )
|
||||||
|
if( mp[j] != flood->ink[j] )
|
||||||
|
break;
|
||||||
|
|
||||||
|
return( j == flood->msize );
|
||||||
|
}
|
||||||
|
|
||||||
/* Faster than memcpy for n < about 20.
|
/* Faster than memcpy for n < about 20.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
@ -229,7 +228,7 @@ flood_paint( Flood *flood, PEL *q )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fill left and right, return the endpoints. The start point (x, y) must be
|
/* Fill left and right, return the endpoints. The start point (x, y) must be
|
||||||
* connected.
|
* connected and unpainted.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
flood_scanline( Flood *flood, int x, int y, int *x1, int *x2 )
|
flood_scanline( Flood *flood, int x, int y, int *x1, int *x2 )
|
||||||
@ -239,33 +238,43 @@ flood_scanline( Flood *flood, int x, int y, int *x1, int *x2 )
|
|||||||
PEL *tp;
|
PEL *tp;
|
||||||
PEL *mp;
|
PEL *mp;
|
||||||
int i;
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
g_assert( flood_connected( flood,
|
g_assert( flood_connected( flood,
|
||||||
(PEL *) IM_IMAGE_ADDR( flood->test, x, y ),
|
(PEL *) IM_IMAGE_ADDR( flood->test, x, y ) ) );
|
||||||
|
g_assert( !flood_painted( flood,
|
||||||
(PEL *) IM_IMAGE_ADDR( flood->mark, x, y ) ) );
|
(PEL *) IM_IMAGE_ADDR( flood->mark, x, y ) ) );
|
||||||
|
|
||||||
/* Fill this pixel and to the right.
|
/* Search to the right for the first non-connected pixel. If the start
|
||||||
|
* pixel is unpainted, we know all the intervening pixels must be
|
||||||
|
* unpainted too.
|
||||||
*/
|
*/
|
||||||
tp = (PEL *) IM_IMAGE_ADDR( flood->test, x, y );
|
tp = (PEL *) IM_IMAGE_ADDR( flood->test, x, y );
|
||||||
mp = (PEL *) IM_IMAGE_ADDR( flood->mark, x, y );
|
for( i = x; i < width; i++ ) {
|
||||||
for( i = x; i < width && flood_connected( flood, tp, mp ); i++ ) {
|
if( !flood_connected( flood, tp ) )
|
||||||
flood_paint( flood, mp );
|
break;
|
||||||
tp += flood->tsize;
|
tp += flood->tsize;
|
||||||
mp += flood->msize;
|
|
||||||
}
|
}
|
||||||
*x2 = i - 1;
|
*x2 = i - 1;
|
||||||
|
|
||||||
/* Fill to the left.
|
/* Search left.
|
||||||
*/
|
*/
|
||||||
tp = (PEL *) IM_IMAGE_ADDR( flood->test, x - 1, y );
|
tp = (PEL *) IM_IMAGE_ADDR( flood->test, x - 1, y );
|
||||||
mp = (PEL *) IM_IMAGE_ADDR( flood->mark, x - 1, y );
|
for( i = x - 1; i > 0; i-- ) {
|
||||||
for( i = x - 1; i > 0 && flood_connected( flood, tp, mp ); i-- ) {
|
if( !flood_connected( flood, tp ) )
|
||||||
flood_paint( flood, mp );
|
break;
|
||||||
tp -= flood->tsize;
|
tp -= flood->tsize;
|
||||||
mp -= flood->msize;
|
|
||||||
}
|
}
|
||||||
*x1 = i + 1;
|
*x1 = i + 1;
|
||||||
|
|
||||||
|
/* Paint the range we discovered.
|
||||||
|
*/
|
||||||
|
mp = (PEL *) IM_IMAGE_ADDR( flood->mark, x, y );
|
||||||
|
for( i = *x1; i <= *x2; i++ ) {
|
||||||
|
flood_paint( flood, mp );
|
||||||
|
mp += flood->msize;
|
||||||
|
}
|
||||||
|
|
||||||
if( flood->dout ) {
|
if( flood->dout ) {
|
||||||
flood->left = IM_MIN( flood->left, *x1 );
|
flood->left = IM_MIN( flood->left, *x1 );
|
||||||
flood->right = IM_MAX( flood->right, *x2 );
|
flood->right = IM_MAX( flood->right, *x2 );
|
||||||
@ -285,18 +294,29 @@ flood_scanline( Flood *flood, int x, int y, int *x1, int *x2 )
|
|||||||
static void
|
static void
|
||||||
flood_around( Flood *flood, Scan *scan )
|
flood_around( Flood *flood, Scan *scan )
|
||||||
{
|
{
|
||||||
|
PEL *tp;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
g_assert( scan->dir == 1 || scan->dir == -1 );
|
g_assert( scan->dir == 1 || scan->dir == -1 );
|
||||||
|
|
||||||
|
tp = (PEL *) IM_IMAGE_ADDR( flood->test, scan->x1, scan->y );
|
||||||
for( x = scan->x1; x <= scan->x2; x++ ) {
|
for( x = scan->x1; x <= scan->x2; x++ ) {
|
||||||
PEL *tp = (PEL *) IM_IMAGE_ADDR( flood->test, x, scan->y );
|
if( flood_connected( flood, tp ) ) {
|
||||||
PEL *mp = (PEL *) IM_IMAGE_ADDR( flood->mark, x, scan->y );
|
|
||||||
|
|
||||||
if( flood_connected( flood, tp, mp ) ) {
|
|
||||||
int x1a;
|
int x1a;
|
||||||
int x2a;
|
int x2a;
|
||||||
|
|
||||||
|
/* If mark and test are different images, we also need
|
||||||
|
* to check for painted. Otherwise we can get stuck in
|
||||||
|
* connected loops.
|
||||||
|
*/
|
||||||
|
if( flood->mark != flood->test ) {
|
||||||
|
PEL *mp = (PEL *) IM_IMAGE_ADDR(
|
||||||
|
flood->mark, x, scan->y );
|
||||||
|
|
||||||
|
if( flood_painted( flood, mp ) )
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
flood_scanline( flood, x, scan->y, &x1a, &x2a );
|
flood_scanline( flood, x, scan->y, &x1a, &x2a );
|
||||||
|
|
||||||
/* Our new scanline can have up to three more
|
/* Our new scanline can have up to three more
|
||||||
@ -316,7 +336,10 @@ flood_around( Flood *flood, Scan *scan )
|
|||||||
scan->dir );
|
scan->dir );
|
||||||
|
|
||||||
x = x2a;
|
x = x2a;
|
||||||
|
tp = (PEL *) IM_IMAGE_ADDR( flood->test, x, scan->y );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tp += flood->tsize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,8 +364,7 @@ flood_all( Flood *flood, int x, int y )
|
|||||||
/* Test start pixel ... nothing to do?
|
/* Test start pixel ... nothing to do?
|
||||||
*/
|
*/
|
||||||
if( flood_connected( flood,
|
if( flood_connected( flood,
|
||||||
(PEL *) IM_IMAGE_ADDR( flood->test, x, y ),
|
(PEL *) IM_IMAGE_ADDR( flood->test, x, y ) ) ) {
|
||||||
(PEL *) IM_IMAGE_ADDR( flood->mark, x, y ) ) ) {
|
|
||||||
int x1, x2;
|
int x1, x2;
|
||||||
|
|
||||||
flood_scanline( flood, x, y, &x1, &x2 );
|
flood_scanline( flood, x, y, &x1, &x2 );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user