mirror of https://github.com/GNOME/gimp.git
app: port the mask shrink and grow operations from u8 to float
This commit is contained in:
parent
c64cb2dcde
commit
7ac385caec
|
@ -166,8 +166,8 @@ gimp_operation_grow_set_property (GObject *object,
|
||||||
static void
|
static void
|
||||||
gimp_operation_grow_prepare (GeglOperation *operation)
|
gimp_operation_grow_prepare (GeglOperation *operation)
|
||||||
{
|
{
|
||||||
gegl_operation_set_format (operation, "input", babl_format ("Y u8"));
|
gegl_operation_set_format (operation, "input", babl_format ("Y float"));
|
||||||
gegl_operation_set_format (operation, "output", babl_format ("Y u8"));
|
gegl_operation_set_format (operation, "output", babl_format ("Y float"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GeglRectangle
|
static GeglRectangle
|
||||||
|
@ -209,11 +209,11 @@ compute_border (gint16 *circ,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
rotate_pointers (guchar **p,
|
rotate_pointers (gfloat **p,
|
||||||
guint32 n)
|
guint32 n)
|
||||||
{
|
{
|
||||||
guint32 i;
|
guint32 i;
|
||||||
guchar *tmp;
|
gfloat *tmp;
|
||||||
|
|
||||||
tmp = p[0];
|
tmp = p[0];
|
||||||
|
|
||||||
|
@ -230,27 +230,29 @@ gimp_operation_grow_process (GeglOperation *operation,
|
||||||
const GeglRectangle *roi,
|
const GeglRectangle *roi,
|
||||||
gint level)
|
gint level)
|
||||||
{
|
{
|
||||||
/* Any bugs in this fuction are probably also in thin_region Blame
|
/* Any bugs in this fuction are probably also in thin_region.
|
||||||
* all bugs in this function on jaycox@gimp.org
|
* Blame all bugs in this function on jaycox@gimp.org
|
||||||
*/
|
*/
|
||||||
GimpOperationGrow *self = GIMP_OPERATION_GROW (operation);
|
GimpOperationGrow *self = GIMP_OPERATION_GROW (operation);
|
||||||
const Babl *input_format = babl_format ("Y u8");
|
const Babl *input_format = babl_format ("Y float");
|
||||||
const Babl *output_format = babl_format ("Y u8");
|
const Babl *output_format = babl_format ("Y float");
|
||||||
gint32 i, j, x, y;
|
gint32 i, j, x, y;
|
||||||
guchar **buf; /* caches the region's pixel data */
|
gfloat **buf; /* caches the region's pixel data */
|
||||||
guchar *out; /* holds the new scan line we are computing */
|
gfloat *out; /* holds the new scan line we are computing */
|
||||||
guchar **max; /* caches the largest values for each column */
|
gfloat **max; /* caches the largest values for each column */
|
||||||
gint16 *circ; /* holds the y coords of the filter's mask */
|
gint16 *circ; /* holds the y coords of the filter's mask */
|
||||||
gint16 last_max, last_index;
|
gfloat last_max;
|
||||||
guchar *buffer;
|
gint16 last_index;
|
||||||
|
gfloat *buffer;
|
||||||
|
|
||||||
max = g_new (guchar *, roi->width + 2 * self->radius_x);
|
max = g_new (gfloat *, roi->width + 2 * self->radius_x);
|
||||||
buf = g_new (guchar *, self->radius_y + 1);
|
buf = g_new (gfloat *, self->radius_y + 1);
|
||||||
|
|
||||||
for (i = 0; i < self->radius_y + 1; i++)
|
for (i = 0; i < self->radius_y + 1; i++)
|
||||||
buf[i] = g_new (guchar, roi->width);
|
buf[i] = g_new (gfloat, roi->width);
|
||||||
|
|
||||||
buffer = g_new (guchar, (roi->width + 2 * self->radius_x) * (self->radius_y + 1));
|
buffer = g_new (gfloat,
|
||||||
|
(roi->width + 2 * self->radius_x) * (self->radius_y + 1));
|
||||||
|
|
||||||
for (i = 0; i < roi->width + 2 * self->radius_x; i++)
|
for (i = 0; i < roi->width + 2 * self->radius_x; i++)
|
||||||
{
|
{
|
||||||
|
@ -262,7 +264,7 @@ gimp_operation_grow_process (GeglOperation *operation,
|
||||||
max[i] = &buffer[(self->radius_y + 1) * (roi->width + self->radius_x - 1)];
|
max[i] = &buffer[(self->radius_y + 1) * (roi->width + self->radius_x - 1)];
|
||||||
|
|
||||||
for (j = 0; j < self->radius_x + 1; j++)
|
for (j = 0; j < self->radius_x + 1; j++)
|
||||||
max[i][j] = 0;
|
max[i][j] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* offset the max pointer by self->radius_x so the range of the
|
/* offset the max pointer by self->radius_x so the range of the
|
||||||
|
@ -270,7 +272,7 @@ gimp_operation_grow_process (GeglOperation *operation,
|
||||||
*/
|
*/
|
||||||
max += self->radius_x;
|
max += self->radius_x;
|
||||||
|
|
||||||
out = g_new (guchar, roi->width);
|
out = g_new (gfloat, roi->width);
|
||||||
|
|
||||||
circ = g_new (gint16, 2 * self->radius_x + 1);
|
circ = g_new (gint16, 2 * self->radius_x + 1);
|
||||||
compute_border (circ, self->radius_x, self->radius_y);
|
compute_border (circ, self->radius_x, self->radius_y);
|
||||||
|
@ -280,7 +282,7 @@ gimp_operation_grow_process (GeglOperation *operation,
|
||||||
*/
|
*/
|
||||||
circ += self->radius_x;
|
circ += self->radius_x;
|
||||||
|
|
||||||
memset (buf[0], 0, roi->width);
|
memset (buf[0], 0, roi->width * sizeof (gfloat));
|
||||||
|
|
||||||
for (i = 0; i < self->radius_y && i < roi->height; i++) /* load top of image */
|
for (i = 0; i < self->radius_y && i < roi->height; i++) /* load top of image */
|
||||||
gegl_buffer_get (input,
|
gegl_buffer_get (input,
|
||||||
|
@ -291,7 +293,7 @@ gimp_operation_grow_process (GeglOperation *operation,
|
||||||
|
|
||||||
for (x = 0; x < roi->width; x++) /* set up max for top of image */
|
for (x = 0; x < roi->width; x++) /* set up max for top of image */
|
||||||
{
|
{
|
||||||
max[x][0] = 0; /* buf[0][x] is always 0 */
|
max[x][0] = 0.0; /* buf[0][x] is always 0 */
|
||||||
max[x][1] = buf[1][x]; /* MAX (buf[1][x], max[x][0]) always = buf[1][x]*/
|
max[x][1] = buf[1][x]; /* MAX (buf[1][x], max[x][0]) always = buf[1][x]*/
|
||||||
|
|
||||||
for (j = 2; j < self->radius_y + 1; j++)
|
for (j = 2; j < self->radius_y + 1; j++)
|
||||||
|
@ -309,7 +311,7 @@ gimp_operation_grow_process (GeglOperation *operation,
|
||||||
1.0, input_format, buf[self->radius_y],
|
1.0, input_format, buf[self->radius_y],
|
||||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||||
else
|
else
|
||||||
memset (buf[self->radius_y], 0, roi->width);
|
memset (buf[self->radius_y], 0, roi->width * sizeof (gfloat));
|
||||||
|
|
||||||
for (x = 0; x < roi->width; x++) /* update max array */
|
for (x = 0; x < roi->width; x++) /* update max array */
|
||||||
{
|
{
|
||||||
|
@ -328,13 +330,13 @@ gimp_operation_grow_process (GeglOperation *operation,
|
||||||
|
|
||||||
if (last_index >= 0)
|
if (last_index >= 0)
|
||||||
{
|
{
|
||||||
if (last_max == 255)
|
if (last_max >= 1.0)
|
||||||
{
|
{
|
||||||
out[x] = 255;
|
out[x] = 1.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
last_max = 0;
|
last_max = 0.0;
|
||||||
|
|
||||||
for (i = self->radius_x; i >= 0; i--)
|
for (i = self->radius_x; i >= 0; i--)
|
||||||
if (last_max < max[x + i][circ[i]])
|
if (last_max < max[x + i][circ[i]])
|
||||||
|
|
|
@ -183,8 +183,8 @@ gimp_operation_shrink_set_property (GObject *object,
|
||||||
static void
|
static void
|
||||||
gimp_operation_shrink_prepare (GeglOperation *operation)
|
gimp_operation_shrink_prepare (GeglOperation *operation)
|
||||||
{
|
{
|
||||||
gegl_operation_set_format (operation, "input", babl_format ("Y u8"));
|
gegl_operation_set_format (operation, "input", babl_format ("Y float"));
|
||||||
gegl_operation_set_format (operation, "output", babl_format ("Y u8"));
|
gegl_operation_set_format (operation, "output", babl_format ("Y float"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GeglRectangle
|
static GeglRectangle
|
||||||
|
@ -226,11 +226,11 @@ compute_border (gint16 *circ,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
rotate_pointers (guchar **p,
|
rotate_pointers (gfloat **p,
|
||||||
guint32 n)
|
guint32 n)
|
||||||
{
|
{
|
||||||
guint32 i;
|
guint32 i;
|
||||||
guchar *tmp;
|
gfloat *tmp;
|
||||||
|
|
||||||
tmp = p[0];
|
tmp = p[0];
|
||||||
|
|
||||||
|
@ -247,38 +247,44 @@ gimp_operation_shrink_process (GeglOperation *operation,
|
||||||
const GeglRectangle *roi,
|
const GeglRectangle *roi,
|
||||||
gint level)
|
gint level)
|
||||||
{
|
{
|
||||||
/* pretty much the same as fatten_region only different blame all
|
/* Pretty much the same as fatten_region only different.
|
||||||
* bugs in this function on jaycox@gimp.org
|
* Blame all bugs in this function on jaycox@gimp.org
|
||||||
*
|
*
|
||||||
* If edge_lock is true we assume that pixels outside the region we
|
* If edge_lock is true we assume that pixels outside the region we
|
||||||
* are passed are identical to the edge pixels. If edge_lock is
|
* are passed are identical to the edge pixels. If edge_lock is
|
||||||
* false, we assume that pixels outside the region are 0
|
* false, we assume that pixels outside the region are 0
|
||||||
*/
|
*/
|
||||||
GimpOperationShrink *self = GIMP_OPERATION_SHRINK (operation);
|
GimpOperationShrink *self = GIMP_OPERATION_SHRINK (operation);
|
||||||
const Babl *input_format = babl_format ("Y u8");
|
const Babl *input_format = babl_format ("Y float");
|
||||||
const Babl *output_format = babl_format ("Y u8");
|
const Babl *output_format = babl_format ("Y float");
|
||||||
gint32 i, j, x, y;
|
gint32 i, j, x, y;
|
||||||
guchar **buf; /* caches the the region's pixels */
|
gfloat **buf; /* caches the the region's pixels */
|
||||||
guchar *out; /* holds the new scan line we are computing */
|
gfloat *out; /* holds the new scan line we are computing */
|
||||||
guchar **max; /* caches the smallest values for each column */
|
gfloat **max; /* caches the smallest values for each column */
|
||||||
gint16 *circ; /* holds the y coords of the filter's mask */
|
gint16 *circ; /* holds the y coords of the filter's mask */
|
||||||
gint16 last_max, last_index;
|
gfloat last_max;
|
||||||
guchar *buffer;
|
gint16 last_index;
|
||||||
|
gfloat *buffer;
|
||||||
gint buffer_size;
|
gint buffer_size;
|
||||||
|
|
||||||
max = g_new (guchar *, roi->width + 2 * self->radius_x);
|
max = g_new (gfloat *, roi->width + 2 * self->radius_x);
|
||||||
buf = g_new (guchar *, self->radius_y + 1);
|
buf = g_new (gfloat *, self->radius_y + 1);
|
||||||
|
|
||||||
for (i = 0; i < self->radius_y + 1; i++)
|
for (i = 0; i < self->radius_y + 1; i++)
|
||||||
buf[i] = g_new (guchar, roi->width);
|
buf[i] = g_new (gfloat, roi->width);
|
||||||
|
|
||||||
buffer_size = (roi->width+ 2 * self->radius_x + 1) * (self->radius_y + 1);
|
buffer_size = (roi->width+ 2 * self->radius_x + 1) * (self->radius_y + 1);
|
||||||
buffer = g_new (guchar, buffer_size);
|
buffer = g_new (gfloat, buffer_size);
|
||||||
|
|
||||||
if (self->edge_lock)
|
if (self->edge_lock)
|
||||||
memset(buffer, 255, buffer_size);
|
{
|
||||||
|
for (i = 0; i < buffer_size; i++)
|
||||||
|
buffer[i] = 1.0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
memset(buffer, 0, buffer_size);
|
{
|
||||||
|
memset (buffer, 0, buffer_size * sizeof (gfloat));
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < roi->width + 2 * self->radius_x; i++)
|
for (i = 0; i < roi->width + 2 * self->radius_x; i++)
|
||||||
{
|
{
|
||||||
|
@ -304,14 +310,14 @@ gimp_operation_shrink_process (GeglOperation *operation,
|
||||||
|
|
||||||
if (! self->edge_lock)
|
if (! self->edge_lock)
|
||||||
for (j = 0 ; j < self->radius_x + 1; j++)
|
for (j = 0 ; j < self->radius_x + 1; j++)
|
||||||
max[0][j] = 0;
|
max[0][j] = 0.0;
|
||||||
|
|
||||||
/* offset the max pointer by self->radius_x so the range of the
|
/* offset the max pointer by self->radius_x so the range of the
|
||||||
* array is [-self->radius_x] to [roi->width + self->radius_x]
|
* array is [-self->radius_x] to [roi->width + self->radius_x]
|
||||||
*/
|
*/
|
||||||
max += self->radius_x;
|
max += self->radius_x;
|
||||||
|
|
||||||
out = g_new (guchar, roi->width);
|
out = g_new (gfloat, roi->width);
|
||||||
|
|
||||||
circ = g_new (gint16, 2 * self->radius_x + 1);
|
circ = g_new (gint16, 2 * self->radius_x + 1);
|
||||||
compute_border (circ, self->radius_x, self->radius_y);
|
compute_border (circ, self->radius_x, self->radius_y);
|
||||||
|
@ -329,10 +335,9 @@ gimp_operation_shrink_process (GeglOperation *operation,
|
||||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
if (self->edge_lock)
|
if (self->edge_lock)
|
||||||
memcpy (buf[0], buf[1], roi->width);
|
memcpy (buf[0], buf[1], roi->width * sizeof (gfloat));
|
||||||
else
|
else
|
||||||
memset (buf[0], 0, roi->width);
|
memset (buf[0], 0, roi->width * sizeof (gfloat));
|
||||||
|
|
||||||
|
|
||||||
for (x = 0; x < roi->width; x++) /* set up max for top of image */
|
for (x = 0; x < roi->width; x++) /* set up max for top of image */
|
||||||
{
|
{
|
||||||
|
@ -352,10 +357,12 @@ gimp_operation_shrink_process (GeglOperation *operation,
|
||||||
roi->width, 1),
|
roi->width, 1),
|
||||||
1.0, input_format, buf[self->radius_y],
|
1.0, input_format, buf[self->radius_y],
|
||||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
else if (self->edge_lock)
|
else if (self->edge_lock)
|
||||||
memcpy (buf[self->radius_y], buf[self->radius_y - 1], roi->width);
|
memcpy (buf[self->radius_y], buf[self->radius_y - 1],
|
||||||
|
roi->width * sizeof (gfloat));
|
||||||
else
|
else
|
||||||
memset (buf[self->radius_y], 0, roi->width);
|
memset (buf[self->radius_y], 0, roi->width * sizeof (gfloat));
|
||||||
|
|
||||||
for (x = 0 ; x < roi->width; x++) /* update max array */
|
for (x = 0 ; x < roi->width; x++) /* update max array */
|
||||||
{
|
{
|
||||||
|
@ -374,13 +381,13 @@ gimp_operation_shrink_process (GeglOperation *operation,
|
||||||
|
|
||||||
if (last_index >= 0)
|
if (last_index >= 0)
|
||||||
{
|
{
|
||||||
if (last_max == 0)
|
if (last_max <= 0.0)
|
||||||
{
|
{
|
||||||
out[x] = 0;
|
out[x] = 0.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
last_max = 255;
|
last_max = 1.0;
|
||||||
|
|
||||||
for (i = self->radius_x; i >= 0; i--)
|
for (i = self->radius_x; i >= 0; i--)
|
||||||
if (last_max > max[x + i][circ[i]])
|
if (last_max > max[x + i][circ[i]])
|
||||||
|
|
Loading…
Reference in New Issue