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;
|
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
|
/* this is a pretty stupid port of concolve_region() that only works
|
||||||
* on a linear source buffer
|
* on a linear source buffer
|
||||||
*/
|
*/
|
||||||
void gimp_gegl_convolve (GeglBuffer *src_buffer,
|
void gimp_gegl_convolve (GeglBuffer *src_buffer,
|
||||||
const GeglRectangle *src_rect,
|
const GeglRectangle *src_rect,
|
||||||
GeglBuffer *dest_buffer,
|
GeglBuffer *dest_buffer,
|
||||||
const GeglRectangle *dest_rect,
|
const GeglRectangle *dest_rect,
|
||||||
const gfloat *kernel,
|
const gfloat *kernel,
|
||||||
gint kernel_size,
|
gint kernel_size,
|
||||||
gdouble divisor,
|
gdouble divisor,
|
||||||
GimpConvolutionType mode,
|
GimpConvolutionType mode,
|
||||||
gboolean alpha_weighting);
|
gboolean alpha_weighting);
|
||||||
|
|
||||||
void gimp_gegl_dodgeburn (GeglBuffer *src_buffer,
|
void gimp_gegl_dodgeburn (GeglBuffer *src_buffer,
|
||||||
const GeglRectangle *src_rect,
|
const GeglRectangle *src_rect,
|
||||||
GeglBuffer *dest_buffer,
|
GeglBuffer *dest_buffer,
|
||||||
const GeglRectangle *dest_rect,
|
const GeglRectangle *dest_rect,
|
||||||
gdouble exposure,
|
gdouble exposure,
|
||||||
GimpDodgeBurnType type,
|
GimpDodgeBurnType type,
|
||||||
GimpTransferMode mode);
|
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__ */
|
#endif /* __GIMP_GEGL_LOOPS_H__ */
|
||||||
|
@ -23,13 +23,9 @@
|
|||||||
|
|
||||||
#include "paint-types.h"
|
#include "paint-types.h"
|
||||||
|
|
||||||
#include "base/pixel-region.h"
|
#include "gegl/gimp-gegl-loops.h"
|
||||||
|
|
||||||
#include "paint-funcs/paint-funcs.h"
|
|
||||||
|
|
||||||
#include "gegl/gimp-gegl-utils.h"
|
#include "gegl/gimp-gegl-utils.h"
|
||||||
|
|
||||||
#include "core/gimp.h"
|
|
||||||
#include "core/gimpbrush.h"
|
#include "core/gimpbrush.h"
|
||||||
#include "core/gimpdrawable.h"
|
#include "core/gimpdrawable.h"
|
||||||
#include "core/gimpdynamics.h"
|
#include "core/gimpdynamics.h"
|
||||||
@ -164,13 +160,12 @@ gimp_smudge_start (GimpPaintCore *paint_core,
|
|||||||
GimpPaintOptions *paint_options,
|
GimpPaintOptions *paint_options,
|
||||||
const GimpCoords *coords)
|
const GimpCoords *coords)
|
||||||
{
|
{
|
||||||
GimpSmudge *smudge = GIMP_SMUDGE (paint_core);
|
GimpSmudge *smudge = GIMP_SMUDGE (paint_core);
|
||||||
GeglBuffer *paint_buffer;
|
GeglBuffer *paint_buffer;
|
||||||
gint paint_buffer_x;
|
gint paint_buffer_x;
|
||||||
gint paint_buffer_y;
|
gint paint_buffer_y;
|
||||||
GimpTempBuf *accum_temp;
|
gint accum_size;
|
||||||
gint accum_size;
|
gint x, y;
|
||||||
gint x, y;
|
|
||||||
|
|
||||||
if (gimp_drawable_is_indexed (drawable))
|
if (gimp_drawable_is_indexed (drawable))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -185,10 +180,10 @@ gimp_smudge_start (GimpPaintCore *paint_core,
|
|||||||
gimp_smudge_accumulator_size (paint_options, &accum_size);
|
gimp_smudge_accumulator_size (paint_options, &accum_size);
|
||||||
|
|
||||||
/* Allocate the accumulation buffer */
|
/* Allocate the accumulation buffer */
|
||||||
accum_temp = gimp_temp_buf_new (accum_size, accum_size,
|
smudge->accum_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
|
||||||
gimp_drawable_get_format (drawable));
|
accum_size,
|
||||||
smudge->accum_buffer = gimp_temp_buf_create_buffer (accum_temp);
|
accum_size),
|
||||||
gimp_temp_buf_unref (accum_temp);
|
gimp_drawable_get_format (drawable));
|
||||||
|
|
||||||
/* adjust the x and y coordinates to the upper left corner of the
|
/* adjust the x and y coordinates to the upper left corner of the
|
||||||
* accumulator
|
* accumulator
|
||||||
@ -251,7 +246,8 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
|
|||||||
GeglBuffer *paint_buffer;
|
GeglBuffer *paint_buffer;
|
||||||
gint paint_buffer_x;
|
gint paint_buffer_x;
|
||||||
gint paint_buffer_y;
|
gint paint_buffer_y;
|
||||||
PixelRegion srcPR, tempPR;
|
gint paint_buffer_width;
|
||||||
|
gint paint_buffer_height;
|
||||||
gdouble fade_point;
|
gdouble fade_point;
|
||||||
gdouble opacity;
|
gdouble opacity;
|
||||||
gdouble rate;
|
gdouble rate;
|
||||||
@ -284,16 +280,12 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
|
|||||||
if (! paint_buffer)
|
if (! paint_buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
paint_buffer_width = gegl_buffer_get_width (paint_buffer);
|
||||||
|
paint_buffer_height = gegl_buffer_get_height (paint_buffer);
|
||||||
|
|
||||||
/* Get the unclipped acumulator coordinates */
|
/* Get the unclipped acumulator coordinates */
|
||||||
gimp_smudge_accumulator_coords (paint_core, coords, &x, &y);
|
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 */
|
/* Enable dynamic rate */
|
||||||
rate_output = gimp_dynamics_get_output (dynamics,
|
rate_output = gimp_dynamics_get_output (dynamics,
|
||||||
GIMP_DYNAMICS_OUTPUT_RATE);
|
GIMP_DYNAMICS_OUTPUT_RATE);
|
||||||
@ -305,14 +297,6 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
|
|||||||
|
|
||||||
rate = (options->rate / 100.0) * dynamic_rate;
|
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.
|
/* Smudge uses the buffer Accum.
|
||||||
* For each successive painthit Accum is built like this
|
* For each successive painthit Accum is built like this
|
||||||
* Accum = rate*Accum + (1-rate)*I.
|
* Accum = rate*Accum + (1-rate)*I.
|
||||||
@ -321,13 +305,28 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
|
|||||||
* (Accum,1) (if no alpha),
|
* (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_buffer_copy (smudge->accum_buffer,
|
||||||
GEGL_RECTANGLE (paint_buffer_x - x,
|
GEGL_RECTANGLE (paint_buffer_x - x,
|
||||||
paint_buffer_y - y,
|
paint_buffer_y - y,
|
||||||
gegl_buffer_get_width (paint_buffer),
|
paint_buffer_width,
|
||||||
gegl_buffer_get_height (paint_buffer)),
|
paint_buffer_height),
|
||||||
paint_buffer,
|
paint_buffer,
|
||||||
GEGL_RECTANGLE (0, 0, 0, 0));
|
GEGL_RECTANGLE (0, 0, 0, 0));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user