app: add gimp_gegl_smudge_blend(), a brute-force port of blend_region()
and use it in GimpSmudge. This only to get functionality ported and the API done, and not the final state.
This commit is contained in:
@ -307,3 +307,102 @@ gimp_gegl_dodgeburn (GeglBuffer *src_buffer,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* blend_pixels patched 8-24-05 to fix bug #163721. Note that this change
|
||||
* causes the function to treat src1 and src2 asymmetrically. This gives the
|
||||
* right behavior for the smudge tool, which is the only user of this function
|
||||
* at the time of patching. If you want to use the function for something
|
||||
* else, caveat emptor.
|
||||
*/
|
||||
void
|
||||
gimp_gegl_smudge_blend (GeglBuffer *top_buffer,
|
||||
const GeglRectangle *top_rect,
|
||||
GeglBuffer *bottom_buffer,
|
||||
const GeglRectangle *bottom_rect,
|
||||
GeglBuffer *dest_buffer,
|
||||
const GeglRectangle *dest_rect,
|
||||
guchar blend)
|
||||
{
|
||||
GeglBufferIterator *iter;
|
||||
const Babl *top_format;
|
||||
const Babl *bottom_format;
|
||||
const Babl *dest_format;
|
||||
gint top_bpp;
|
||||
gint bottom_bpp;
|
||||
gint dest_bpp;
|
||||
|
||||
top_format = gegl_buffer_get_format (top_buffer);
|
||||
bottom_format = gegl_buffer_get_format (bottom_buffer);
|
||||
dest_format = gegl_buffer_get_format (dest_buffer);
|
||||
|
||||
top_bpp = babl_format_get_bytes_per_pixel (top_format);
|
||||
bottom_bpp = babl_format_get_bytes_per_pixel (bottom_format);
|
||||
dest_bpp = babl_format_get_bytes_per_pixel (dest_format);
|
||||
|
||||
iter = gegl_buffer_iterator_new (top_buffer, top_rect, 0, NULL,
|
||||
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
|
||||
|
||||
gegl_buffer_iterator_add (iter, bottom_buffer, bottom_rect, 0, NULL,
|
||||
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
|
||||
|
||||
gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0, NULL,
|
||||
GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
|
||||
|
||||
while (gegl_buffer_iterator_next (iter))
|
||||
{
|
||||
const guchar *top = iter->data[0];
|
||||
const guchar *bottom = iter->data[1];
|
||||
guchar *dest = iter->data[2];
|
||||
|
||||
if (babl_format_has_alpha (top_format))
|
||||
{
|
||||
const guint blend1 = 255 - blend;
|
||||
const guint blend2 = blend + 1;
|
||||
const guint c = top_bpp - 1;
|
||||
|
||||
while (iter->length--)
|
||||
{
|
||||
const gint a1 = blend1 * bottom[c];
|
||||
const gint a2 = blend2 * top[c];
|
||||
const gint a = a1 + a2;
|
||||
guint b;
|
||||
|
||||
if (!a)
|
||||
{
|
||||
for (b = 0; b < top_bpp; b++)
|
||||
dest[b] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (b = 0; b < c; b++)
|
||||
dest[b] =
|
||||
bottom[b] + (bottom[b] * a1 + top[b] * a2 - a * bottom[b]) / a;
|
||||
|
||||
dest[c] = a >> 8;
|
||||
}
|
||||
|
||||
top += top_bpp;
|
||||
bottom += bottom_bpp;
|
||||
dest += dest_bpp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const guchar blend1 = 255 - blend;
|
||||
|
||||
while (iter->length--)
|
||||
{
|
||||
guint b;
|
||||
|
||||
for (b = 0; b < top_bpp; b++)
|
||||
dest[b] =
|
||||
bottom[b] + (bottom[b] * blend1 + top[b] * blend - bottom[b] * 255) / 255;
|
||||
|
||||
top += top_bpp;
|
||||
bottom += bottom_bpp;
|
||||
dest += dest_bpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,23 +25,31 @@
|
||||
/* this is a pretty stupid port of concolve_region() that only works
|
||||
* on a linear source buffer
|
||||
*/
|
||||
void gimp_gegl_convolve (GeglBuffer *src_buffer,
|
||||
const GeglRectangle *src_rect,
|
||||
GeglBuffer *dest_buffer,
|
||||
const GeglRectangle *dest_rect,
|
||||
const gfloat *kernel,
|
||||
gint kernel_size,
|
||||
gdouble divisor,
|
||||
GimpConvolutionType mode,
|
||||
gboolean alpha_weighting);
|
||||
void gimp_gegl_convolve (GeglBuffer *src_buffer,
|
||||
const GeglRectangle *src_rect,
|
||||
GeglBuffer *dest_buffer,
|
||||
const GeglRectangle *dest_rect,
|
||||
const gfloat *kernel,
|
||||
gint kernel_size,
|
||||
gdouble divisor,
|
||||
GimpConvolutionType mode,
|
||||
gboolean alpha_weighting);
|
||||
|
||||
void gimp_gegl_dodgeburn (GeglBuffer *src_buffer,
|
||||
const GeglRectangle *src_rect,
|
||||
GeglBuffer *dest_buffer,
|
||||
const GeglRectangle *dest_rect,
|
||||
gdouble exposure,
|
||||
GimpDodgeBurnType type,
|
||||
GimpTransferMode mode);
|
||||
void gimp_gegl_dodgeburn (GeglBuffer *src_buffer,
|
||||
const GeglRectangle *src_rect,
|
||||
GeglBuffer *dest_buffer,
|
||||
const GeglRectangle *dest_rect,
|
||||
gdouble exposure,
|
||||
GimpDodgeBurnType type,
|
||||
GimpTransferMode mode);
|
||||
|
||||
void gimp_gegl_smudge_blend (GeglBuffer *top_buffer,
|
||||
const GeglRectangle *top_rect,
|
||||
GeglBuffer *bottom_buffer,
|
||||
const GeglRectangle *bottom_rect,
|
||||
GeglBuffer *dest_buffer,
|
||||
const GeglRectangle *dest_rect,
|
||||
guchar blend);
|
||||
|
||||
|
||||
#endif /* __GIMP_GEGL_LOOPS_H__ */
|
||||
|
@ -23,13 +23,9 @@
|
||||
|
||||
#include "paint-types.h"
|
||||
|
||||
#include "base/pixel-region.h"
|
||||
|
||||
#include "paint-funcs/paint-funcs.h"
|
||||
|
||||
#include "gegl/gimp-gegl-loops.h"
|
||||
#include "gegl/gimp-gegl-utils.h"
|
||||
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimpbrush.h"
|
||||
#include "core/gimpdrawable.h"
|
||||
#include "core/gimpdynamics.h"
|
||||
@ -164,13 +160,12 @@ gimp_smudge_start (GimpPaintCore *paint_core,
|
||||
GimpPaintOptions *paint_options,
|
||||
const GimpCoords *coords)
|
||||
{
|
||||
GimpSmudge *smudge = GIMP_SMUDGE (paint_core);
|
||||
GeglBuffer *paint_buffer;
|
||||
gint paint_buffer_x;
|
||||
gint paint_buffer_y;
|
||||
GimpTempBuf *accum_temp;
|
||||
gint accum_size;
|
||||
gint x, y;
|
||||
GimpSmudge *smudge = GIMP_SMUDGE (paint_core);
|
||||
GeglBuffer *paint_buffer;
|
||||
gint paint_buffer_x;
|
||||
gint paint_buffer_y;
|
||||
gint accum_size;
|
||||
gint x, y;
|
||||
|
||||
if (gimp_drawable_is_indexed (drawable))
|
||||
return FALSE;
|
||||
@ -185,10 +180,10 @@ gimp_smudge_start (GimpPaintCore *paint_core,
|
||||
gimp_smudge_accumulator_size (paint_options, &accum_size);
|
||||
|
||||
/* Allocate the accumulation buffer */
|
||||
accum_temp = gimp_temp_buf_new (accum_size, accum_size,
|
||||
gimp_drawable_get_format (drawable));
|
||||
smudge->accum_buffer = gimp_temp_buf_create_buffer (accum_temp);
|
||||
gimp_temp_buf_unref (accum_temp);
|
||||
smudge->accum_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
|
||||
accum_size,
|
||||
accum_size),
|
||||
gimp_drawable_get_format (drawable));
|
||||
|
||||
/* adjust the x and y coordinates to the upper left corner of the
|
||||
* accumulator
|
||||
@ -251,7 +246,8 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
|
||||
GeglBuffer *paint_buffer;
|
||||
gint paint_buffer_x;
|
||||
gint paint_buffer_y;
|
||||
PixelRegion srcPR, tempPR;
|
||||
gint paint_buffer_width;
|
||||
gint paint_buffer_height;
|
||||
gdouble fade_point;
|
||||
gdouble opacity;
|
||||
gdouble rate;
|
||||
@ -284,16 +280,12 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
|
||||
if (! paint_buffer)
|
||||
return;
|
||||
|
||||
paint_buffer_width = gegl_buffer_get_width (paint_buffer);
|
||||
paint_buffer_height = gegl_buffer_get_height (paint_buffer);
|
||||
|
||||
/* Get the unclipped acumulator coordinates */
|
||||
gimp_smudge_accumulator_coords (paint_core, coords, &x, &y);
|
||||
|
||||
/* srcPR will be the pixels under the current painthit from the drawable */
|
||||
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
||||
paint_buffer_x,
|
||||
paint_buffer_y,
|
||||
gegl_buffer_get_width (paint_buffer),
|
||||
gegl_buffer_get_height (paint_buffer), FALSE);
|
||||
|
||||
/* Enable dynamic rate */
|
||||
rate_output = gimp_dynamics_get_output (dynamics,
|
||||
GIMP_DYNAMICS_OUTPUT_RATE);
|
||||
@ -305,14 +297,6 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
|
||||
|
||||
rate = (options->rate / 100.0) * dynamic_rate;
|
||||
|
||||
/* The tempPR will be the built up buffer (for smudge) */
|
||||
pixel_region_init_temp_buf (&tempPR,
|
||||
gimp_gegl_buffer_get_temp_buf (smudge->accum_buffer),
|
||||
paint_buffer_x - x,
|
||||
paint_buffer_y - y,
|
||||
gegl_buffer_get_width (paint_buffer),
|
||||
gegl_buffer_get_height (paint_buffer));
|
||||
|
||||
/* Smudge uses the buffer Accum.
|
||||
* For each successive painthit Accum is built like this
|
||||
* Accum = rate*Accum + (1-rate)*I.
|
||||
@ -321,13 +305,28 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
|
||||
* (Accum,1) (if no alpha),
|
||||
*/
|
||||
|
||||
blend_region (&srcPR, &tempPR, &tempPR, ROUND (rate * 255.0));
|
||||
gimp_gegl_smudge_blend (smudge->accum_buffer,
|
||||
GEGL_RECTANGLE (paint_buffer_x - x,
|
||||
paint_buffer_y - y,
|
||||
paint_buffer_width,
|
||||
paint_buffer_height),
|
||||
gimp_drawable_get_buffer (drawable),
|
||||
GEGL_RECTANGLE (paint_buffer_x,
|
||||
paint_buffer_y,
|
||||
paint_buffer_width,
|
||||
paint_buffer_height),
|
||||
smudge->accum_buffer,
|
||||
GEGL_RECTANGLE (paint_buffer_x - x,
|
||||
paint_buffer_y - y,
|
||||
paint_buffer_width,
|
||||
paint_buffer_height),
|
||||
ROUND (rate * 255.0));
|
||||
|
||||
gegl_buffer_copy (smudge->accum_buffer,
|
||||
GEGL_RECTANGLE (paint_buffer_x - x,
|
||||
paint_buffer_y - y,
|
||||
gegl_buffer_get_width (paint_buffer),
|
||||
gegl_buffer_get_height (paint_buffer)),
|
||||
paint_buffer_width,
|
||||
paint_buffer_height),
|
||||
paint_buffer,
|
||||
GEGL_RECTANGLE (0, 0, 0, 0));
|
||||
|
||||
|
Reference in New Issue
Block a user