1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
#include <glib-object.h>
23
#include "paint-types.h"
25
#include "base/pixel-region.h"
26
#include "base/temp-buf.h"
28
#include "paint-funcs/paint-funcs.h"
30
#include "core/gimp.h"
31
#include "core/gimpbrush.h"
32
#include "core/gimpdrawable.h"
33
#include "core/gimpimage.h"
34
#include "core/gimppickable.h"
36
#include "gimpconvolve.h"
37
#include "gimpconvolveoptions.h"
39
#include "gimp-intl.h"
43
#define MIN_BLUR 64 /* (8/9 original pixel) */
44
#define MAX_BLUR 0.25 /* (1/33 original pixel) */
45
#define MIN_SHARPEN -512
46
#define MAX_SHARPEN -64
48
/* Different clip relationships between a blur-blob and edges:
53
CONVOLVE_NCLIP, /* Left or top edge */
54
CONVOLVE_NOT_CLIPPED, /* No edges */
55
CONVOLVE_PCLIP /* Right or bottom edge */
59
static void gimp_convolve_class_init (GimpConvolveClass *klass);
60
static void gimp_convolve_init (GimpConvolve *convolve);
62
static void gimp_convolve_paint (GimpPaintCore *paint_core,
63
GimpDrawable *drawable,
64
GimpPaintOptions *paint_options,
65
GimpPaintState paint_state,
67
static void gimp_convolve_motion (GimpPaintCore *paint_core,
68
GimpDrawable *drawable,
69
GimpPaintOptions *paint_options);
71
static void gimp_convolve_calculate_matrix (GimpConvolveType type,
73
static void gimp_convolve_copy_matrix (const gfloat *src,
76
static gdouble gimp_convolve_sum_matrix (const gfloat *matrix,
80
static gint matrix_size;
81
static gdouble matrix_divisor;
83
static gfloat matrix[25] =
92
static gfloat blur_matrix[25] =
101
static gfloat sharpen_matrix[25] =
105
0, 1, MIN_SHARPEN, 1, 0,
111
static GimpBrushCoreClass *parent_class;
115
gimp_convolve_register (Gimp *gimp,
116
GimpPaintRegisterCallback callback)
120
GIMP_TYPE_CONVOLVE_OPTIONS,
125
gimp_convolve_get_type (void)
127
static GType type = 0;
131
static const GTypeInfo info =
133
sizeof (GimpConvolveClass),
134
(GBaseInitFunc) NULL,
135
(GBaseFinalizeFunc) NULL,
136
(GClassInitFunc) gimp_convolve_class_init,
137
NULL, /* class_finalize */
138
NULL, /* class_data */
139
sizeof (GimpConvolve),
141
(GInstanceInitFunc) gimp_convolve_init,
144
type = g_type_register_static (GIMP_TYPE_BRUSH_CORE,
153
gimp_convolve_class_init (GimpConvolveClass *klass)
155
GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
157
parent_class = g_type_class_peek_parent (klass);
159
paint_core_class->paint = gimp_convolve_paint;
163
gimp_convolve_init (GimpConvolve *convolve)
168
gimp_convolve_paint (GimpPaintCore *paint_core,
169
GimpDrawable *drawable,
170
GimpPaintOptions *paint_options,
171
GimpPaintState paint_state,
176
case GIMP_PAINT_STATE_MOTION:
177
gimp_convolve_motion (paint_core, drawable, paint_options);
186
gimp_convolve_motion (GimpPaintCore *paint_core,
187
GimpDrawable *drawable,
188
GimpPaintOptions *paint_options)
190
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core);
191
GimpConvolveOptions *options = GIMP_CONVOLVE_OPTIONS (paint_options);
192
GimpContext *context = GIMP_CONTEXT (paint_options);
193
GimpPressureOptions *pressure_options = paint_options->pressure_options;
201
ConvolveClipType area_hclip = CONVOLVE_NOT_CLIPPED;
202
ConvolveClipType area_vclip = CONVOLVE_NOT_CLIPPED;
206
gimage = gimp_item_get_image (GIMP_ITEM (drawable));
208
if (gimp_drawable_is_indexed (drawable))
211
/* If the brush is smaller than the convolution matrix, don't convolve */
212
if (brush_core->brush->mask->width < matrix_size ||
213
brush_core->brush->mask->height < matrix_size)
216
opacity = gimp_paint_options_get_fade (paint_options, gimage,
217
paint_core->pixel_dist);
221
area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
225
/* configure the source pixel region */
226
pixel_region_init (&srcPR, gimp_drawable_data (drawable),
227
area->x, area->y, area->width, area->height, FALSE);
229
/* configure the destination pixel region */
230
destPR.bytes = area->bytes;
234
destPR.w = area->width;
235
destPR.h = area->height;
236
destPR.rowstride = area->width * destPR.bytes;
237
destPR.data = temp_buf_data (area);
239
rate = options->rate;
241
if (pressure_options->rate)
242
rate *= PRESSURE_SCALE * paint_core->cur_coords.pressure;
244
gimp_convolve_calculate_matrix (options->type, rate);
246
/* Image region near edges? If so, paint area will be clipped */
247
/* with respect to brush mask + 1 pixel border (# 19285) */
249
marginx = ((gint) paint_core->cur_coords.x -
250
brush_core->brush->mask->width / 2 - 1);
252
if (marginx != area->x)
254
area_hclip = CONVOLVE_NCLIP;
258
marginx = area->width - brush_core->brush->mask->width - 2;
261
area_hclip = CONVOLVE_PCLIP;
264
marginy = ((gint) paint_core->cur_coords.y -
265
brush_core->brush->mask->height / 2 - 1);
267
if (marginy != area->y)
269
area_vclip = CONVOLVE_NCLIP;
273
marginy = area->height - brush_core->brush->mask->height - 2;
276
area_vclip = CONVOLVE_PCLIP;
279
/* Has the TempBuf been clipped by a canvas edge or two? */
280
if (area_hclip == CONVOLVE_NOT_CLIPPED &&
281
area_vclip == CONVOLVE_NOT_CLIPPED)
284
/* Standard case: copy src to temp. convolve temp to dest. */
285
/* Brush defines pipe size and no edge adjustments are needed. */
287
/* If the source has no alpha, then add alpha pixels */
288
/* Because paint_core.c is alpha-only code. See below. */
294
tempPR.w = area->width;
295
tempPR.h = area->height;
298
if (! gimp_drawable_has_alpha (drawable))
300
/* note: this particular approach needlessly convolves the totally-
301
opaque alpha channel. A faster approach would be to keep
302
tempPR the same number of bytes as srcPR, and extend the
303
paint_core_replace_canvas API to handle non-alpha images. */
305
tempPR.bytes = srcPR.bytes + 1;
306
tempPR.rowstride = tempPR.bytes * tempPR.w;
307
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
308
tempPR.data = temp_data;
310
add_alpha_region (&srcPR, &tempPR);
314
tempPR.bytes = srcPR.bytes;
315
tempPR.rowstride = tempPR.bytes * tempPR.w;
316
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
317
tempPR.data = temp_data;
319
copy_region (&srcPR, &tempPR);
322
/* Convolve the region */
326
tempPR.w = area->width;
327
tempPR.h = area->height;
328
tempPR.data = temp_data;
330
convolve_region (&tempPR, &destPR, matrix, matrix_size,
331
matrix_divisor, GIMP_NORMAL_CONVOL, TRUE);
333
/* Free the allocated temp space */
338
/* TempBuf clipping has occured on at least one edge...
339
* Edge case: expand area under brush margin px on near edge(s), convolve
340
* expanded buffers. copy src -> ovrsz1 convolve ovrsz1 -> ovrsz2
341
* copy-with-crop ovrsz2 -> dest
343
PixelRegion ovrsz1PR;
344
PixelRegion ovrsz2PR;
345
guchar *ovrsz1_data = NULL;
346
guchar *ovrsz2_data = NULL;
349
fillcolor = gimp_pickable_get_color_at
350
(GIMP_PICKABLE (drawable),
351
CLAMP ((gint) paint_core->cur_coords.x,
352
0, gimp_item_width (GIMP_ITEM (drawable)) - 1),
353
CLAMP ((gint) paint_core->cur_coords.y,
354
0, gimp_item_height (GIMP_ITEM (drawable)) - 1));
356
marginx *= (marginx < 0) ? -1 : 0;
357
marginy *= (marginy < 0) ? -1 : 0;
361
ovrsz2PR.w = area->width + marginx;
362
ovrsz2PR.h = area->height + marginy;
363
ovrsz2PR.bytes = (gimp_drawable_has_alpha (drawable) ?
364
srcPR.bytes : srcPR.bytes + 1);
367
ovrsz2PR.rowstride = ovrsz2PR.bytes * ovrsz2PR.w;
368
ovrsz2PR.tiles = NULL;
369
ovrsz2_data = g_malloc (ovrsz2PR.h * ovrsz2PR.rowstride);
370
ovrsz2PR.data = ovrsz2_data;
374
ovrsz1PR.w = area->width + marginx;
375
ovrsz1PR.h = area->height + marginy;
376
ovrsz1PR.bytes = (gimp_drawable_has_alpha (drawable) ?
377
srcPR.bytes : srcPR.bytes + 1);
380
ovrsz1PR.rowstride = ovrsz2PR.bytes * ovrsz2PR.w;
381
ovrsz1PR.tiles = NULL;
382
ovrsz1_data = g_malloc (ovrsz1PR.h * ovrsz1PR.rowstride);
383
ovrsz1PR.data = ovrsz1_data;
385
color_region (&ovrsz1PR, fillcolor);
387
ovrsz1PR.x = (area_hclip == CONVOLVE_NCLIP)? marginx : 0;
388
ovrsz1PR.y = (area_vclip == CONVOLVE_NCLIP)? marginy : 0;
389
ovrsz1PR.w = area->width;
390
ovrsz1PR.h = area->height;
391
ovrsz1PR.data = (ovrsz1_data +
392
(ovrsz1PR.rowstride * ovrsz1PR.y) +
393
(ovrsz1PR.bytes * ovrsz1PR.x));
395
if (! gimp_drawable_has_alpha (drawable))
396
add_alpha_region (&srcPR, &ovrsz1PR);
398
copy_region (&srcPR, &ovrsz1PR);
400
/* Convolve the region */
404
ovrsz1PR.w = area->width + marginx;
405
ovrsz1PR.h = area->height + marginy;
406
ovrsz1PR.data = ovrsz1_data;
408
convolve_region (&ovrsz1PR, &ovrsz2PR, matrix, matrix_size,
409
matrix_divisor, GIMP_NORMAL_CONVOL, TRUE);
411
/* Crop and copy to destination */
413
ovrsz2PR.x = (area_hclip == CONVOLVE_NCLIP)? marginx : 0;
414
ovrsz2PR.y = (area_vclip == CONVOLVE_NCLIP)? marginy : 0;
415
ovrsz2PR.w = area->width;
416
ovrsz2PR.h = area->height;
417
ovrsz2PR.data = (ovrsz2_data +
418
(ovrsz2PR.rowstride * ovrsz2PR.y) +
419
(ovrsz2PR.bytes * ovrsz2PR.x));
421
copy_region (&ovrsz2PR, &destPR);
423
g_free (ovrsz1_data);
424
g_free (ovrsz2_data);
428
gimp_brush_core_replace_canvas (brush_core, drawable,
429
MIN (opacity, GIMP_OPACITY_OPAQUE),
430
gimp_context_get_opacity (context),
431
gimp_paint_options_get_brush_mode (paint_options),
432
GIMP_PAINT_INCREMENTAL);
436
gimp_convolve_calculate_matrix (GimpConvolveType type,
441
/* find percent of tool pressure */
442
percent = MIN (rate / 100.0, 1.0);
444
/* get the appropriate convolution matrix and size and divisor */
447
case GIMP_BLUR_CONVOLVE:
449
blur_matrix[12] = MIN_BLUR + percent * (MAX_BLUR - MIN_BLUR);
450
gimp_convolve_copy_matrix (blur_matrix, matrix, matrix_size);
453
case GIMP_SHARPEN_CONVOLVE:
455
sharpen_matrix[12] = MIN_SHARPEN + percent * (MAX_SHARPEN - MIN_SHARPEN);
456
gimp_convolve_copy_matrix (sharpen_matrix, matrix, matrix_size);
459
case GIMP_CUSTOM_CONVOLVE:
464
matrix_divisor = gimp_convolve_sum_matrix (matrix, matrix_size);
467
matrix_divisor = 1.0;
471
gimp_convolve_copy_matrix (const gfloat *src,
481
gimp_convolve_sum_matrix (const gfloat *matrix,