[gimp] app: port the mask border operation from u8 to float
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: port the mask border operation from u8 to float
- Date: Sat, 24 Aug 2013 17:49:44 +0000 (UTC)
commit 05646749f52b53accac873f5d4dcc52f0b188665
Author: Michael Natterer <mitch gimp org>
Date: Sat Aug 24 19:48:01 2013 +0200
app: port the mask border operation from u8 to float
app/operations/gimpoperationborder.c | 162 ++++++++++++++++++++--------------
1 files changed, 94 insertions(+), 68 deletions(-)
---
diff --git a/app/operations/gimpoperationborder.c b/app/operations/gimpoperationborder.c
index 7b25851..ab0fa1b 100644
--- a/app/operations/gimpoperationborder.c
+++ b/app/operations/gimpoperationborder.c
@@ -199,8 +199,8 @@ gimp_operation_border_set_property (GObject *object,
static void
gimp_operation_border_prepare (GeglOperation *operation)
{
- gegl_operation_set_format (operation, "input", babl_format ("Y u8"));
- gegl_operation_set_format (operation, "output", babl_format ("Y u8"));
+ gegl_operation_set_format (operation, "input", babl_format ("Y float"));
+ gegl_operation_set_format (operation, "output", babl_format ("Y float"));
}
static GeglRectangle
@@ -219,11 +219,11 @@ gimp_operation_border_get_cached_region (GeglOperation *self,
}
static inline void
-rotate_pointers (guchar **p,
+rotate_pointers (gfloat **p,
guint32 n)
{
guint32 i;
- guchar *tmp;
+ gfloat *tmp;
tmp = p[0];
@@ -236,8 +236,8 @@ rotate_pointers (guchar **p,
/* Computes whether pixels in `buf[1]', if they are selected, have neighbouring
pixels that are unselected. Put result in `transition'. */
static void
-compute_transition (guchar *transition,
- guchar **buf,
+compute_transition (gfloat *transition,
+ gfloat **buf,
gint32 width,
gboolean edge_lock)
{
@@ -245,84 +245,84 @@ compute_transition (guchar *transition,
if (width == 1)
{
- if (buf[1][0] > 127 && (buf[0][0] < 128 || buf[2][0] < 128))
- transition[0] = 255;
+ if (buf[1][0] >= 0.5 && (buf[0][0] < 0.5 || buf[2][0] < 0.5))
+ transition[0] = 1.0;
else
- transition[0] = 0;
+ transition[0] = 0.0;
return;
}
- if (buf[1][0] > 127 && edge_lock)
+ if (buf[1][0] >= 0.5 && edge_lock)
{
/* The pixel to the left (outside of the canvas) is considered selected,
so we check if there are any unselected pixels in neighbouring pixels
_on_ the canvas. */
- if (buf[0][x] < 128 || buf[0][x + 1] < 128 ||
- buf[1][x + 1] < 128 ||
- buf[2][x] < 128 || buf[2][x + 1] < 128 )
+ if (buf[0][x] < 0.5 || buf[0][x + 1] < 0.5 ||
+ buf[1][x + 1] < 0.5 ||
+ buf[2][x] < 0.5 || buf[2][x + 1] < 0.5 )
{
- transition[x] = 255;
+ transition[x] = 1.0;
}
else
{
- transition[x] = 0;
+ transition[x] = 0.0;
}
}
- else if (buf[1][0] > 127 && !edge_lock)
+ else if (buf[1][0] >= 0.5 && !edge_lock)
{
/* We must not care about neighbouring pixels on the image canvas since
there always are unselected pixels to the left (which is outside of
the image canvas). */
- transition[x] = 255;
+ transition[x] = 1.0;
}
else
{
- transition[x] = 0;
+ transition[x] = 0.0;
}
for (x = 1; x < width - 1; x++)
{
- if (buf[1][x] >= 128)
+ if (buf[1][x] >= 0.5)
{
- if (buf[0][x - 1] < 128 || buf[0][x] < 128 || buf[0][x + 1] < 128 ||
- buf[1][x - 1] < 128 || buf[1][x + 1] < 128 ||
- buf[2][x - 1] < 128 || buf[2][x] < 128 || buf[2][x + 1] < 128)
- transition[x] = 255;
+ if (buf[0][x - 1] < 0.5 || buf[0][x] < 0.5 || buf[0][x + 1] < 0.5 ||
+ buf[1][x - 1] < 0.5 || buf[1][x + 1] < 0.5 ||
+ buf[2][x - 1] < 0.5 || buf[2][x] < 0.5 || buf[2][x + 1] < 0.5)
+ transition[x] = 1.0;
else
- transition[x] = 0;
+ transition[x] = 0.0;
}
else
{
- transition[x] = 0;
+ transition[x] = 0.0;
}
}
- if (buf[1][width - 1] >= 128 && edge_lock)
+ if (buf[1][width - 1] >= 0.5 && edge_lock)
{
/* The pixel to the right (outside of the canvas) is considered selected,
so we check if there are any unselected pixels in neighbouring pixels
_on_ the canvas. */
- if ( buf[0][x - 1] < 128 || buf[0][x] < 128 ||
- buf[1][x - 1] < 128 ||
- buf[2][x - 1] < 128 || buf[2][x] < 128)
+ if ( buf[0][x - 1] < 0.5 || buf[0][x] < 0.5 ||
+ buf[1][x - 1] < 0.5 ||
+ buf[2][x - 1] < 0.5 || buf[2][x] < 0.5)
{
- transition[width - 1] = 255;
+ transition[width - 1] = 1.0;
}
else
{
- transition[width - 1] = 0;
+ transition[width - 1] = 0.0;
}
}
- else if (buf[1][width - 1] >= 128 && !edge_lock)
+ else if (buf[1][width - 1] >= 0.5 && !edge_lock)
{
/* We must not care about neighbouring pixels on the image canvas since
there always are unselected pixels to the right (which is outside of
the image canvas). */
- transition[width - 1] = 255;
+ transition[width - 1] = 1.0;
}
else
{
- transition[width - 1] = 0;
+ transition[width - 1] = 0.0;
}
}
@@ -337,47 +337,55 @@ gimp_operation_border_process (GeglOperation *operation,
* them on jaycox gimp org
*/
GimpOperationBorder *self = GIMP_OPERATION_BORDER (operation);
- const Babl *input_format = babl_format ("Y u8");
- const Babl *output_format = babl_format ("Y u8");
+ const Babl *input_format = babl_format ("Y float");
+ const Babl *output_format = babl_format ("Y float");
gint32 i, j, x, y;
/* A cache used in the algorithm as it works its way down. `buf[1]' is the
current row. Thus, at algorithm initialization, `buf[0]' represents the
row 'above' the first row of the region. */
- guchar *buf[3];
+ gfloat *buf[3];
/* The resulting selection is calculated row by row, and this buffer holds the
output for each individual row, on each iteration. */
- guchar *out;
+ gfloat *out;
/* Keeps track of transitional pixels (pixels that are selected and have
unselected neighbouring pixels). */
- guchar **transition;
+ gfloat **transition;
/* TODO: Figure out role clearly in algorithm. */
gint16 *max;
/* TODO: Figure out role clearly in algorithm. */
- guchar **density;
+ gfloat **density;
gint16 last_index;
/* optimize this case specifically */
if (self->radius_x == 1 && self->radius_y == 1)
{
- guchar *transition;
- guchar *source[3];
+ gfloat *transition;
+ gfloat *source[3];
for (i = 0; i < 3; i++)
- source[i] = g_new (guchar, roi->width);
+ source[i] = g_new (gfloat, roi->width);
- transition = g_new (guchar, roi->width);
+ transition = g_new (gfloat, roi->width);
/* With `self->edge_lock', initialize row above image as
* selected, otherwise, initialize as unselected.
*/
- memset (source[0], self->edge_lock ? 255 : 0, roi->width);
+ if (self->edge_lock)
+ {
+ for (i = 0; i < roi->width; i++)
+ source[0][i] = 1.0;
+ }
+ else
+ {
+ memset (source[0], 0, roi->width * sizeof (gfloat));
+ }
gegl_buffer_get (input,
GEGL_RECTANGLE (roi->x, roi->y + 0,
@@ -392,7 +400,7 @@ gimp_operation_border_process (GeglOperation *operation,
1.0, input_format, source[2],
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
else
- memcpy (source[2], source[1], roi->width);
+ memcpy (source[2], source[1], roi->width * sizeof (gfloat));
compute_transition (transition, source, roi->width, self->edge_lock);
gegl_buffer_set (output,
@@ -418,7 +426,15 @@ gimp_operation_border_process (GeglOperation *operation,
/* Depending on `self->edge_lock', set the row below the
* image as either selected or non-selected.
*/
- memset(source[2], self->edge_lock ? 255 : 0, roi->width);
+ if (self->edge_lock)
+ {
+ for (i = 0; i < roi->width; i++)
+ source[2][i] = 1.0;
+ }
+ else
+ {
+ memset (source[2], 0, roi->width * sizeof (gfloat));
+ }
}
compute_transition (transition, source, roi->width, self->edge_lock);
@@ -446,26 +462,27 @@ gimp_operation_border_process (GeglOperation *operation,
max += self->radius_x;
for (i = 0; i < 3; i++)
- buf[i] = g_new (guchar, roi->width);
+ buf[i] = g_new (gfloat, roi->width);
- transition = g_new (guchar *, self->radius_y + 1);
+ transition = g_new (gfloat *, self->radius_y + 1);
for (i = 0; i < self->radius_y + 1; i++)
{
- transition[i] = g_new (guchar, roi->width + 2 * self->radius_x);
- memset(transition[i], 0, roi->width + 2 * self->radius_x);
+ transition[i] = g_new (gfloat, roi->width + 2 * self->radius_x);
+ memset (transition[i], 0,
+ (roi->width + 2 * self->radius_x) * sizeof (gfloat));
transition[i] += self->radius_x;
}
- out = g_new (guchar, roi->width);
+ out = g_new (gfloat, roi->width);
- density = g_new (guchar *, 2 * self->radius_x + 1);
+ density = g_new (gfloat *, 2 * self->radius_x + 1);
density += self->radius_x;
- /* allocate density[][] */
+ /* allocate density[][] */
for (x = 0; x < (self->radius_x + 1); x++)
{
- density[ x] = g_new (guchar, 2 * self->radius_y + 1);
+ density[ x] = g_new (gfloat, 2 * self->radius_y + 1);
density[ x] += self->radius_y;
density[-x] = density[x];
}
@@ -473,8 +490,8 @@ gimp_operation_border_process (GeglOperation *operation,
/* compute density[][] */
for (x = 0; x < (self->radius_x + 1); x++)
{
- register gdouble tmpx, tmpy, dist;
- guchar a;
+ gdouble tmpx, tmpy, dist;
+ gfloat a;
if (x > 0)
tmpx = x - 0.5;
@@ -498,13 +515,13 @@ gimp_operation_border_process (GeglOperation *operation,
if (dist < 1.0)
{
if (self->feather)
- a = 255 * (1.0 - sqrt (dist));
+ a = 1.0 - sqrt (dist);
else
- a = 255;
+ a = 1.0;
}
else
{
- a = 0;
+ a = 0.0;
}
density[ x][ y] = a;
@@ -520,7 +537,16 @@ gimp_operation_border_process (GeglOperation *operation,
* 'self->edge_lock', initialize the first row to 'selected'. Refer
* to bug #350009.
*/
- memset (buf[0], self->edge_lock ? 255 : 0, roi->width);
+ if (self->edge_lock)
+ {
+ for (i = 0; i < roi->width; i++)
+ buf[0][i] = 1.0;
+ }
+ else
+ {
+ memset (buf[0], 0, roi->width * sizeof (gfloat));
+ }
+
gegl_buffer_get (input,
GEGL_RECTANGLE (roi->x, roi->y + 0,
roi->width, 1),
@@ -534,7 +560,7 @@ gimp_operation_border_process (GeglOperation *operation,
1.0, input_format, buf[2],
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
else
- memcpy (buf[2], buf[1], roi->width);
+ memcpy (buf[2], buf[1], roi->width * sizeof (gfloat));
compute_transition (transition[1], buf, roi->width, self->edge_lock);
@@ -583,14 +609,14 @@ gimp_operation_border_process (GeglOperation *operation,
{
if (self->edge_lock)
{
- memcpy (transition[self->radius_y], transition[self->radius_y - 1], roi->width);
+ memcpy (transition[self->radius_y], transition[self->radius_y - 1], roi->width * sizeof
(gfloat));
}
else
{
/* No edge lock, set everything 'below canvas' as seen
* from the algorithm as unselected.
*/
- memset (buf[2], 0, roi->width);
+ memset (buf[2], 0, roi->width * sizeof (gfloat));
compute_transition (transition[self->radius_y], buf, roi->width, self->edge_lock);
}
}
@@ -631,13 +657,13 @@ gimp_operation_border_process (GeglOperation *operation,
/* render scan line */
for (x = 0 ; x < roi->width; x++)
{
- guchar last_max;
+ gfloat last_max;
last_index--;
if (last_index >= 0)
{
- last_max = 0;
+ last_max = 0.0;
for (i = self->radius_x; i >= 0; i--)
if (max[x + i] <= self->radius_y && max[x + i] >= -self->radius_y &&
@@ -651,7 +677,7 @@ gimp_operation_border_process (GeglOperation *operation,
}
else
{
- last_max = 0;
+ last_max = 0.0;
for (i = self->radius_x; i >= -self->radius_x; i--)
if (max[x + i] <= self->radius_y && max[x + i] >= -self->radius_y &&
@@ -664,7 +690,7 @@ gimp_operation_border_process (GeglOperation *operation,
out[x] = last_max;
}
- if (last_max == 0)
+ if (last_max <= 0.0)
{
for (i = x + 1; i < roi->width; i++)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]