diff --git a/ChangeLog b/ChangeLog index f357dce35a..29d6612918 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2005-07-14 Sven Neumann + + * app/paint-funcs/paint-funcs.[ch]: added erode_region() and + dilate_region(). Less general than thin_region() and fatten_region() + but a little faster. + + * app/base/siox.c: use the new functions. + 2005-07-14 Michael Natterer * app/widgets/Makefile.am diff --git a/app/base/siox.c b/app/base/siox.c index 00a1de6108..47f18edf48 100644 --- a/app/base/siox.c +++ b/app/base/siox.c @@ -16,6 +16,8 @@ * by Gerald Friedland * and Kristian Jantz . * + * Adapted for GIMP by Sven Neumann + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -649,8 +651,7 @@ erode_mask (TileManager *mask, pixel_region_init (®ion, mask, x, y, width, height, TRUE); - /* inefficient */ - thin_region (®ion, 1, 1, TRUE); + erode_region (®ion); } static void @@ -664,8 +665,7 @@ dilate_mask (TileManager *mask, pixel_region_init (®ion, mask, x, y, width, height, TRUE); - /* inefficient */ - fatten_region (®ion, 1, 1); + dilate_region (®ion); } static void diff --git a/app/paint-funcs/paint-funcs.c b/app/paint-funcs/paint-funcs.c index 5eaea8a86c..e1fbfac335 100644 --- a/app/paint-funcs/paint-funcs.c +++ b/app/paint-funcs/paint-funcs.c @@ -3350,7 +3350,7 @@ smooth_region (PixelRegion *region) memcpy (buf[2], buf[1], width + 2); } - for (x = 0 ; x < width; x++) /* render scan line */ + for (x = 0 ; x < width; x++) { gint value = (buf[0][x] + buf[0][x+1] + buf[0][x+2] + buf[1][x] + buf[2][x+1] + buf[1][x+2] + @@ -3370,6 +3370,142 @@ smooth_region (PixelRegion *region) g_free (out); } +/* Erode (radius 1 pixel) a mask (1bpp). */ +void +erode_region (PixelRegion *region) +{ + gint x, y; + gint width; + gint i; + guchar *buf[3]; + guchar *out; + + width = region->w; + + for (i = 0; i < 3; i++) + buf[i] = g_new (guchar, width + 2); + + out = g_new (guchar, width); + + /* load top of image */ + pixel_region_get_row (region, region->x, region->y, width, buf[0] + 1, 1); + + buf[0][0] = buf[0][1]; + buf[0][width + 1] = buf[0][width]; + + memcpy (buf[1], buf[2], width + 2); + + for (y = 0; y < region->h; y++) + { + if (y + 1 < region->h) + { + pixel_region_get_row (region, region->x, region->y + y + 1, width, + buf[2] + 1, 1); + + buf[2][0] = buf[2][1]; + buf[2][width + 1] = buf[2][width]; + } + else + { + memcpy (buf[2], buf[1], width + 2); + } + + for (x = 0 ; x < width; x++) + { + gint min = 255; + + if (buf[0][x] < min) min = buf[0][x]; + if (buf[0][x+1] < min) min = buf[0][x+1]; + if (buf[0][x+2] < min) min = buf[0][x+2]; + if (buf[1][x] < min) min = buf[1][x]; + if (buf[1][x+1] < min) min = buf[1][x+1]; + if (buf[1][x+2] < min) min = buf[1][x+2]; + if (buf[2][x] < min) min = buf[2][x]; + if (buf[2][x+1] < min) min = buf[2][x+1]; + if (buf[2][x+2] < min) min = buf[2][x+2]; + + out[x] = min; + } + + pixel_region_set_row (region, region->x, region->y + y, width, out); + + rotate_pointers (buf, 3); + } + + for (i = 0; i < 3; i++) + g_free (buf[i]); + + g_free (out); +} + +/* Dilate (radius 1 pixel) a mask (1bpp). */ +void +dilate_region (PixelRegion *region) +{ + gint x, y; + gint width; + gint i; + guchar *buf[3]; + guchar *out; + + width = region->w; + + for (i = 0; i < 3; i++) + buf[i] = g_new (guchar, width + 2); + + out = g_new (guchar, width); + + /* load top of image */ + pixel_region_get_row (region, region->x, region->y, width, buf[0] + 1, 1); + + buf[0][0] = buf[0][1]; + buf[0][width + 1] = buf[0][width]; + + memcpy (buf[1], buf[2], width + 2); + + for (y = 0; y < region->h; y++) + { + if (y + 1 < region->h) + { + pixel_region_get_row (region, region->x, region->y + y + 1, width, + buf[2] + 1, 1); + + buf[2][0] = buf[2][1]; + buf[2][width + 1] = buf[2][width]; + } + else + { + memcpy (buf[2], buf[1], width + 2); + } + + for (x = 0 ; x < width; x++) + { + gint max = 0; + + if (buf[0][x] < max) max = buf[0][x]; + if (buf[0][x+1] < max) max = buf[0][x+1]; + if (buf[0][x+2] < max) max = buf[0][x+2]; + if (buf[1][x] < max) max = buf[1][x]; + if (buf[1][x+1] < max) max = buf[1][x+1]; + if (buf[1][x+2] < max) max = buf[1][x+2]; + if (buf[2][x] < max) max = buf[2][x]; + if (buf[2][x+1] < max) max = buf[2][x+1]; + if (buf[2][x+2] < max) max = buf[2][x+2]; + + out[x] = max; + } + + pixel_region_set_row (region, region->x, region->y + y, width, out); + + rotate_pointers (buf, 3); + } + + for (i = 0; i < 3; i++) + g_free (buf[i]); + + g_free (out); +} + static void compute_transition (guchar *transition, guchar **buf, diff --git a/app/paint-funcs/paint-funcs.h b/app/paint-funcs/paint-funcs.h index 9c0400e7db..665be0d380 100644 --- a/app/paint-funcs/paint-funcs.h +++ b/app/paint-funcs/paint-funcs.h @@ -388,6 +388,8 @@ void fatten_region (PixelRegion *region, gint16 yradius); void smooth_region (PixelRegion *region); +void erode_region (PixelRegion *region); +void dilate_region (PixelRegion *region); void swap_region (PixelRegion *src, PixelRegion *dest);