85
static GimpParamDef args[] =
96
static const GimpParamDef args[] =
87
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
88
{ GIMP_PDB_IMAGE, "image", "Input image (unused)" },
89
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
90
{ GIMP_PDB_FLOAT, "radius", "Radius of gaussian blur (in pixels, > 0.0)" },
91
{ GIMP_PDB_INT32, "maxdelta", "Maximum delta" }
98
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
99
{ GIMP_PDB_IMAGE, "image", "Input image (unused)" },
100
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
101
{ GIMP_PDB_FLOAT, "radius", "Radius of gaussian blur (in pixels, > 0.0)" },
102
{ GIMP_PDB_INT32, "max-delta", "Maximum delta" }
94
gimp_install_procedure ("plug_in_sel_gauss",
95
"Applies a selective gaussian blur to the "
96
"specified drawable.",
105
gimp_install_procedure (PLUG_IN_PROC,
106
N_("Blur neighboring pixels, but only in low-contrast areas"),
97
107
"This filter functions similar to the regular "
98
108
"gaussian blur filter except that neighbouring "
99
109
"pixels that differ more than the given maxdelta "
297
313
c1 = 1.0 / sqrt (2.0 * G_PI * sd);
298
314
c2 = -2.0 * (sd * sd);
300
for (dy = 0; dy < num; dy++)
302
for (dx = dy; dx < num; dx++)
304
mat[dx][dy] = c1 * exp ((dx * dx + dy * dy)/ c2);
305
mat[dy][dx] = mat[dx][dy];
316
for (dx = 0; dx < num; dx++)
317
mat[dx] = c1 * exp ((dx * dx)/ c2);
311
matrixmult (guchar *src,
320
gboolean preview_mode)
321
#if defined(ARCH_X86) && defined(USE_MMX) && defined(__GNUC__)
324
static ALWAYS_INLINE void
325
matrixmult_mmx (const guchar *src,
334
gboolean preview_mode)
322
gint i, j, b, nb, x, y;
325
gdouble sum, fact, d, alpha = 1.0;
326
guchar *src_b, *src_db;
330
nb = bytes - (has_alpha ? 1 : 0);
331
rowstride = width * bytes;
336
const gint rowstride = width * bytes;
337
const long long maxdelta4 = maxdelta * 0x0001000100010001ULL;
339
gdouble fsum, fscale;
342
g_assert (has_alpha ? (bytes == 4) : (bytes == 3 || bytes == 1));
344
imat = g_new (gushort, 2 * numrad + 3);
347
for (y = 1 - numrad; y < numrad; y++)
350
/* Ensure that one pixel's product fits in 16bits,
351
* and that the sum fits in 32bits.
353
fscale = MIN (0x100 / mat[0], 0x1000 / fsum);
354
for (y = 0; y < numrad; y++)
355
imat[numrad - y] = imat[numrad + y] = mat[y] * fscale;
357
for (y = numrad; y < numrad + 3; y++)
358
imat[numrad + y] = 0;
333
360
for (y = 0; y < height; y++)
363
"pxor %%mm7, %%mm7 \n\t":
335
366
for (x = 0; x < width; x++)
368
guint r, g, b, fr, fg, fb;
372
r = g = b = fr = fg = fb = 0;
337
374
dix = bytes * (width * y + x);
378
*(guint*) &dest[dix] = *(guint*) &src[dix];
385
"movd %0, %%mm6 \n\t"
386
"punpcklbw %%mm7, %%mm6 \n\t" /* center pixel */
390
offset = rowstride * (y - numrad) + bytes * (x - numrad);
395
"pshufw $0, %%mm6, %%mm6 \n\t": /* center pixel x4 */
397
for (j = 1 - numrad; j < numrad; j++)
405
if (y + j < 0 || y + j >= height)
408
src_b = src + offset - 3;
411
"pxor %%mm5, %%mm5 \n\t" /* row fact */
412
"pxor %%mm4, %%mm4 \n\t" /* row sum */
416
for (i = 1 - numrad; i < numrad; i += 4)
419
if (x + i < 0 || x + i >= width)
423
"movd %0, %%mm0 \n\t"
424
"movq %%mm6, %%mm1 \n\t"
425
"punpcklbw %%mm7, %%mm0 \n\t" /* one pixel */
426
"psubusw %%mm0, %%mm1 \n\t" /* diff */
427
"movq %%mm0, %%mm2 \n\t"
428
"psubusw %%mm6, %%mm2 \n\t"
429
"por %%mm2, %%mm1 \n\t" /* abs diff */
430
"pcmpgtw %1, %%mm1 \n\t" /* threshold */
431
"pandn %2, %%mm1 \n\t" /* weight */
432
"pmullw %%mm1, %%mm0 \n\t" /* pixel * weight */
433
"paddusw %%mm1, %%mm5 \n\t" /* fact */
434
"movq %%mm0, %%mm2 \n\t"
435
"punpcklwd %%mm7, %%mm0 \n\t"
436
"punpckhwd %%mm7, %%mm2 \n\t"
437
"paddd %%mm0, %%mm4 \n\t"
438
"paddd %%mm2, %%mm4 \n\t" /* sum */
439
:: "m"(*src_b), "m"(maxdelta4), "m"(imat[numrad + i])
444
"pshufw $0xb1, %%mm5, %%mm3 \n\t"
445
"paddusw %%mm3, %%mm5 \n\t"
446
"pshufw $0x0e, %%mm4, %%mm2 \n\t"
447
"pshufw $0x0e, %%mm5, %%mm3 \n\t"
448
"paddd %%mm2, %%mm4 \n\t"
449
"paddusw %%mm3, %%mm5 \n\t"
450
"movd %%mm4, %0 \n\t"
451
"movd %%mm5, %1 \n\t"
452
:"=g"(rowsum), "=g"(rowfact)
454
d = imat[numrad + j];
456
fr += d * (gushort) rowfact;
463
for (j = 1 - numrad; j < numrad; j++)
470
if (y + j < 0 || y + j >= height)
473
src_b = src + offset;
476
"pxor %%mm5, %%mm5 \n\t" /* row fact */
477
"pxor %%mm4, %%mm4 \n\t" /* row sum RG */
478
"pxor %%mm3, %%mm3 \n\t" /* row sum B */
482
for (i = 1 - numrad; i < numrad; i++)
485
if (x + i < 0 || x + i >= width)
490
"movd %0, %%mm0 \n\t"
491
"movq %%mm6, %%mm1 \n\t"
492
"punpcklbw %%mm7, %%mm0 \n\t" /* one pixel */
493
"psubusw %%mm0, %%mm1 \n\t" /* diff */
494
"movq %%mm0, %%mm2 \n\t"
495
"psubusw %%mm6, %%mm2 \n\t"
496
"por %%mm2, %%mm1 \n\t" /* abs diff */
497
"pcmpgtw %1, %%mm1 \n\t" /* threshold */
498
"pshufw $0, %2, %%mm2 \n\t" /* weight */
499
"pandn %%mm2, %%mm1 \n\t"
500
"pshufw $0xff, %%mm0, %%mm2 \n\t" /* alpha */
501
"psllw $8, %%mm2 \n\t"
502
"pmulhuw %%mm2, %%mm1 \n\t" /* weight *= alpha */
503
"pmullw %%mm1, %%mm0 \n\t" /* pixel * weight */
504
"paddusw %%mm1, %%mm5 \n\t" /* fact */
505
"movq %%mm0, %%mm2 \n\t"
506
"punpcklwd %%mm7, %%mm0 \n\t" /* RG */
507
"punpckhwd %%mm7, %%mm2 \n\t" /* B */
508
"paddd %%mm0, %%mm4 \n\t"
509
"paddd %%mm2, %%mm3 \n\t"
510
:: "m"(*src_b), "m"(maxdelta4), "m"(imat[numrad + i])
514
"movd %0, %%mm0 \n\t"
515
"movq %%mm6, %%mm1 \n\t"
516
"punpcklbw %%mm7, %%mm0 \n\t" /* one pixel */
517
"psubusw %%mm0, %%mm1 \n\t" /* diff */
518
"movq %%mm0, %%mm2 \n\t"
519
"psubusw %%mm6, %%mm2 \n\t"
520
"por %%mm2, %%mm1 \n\t" /* abs diff */
521
"pcmpgtw %1, %%mm1 \n\t" /* threshold */
522
"pshufw $0, %2, %%mm2 \n\t" /* weight */
523
"pandn %%mm2, %%mm1 \n\t"
524
"pmullw %%mm1, %%mm0 \n\t" /* pixel * weight */
525
"paddusw %%mm1, %%mm5 \n\t" /* fact */
526
"movq %%mm0, %%mm2 \n\t"
527
"punpcklwd %%mm7, %%mm0 \n\t" /* RG */
528
"punpckhwd %%mm7, %%mm2 \n\t" /* B */
529
"paddd %%mm0, %%mm4 \n\t"
530
"paddd %%mm2, %%mm3 \n\t"
531
:: "m"(*src_b), "m"(maxdelta4), "m"(imat[numrad + i])
536
"movd %%mm4, %0 \n\t"
537
"movd %%mm3, %2 \n\t"
538
"psrlq $32, %%mm4 \n\t"
539
"movq %%mm5, %3 \n\t"
540
"movd %%mm4, %1 \n\t"
541
:"=g"(rr), "=g"(rg), "=g"(rb), "=m"(*rf)
544
d = imat[numrad + j];
556
dest[dix+0] = r / fr;
558
dest[dix+1] = g / fg;
560
dest[dix+2] = b / fb;
564
dest[dix+0] = r / fr;
565
dest[dix+1] = g / fg;
566
dest[dix+2] = b / fb;
571
if (!(y % 10) && !preview_mode)
573
asm volatile ("emms");
574
gimp_progress_update ((double)y / (double)height);
578
asm volatile ("emms");
582
#endif /* ARCH_X86 && USE_MMX && __GNUC__ */
585
static ALWAYS_INLINE void
586
matrixmult_int (const guchar *src,
595
gboolean preview_mode)
597
const gint nb = bytes - (has_alpha ? 1 : 0);
598
const gint rowstride = width * bytes;
600
gdouble fsum, fscale;
601
gint i, j, b, x, y, d;
604
GimpCpuAccelFlags cpu = gimp_cpu_accel_get_support ();
606
if ((has_alpha ? (bytes == 4) : (bytes == 3 || bytes == 1))
607
&& (cpu & (GIMP_CPU_ACCEL_X86_MMXEXT | GIMP_CPU_ACCEL_X86_SSE)))
608
return matrixmult_mmx (src, dest, width, height, mat, numrad,
609
bytes, has_alpha, maxdelta, preview_mode);
612
imat = g_new (gushort, 2 * numrad);
615
for (y = 1 - numrad; y < numrad; y++)
618
/* Ensure that the sum fits in 32bits. */
619
fscale = 0x1000 / fsum;
620
for (y = 0; y < numrad; y++)
621
imat[numrad - y] = imat[numrad + y] = mat[y] * fscale;
623
for (y = 0; y < height; y++)
625
for (x = 0; x < width; x++)
627
gint dix = bytes * (width * y + x);
339
630
dest[dix + nb] = src[dix + nb];
341
632
for (b = 0; b < nb; b++)
345
src_db = src + dix + b;
634
const guchar *src_db = src + dix + b;
347
639
offset = rowstride * (y - numrad) + bytes * (x - numrad);
349
for (i = 1 - numrad; i < numrad; i++)
641
for (j = 1 - numrad; j < numrad; j++)
352
if (x + i < 0 || x + i >= width)
648
if (y + j < 0 || y + j >= height)
358
src_b = src + six + b;
360
for (j = 1 - numrad; j < numrad; j++)
651
src_b = src + offset + b;
653
for (i = 1 - numrad; i < numrad; i++)
365
if (y + j < 0 || y + j >= height)
659
if (x + i < 0 || x + i >= width)
368
662
tmp = *src_db - *src_b;
369
663
if (tmp > maxdelta || tmp < -maxdelta)
377
alpha = (double) src[six + nb] / 255.0;
670
rowsum += d * *src_b;
385
687
dest[dix + b] = *src_db;
387
689
dest[dix + b] = sum / fact;