app: fix gradient dithering
In gimp:gradient, fix dithering to correspond to how we actually round float values to 8-bit. In particular, this avoids introducing noise when a component is fixed at 0 or 1 along a segment.
This commit is contained in:
@ -158,6 +158,10 @@ static void gradient_put_pixel (gint
|
|||||||
GimpRGB *color,
|
GimpRGB *color,
|
||||||
gpointer put_pixel_data);
|
gpointer put_pixel_data);
|
||||||
|
|
||||||
|
static void gradient_dither_pixel (GimpRGB *color,
|
||||||
|
GRand *dither_rand,
|
||||||
|
gfloat *dest);
|
||||||
|
|
||||||
static gboolean gimp_operation_gradient_process (GeglOperation *operation,
|
static gboolean gimp_operation_gradient_process (GeglOperation *operation,
|
||||||
GeglBuffer *input,
|
GeglBuffer *input,
|
||||||
GeglBuffer *output,
|
GeglBuffer *output,
|
||||||
@ -985,22 +989,9 @@ gradient_put_pixel (gint x,
|
|||||||
|
|
||||||
if (ppd->dither_rand)
|
if (ppd->dither_rand)
|
||||||
{
|
{
|
||||||
gfloat r, g, b, a;
|
gradient_dither_pixel (color, ppd->dither_rand, dest);
|
||||||
gint i = g_rand_int (ppd->dither_rand);
|
|
||||||
|
|
||||||
r = color->r + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8;
|
dest += 4;
|
||||||
g = color->g + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8;
|
|
||||||
b = color->b + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8;
|
|
||||||
|
|
||||||
if (color->a > 0.0 && color->a < 1.0)
|
|
||||||
a = color->a + (gdouble) (i & 0xff) / 256.0 / 256.0;
|
|
||||||
else
|
|
||||||
a = color->a;
|
|
||||||
|
|
||||||
*dest++ = MAX (r, 0.0);
|
|
||||||
*dest++ = MAX (g, 0.0);
|
|
||||||
*dest++ = MAX (b, 0.0);
|
|
||||||
*dest++ = MAX (a, 0.0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1011,6 +1002,31 @@ gradient_put_pixel (gint x,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gradient_dither_pixel (GimpRGB *color,
|
||||||
|
GRand *dither_rand,
|
||||||
|
gfloat *dest)
|
||||||
|
{
|
||||||
|
gfloat r, g, b, a;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
i = g_rand_int (dither_rand);
|
||||||
|
|
||||||
|
r = color->r + (gdouble) (i & 0xff) / 256.0 / 256.0 - 0.5 / 256.0; i >>= 8;
|
||||||
|
g = color->g + (gdouble) (i & 0xff) / 256.0 / 256.0 - 0.5 / 256.0; i >>= 8;
|
||||||
|
b = color->b + (gdouble) (i & 0xff) / 256.0 / 256.0 - 0.5 / 256.0; i >>= 8;
|
||||||
|
|
||||||
|
if (color->a > 0.0 && color->a < 1.0)
|
||||||
|
a = color->a + (gdouble) (i & 0xff) / 256.0 / 256.0 - 0.5 / 256.0;
|
||||||
|
else
|
||||||
|
a = color->a;
|
||||||
|
|
||||||
|
*dest++ = CLAMP (r, 0.0, 1.0);
|
||||||
|
*dest++ = CLAMP (g, 0.0, 1.0);
|
||||||
|
*dest++ = CLAMP (b, 0.0, 1.0);
|
||||||
|
*dest++ = CLAMP (a, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gimp_operation_gradient_process (GeglOperation *operation,
|
gimp_operation_gradient_process (GeglOperation *operation,
|
||||||
GeglBuffer *input,
|
GeglBuffer *input,
|
||||||
@ -1138,24 +1154,11 @@ gimp_operation_gradient_process (GeglOperation *operation,
|
|||||||
for (x = roi->x; x < endx; x++)
|
for (x = roi->x; x < endx; x++)
|
||||||
{
|
{
|
||||||
GimpRGB color = { 0.0, 0.0, 0.0, 1.0 };
|
GimpRGB color = { 0.0, 0.0, 0.0, 1.0 };
|
||||||
gfloat r, g, b, a;
|
|
||||||
gint i = g_rand_int (dither_rand);
|
|
||||||
|
|
||||||
gradient_render_pixel (x, y, &color, &rbd);
|
gradient_render_pixel (x, y, &color, &rbd);
|
||||||
|
gradient_dither_pixel (&color, dither_rand, dest);
|
||||||
|
|
||||||
r = color.r + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8;
|
dest += 4;
|
||||||
g = color.g + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8;
|
|
||||||
b = color.b + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8;
|
|
||||||
|
|
||||||
if (color.a > 0.0 && color.a < 1.0)
|
|
||||||
a = color.a + (gdouble) (i & 0xff) / 256.0 / 256.0;
|
|
||||||
else
|
|
||||||
a = color.a;
|
|
||||||
|
|
||||||
*dest++ = MAX (r, 0.0);
|
|
||||||
*dest++ = MAX (g, 0.0);
|
|
||||||
*dest++ = MAX (b, 0.0);
|
|
||||||
*dest++ = MAX (a, 0.0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user