summaryrefslogtreecommitdiffstats
path: root/src/imageplugins/blurfx
diff options
context:
space:
mode:
Diffstat (limited to 'src/imageplugins/blurfx')
-rw-r--r--src/imageplugins/blurfx/Makefile.am34
-rw-r--r--src/imageplugins/blurfx/blurfx.cpp1445
-rw-r--r--src/imageplugins/blurfx/blurfx.h191
-rw-r--r--src/imageplugins/blurfx/blurfxtool.cpp402
-rw-r--r--src/imageplugins/blurfx/blurfxtool.h93
-rw-r--r--src/imageplugins/blurfx/digikamimageplugin_blurfx.desktop49
-rw-r--r--src/imageplugins/blurfx/digikamimageplugin_blurfx_ui.rc20
-rw-r--r--src/imageplugins/blurfx/imageeffect_blurfx.cpp388
-rw-r--r--src/imageplugins/blurfx/imageeffect_blurfx.h80
-rw-r--r--src/imageplugins/blurfx/imageplugin_blurfx.cpp70
-rw-r--r--src/imageplugins/blurfx/imageplugin_blurfx.h56
11 files changed, 2828 insertions, 0 deletions
diff --git a/src/imageplugins/blurfx/Makefile.am b/src/imageplugins/blurfx/Makefile.am
new file mode 100644
index 00000000..51a78977
--- /dev/null
+++ b/src/imageplugins/blurfx/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_blurfx_la_SOURCES = imageplugin_blurfx.cpp \
+ blurfxtool.cpp blurfx.cpp
+
+digikamimageplugin_blurfx_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_blurfx_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_blurfx.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_blurfx.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_blurfx_ui.rc
+
diff --git a/src/imageplugins/blurfx/blurfx.cpp b/src/imageplugins/blurfx/blurfx.cpp
new file mode 100644
index 00000000..ec5ff30e
--- /dev/null
+++ b/src/imageplugins/blurfx/blurfx.cpp
@@ -0,0 +1,1445 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Blur FX threaded image filter.
+ *
+ * Copyright 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Blur algorithms copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot com>.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Represents 1
+#define ANGLE_RATIO 0.017453292519943295769236907685
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+// TQt includes.
+
+#include <tqdatetime.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dimggaussianblur.h"
+#include "blurfx.h"
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+BlurFX::BlurFX(Digikam::DImg *orgImage, TQObject *parent, int blurFXType, int distance, int level)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "BlurFX")
+{
+ m_blurFXType = blurFXType;
+ m_distance = distance;
+ m_level = level;
+
+ initFilter();
+}
+
+void BlurFX::filterImage(void)
+{
+ int w = m_orgImage.width();
+ int h = m_orgImage.height();
+
+ switch (m_blurFXType)
+ {
+ case ZoomBlur:
+ zoomBlur(&m_orgImage, &m_destImage, w/2, h/2, m_distance);
+ break;
+
+ case RadialBlur:
+ radialBlur(&m_orgImage, &m_destImage, w/2, h/2, m_distance);
+ break;
+
+ case FarBlur:
+ farBlur(&m_orgImage, &m_destImage, m_distance);
+ break;
+
+ case MotionBlur:
+ motionBlur(&m_orgImage, &m_destImage, m_distance, (double)m_level);
+ break;
+
+ case SoftenerBlur:
+ softenerBlur(&m_orgImage, &m_destImage);
+ break;
+
+ case ShakeBlur:
+ shakeBlur(&m_orgImage, &m_destImage, m_distance);
+ break;
+
+ case FocusBlur:
+ focusBlur(&m_orgImage, &m_destImage, w/2, h/2, m_distance, m_level*10);
+ break;
+
+ case SmartBlur:
+ smartBlur(&m_orgImage, &m_destImage, m_distance, m_level);
+ break;
+
+ case FrostGlass:
+ frostGlass(&m_orgImage, &m_destImage, m_distance);
+ break;
+
+ case Mosaic:
+ mosaic(&m_orgImage, &m_destImage, m_distance, m_distance);
+ break;
+ }
+}
+
+/* Function to apply the ZoomBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * X, Y => Center of zoom in the image
+ * Distance => Distance value
+ * pArea => Preview area.
+ *
+ * Theory => Here we have a effect similar to RadialBlur mode Zoom from
+ * Photoshop. The theory is very similar to RadialBlur, but has one
+ * difference. Instead we use pixels with the same radius and
+ * near angles, we take pixels with the same angle but near radius
+ * This radius is always from the center to out of the image, we
+ * calc a proportional radius from the center.
+ */
+void BlurFX::zoomBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int X, int Y, int Distance, TQRect pArea)
+{
+ if (Distance <= 1) return;
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ // We working on full image.
+ int xMin = 0;
+ int xMax = Width;
+ int yMin = 0;
+ int yMax = Height;
+
+ // If we working in preview mode, else we using the preview area.
+ if ( pArea.isValid() )
+ {
+ xMin = pArea.x();
+ xMax = pArea.x() + pArea.width();
+ yMin = pArea.y();
+ yMax = pArea.y() + pArea.height();
+ }
+
+ int h, w, nh, nw, r;
+ int sumR, sumG, sumB, nCount;
+ double lfRadius, lfNewRadius, lfRadMax, lfAngle;
+
+ Digikam::DColor color;
+ int offset;
+
+ lfRadMax = sqrt (Height * Height + Width * Width);
+
+ // number of added pixels
+ nCount = 0;
+
+ // we have reached the main loop
+ for (h = yMin; !m_cancel && (h < yMax); h++)
+ {
+ for (w = xMin; !m_cancel && (w < xMax); w++)
+ {
+ // ...we enter this loop to sum the bits
+
+ // we initialize the variables
+ sumR = sumG = sumB = nCount = 0;
+
+ nw = X - w;
+ nh = Y - h;
+
+ lfRadius = sqrt (nw * nw + nh * nh);
+ lfAngle = atan2 ((double)nh, (double)nw);
+ lfNewRadius = (lfRadius * Distance) / lfRadMax;
+
+ for (r = 0; !m_cancel && (r <= lfNewRadius); r++)
+ {
+ // we need to calc the positions
+ nw = (int)(X - (lfRadius - r) * cos (lfAngle));
+ nh = (int)(Y - (lfRadius - r) * sin (lfAngle));
+
+ if (IsInside(Width, Height, nw, nh))
+ {
+ // read color
+ offset = GetOffset(Width, nw, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ nCount++;
+ }
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)(h - yMin) * 100.0) / (yMax - yMin));
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the radialBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * X, Y => Center of radial in the image
+ * Distance => Distance value
+ * pArea => Preview area.
+ *
+ * Theory => Similar to RadialBlur from Photoshop, its an amazing effect
+ * Very easy to understand but a little hard to implement.
+ * We have all the image and find the center pixel. Now, we analize
+ * all the pixels and calc the radius from the center and find the
+ * angle. After this, we sum this pixel with others with the same
+ * radius, but different angles. Here I'm using degrees angles.
+ */
+void BlurFX::radialBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int X, int Y, int Distance, TQRect pArea)
+{
+ if (Distance <= 1) return;
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ // We working on full image.
+ int xMin = 0;
+ int xMax = Width;
+ int yMin = 0;
+ int yMax = Height;
+
+ // If we working in preview mode, else we using the preview area.
+ if ( pArea.isValid() )
+ {
+ xMin = pArea.x();
+ xMax = pArea.x() + pArea.width();
+ yMin = pArea.y();
+ yMax = pArea.y() + pArea.height();
+ }
+
+ int sumR, sumG, sumB, nw, nh;
+ double Radius, Angle, AngleRad;
+
+ Digikam::DColor color;
+ int offset;
+
+ double *nMultArray = new double[Distance * 2 + 1];
+
+ for (int i = -Distance; i <= Distance; i++)
+ nMultArray[i + Distance] = i * ANGLE_RATIO;
+
+ // number of added pixels
+ int nCount = 0;
+
+ // we have reached the main loop
+
+ for (int h = yMin; !m_cancel && (h < yMax); h++)
+ {
+ for (int w = xMin; !m_cancel && (w < xMax); w++)
+ {
+ // ...we enter this loop to sum the bits
+
+ // we initialize the variables
+ sumR = sumG = sumB = nCount = 0;
+
+ nw = X - w;
+ nh = Y - h;
+
+ Radius = sqrt (nw * nw + nh * nh);
+ AngleRad = atan2 ((double)nh, (double)nw);
+
+ for (int a = -Distance; !m_cancel && (a <= Distance); a++)
+ {
+ Angle = AngleRad + nMultArray[a + Distance];
+ // we need to calc the positions
+ nw = (int)(X - Radius * cos (Angle));
+ nh = (int)(Y - Radius * sin (Angle));
+
+ if (IsInside(Width, Height, nw, nh))
+ {
+ // read color
+ offset = GetOffset(Width, nw, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ nCount++;
+ }
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)(h - yMin) * 100.0) / (yMax - yMin));
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] nMultArray;
+}
+
+/* Function to apply the focusBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * BlurRadius => Radius of blurred image.
+ * BlendRadius => Radius of blending effect.
+ * bInversed => If true, invert focus effect.
+ * pArea => Preview area.
+ *
+ */
+void BlurFX::focusBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int X, int Y, int BlurRadius, int BlendRadius,
+ bool bInversed, TQRect pArea)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ // We working on full image.
+ int xMin = 0;
+ int xMax = Width;
+ int yMin = 0;
+ int yMax = Height;
+
+ // If we working in preview mode, else we using the preview area.
+ if ( pArea.isValid() )
+ {
+ xMin = pArea.x();
+ xMax = pArea.x() + pArea.width();
+ yMin = pArea.y();
+ yMax = pArea.y() + pArea.height();
+ }
+
+ if (pArea.isValid())
+ {
+ //UNTESTED (unused)
+
+ // We do not have access to the loop of the Gaussian blur,
+ // so we have to cut the image that we run the effect on.
+ int xMinBlur = xMin - BlurRadius;
+ int xMaxBlur = xMax + BlurRadius;
+ int yMinBlur = yMin - BlurRadius;
+ int yMaxBlur = yMax + BlurRadius;
+ Digikam::DImg areaImage = orgImage->copy(xMinBlur, yMaxBlur, xMaxBlur - xMinBlur, yMaxBlur - yMinBlur);
+
+ Digikam::DImgGaussianBlur(this, *orgImage, *destImage, 10, 75, BlurRadius);
+
+ // I am unsure about differences of 1 pixel
+ destImage->bitBltImage(&areaImage, xMinBlur, yMinBlur);
+ destImage->bitBltImage(orgImage, 0, 0, Width, yMinBlur, 0, 0);
+ destImage->bitBltImage(orgImage, 0, yMinBlur, xMinBlur, yMaxBlur - yMinBlur, 0, yMinBlur);
+ destImage->bitBltImage(orgImage, xMaxBlur + 1, yMinBlur, Width - xMaxBlur - 1, yMaxBlur - yMinBlur, yMaxBlur, yMinBlur);
+ destImage->bitBltImage(orgImage, 0, yMaxBlur + 1, Width, Height - yMaxBlur - 1, 0, yMaxBlur);
+
+ postProgress(80);
+ }
+ else
+ {
+ // copy bits for blurring
+ memcpy(pResBits, data, orgImage->numBytes());
+
+ // Gaussian blur using the BlurRadius parameter.
+ Digikam::DImgGaussianBlur(this, *orgImage, *destImage, 10, 80, BlurRadius);
+ }
+
+ // Blending results.
+
+ int nBlendFactor;
+ double lfRadius;
+ int offset;
+
+ Digikam::DColor colorOrgImage, colorBlurredImage;
+ int alpha;
+ uchar *ptr;
+
+ // get composer for default blending
+ Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffNone);
+
+ int nh = 0, nw = 0;
+
+ for (int h = yMin; !m_cancel && (h < yMax); h++)
+ {
+ nh = Y - h;
+
+ for (int w = xMin; !m_cancel && (w < xMax); w++)
+ {
+ nw = X - w;
+
+ lfRadius = sqrt (nh * nh + nw * nw);
+
+ if (sixteenBit)
+ nBlendFactor = LimitValues16 ((int)(65535.0 * lfRadius / (double)BlendRadius));
+ else
+ nBlendFactor = LimitValues8 ((int)(255.0 * lfRadius / (double)BlendRadius));
+
+ // Read color values
+ offset = GetOffset(Width, w, h, bytesDepth);
+ ptr = pResBits + offset;
+ colorOrgImage.setColor(data + offset, sixteenBit);
+ colorBlurredImage.setColor(ptr, sixteenBit);
+
+ // Preserve alpha
+ alpha = colorOrgImage.alpha();
+
+ // In normal mode, the image is focused in the middle
+ // and less focused towards the border.
+ // In inversed mode, the image is more focused towards the edge
+ // and less focused in the middle.
+ // This is achieved by swapping src and dest while blending.
+ if (bInversed)
+ {
+ // set blending alpha value as src alpha. Original value is stored above.
+ colorOrgImage.setAlpha(nBlendFactor);
+ // compose colors, writing to dest - colorBlurredImage
+ composer->compose(colorBlurredImage, colorOrgImage);
+ // restore alpha
+ colorBlurredImage.setAlpha(alpha);
+ // write color to destination
+ colorBlurredImage.setPixel(ptr);
+ }
+ else
+ {
+ // set blending alpha value as src alpha. Original value is stored above.
+ colorBlurredImage.setAlpha(nBlendFactor);
+ // compose colors, writing to dest - colorOrgImage
+ composer->compose(colorOrgImage, colorBlurredImage);
+ // restore alpha
+ colorOrgImage.setAlpha(alpha);
+ // write color to destination
+ colorOrgImage.setPixel(ptr);
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (80.0 + ((double)(h - yMin) * 20.0) / (yMax - yMin));
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete composer;
+}
+
+/* Function to apply the farBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Distance => Distance value
+ *
+ * Theory => This is an interesting effect, the blur is applied in that
+ * way: (the value "1" means pixel to be used in a blur calc, ok?)
+ * e.g. With distance = 2
+ * |1|1|1|1|1|
+ * |1|0|0|0|1|
+ * |1|0|C|0|1|
+ * |1|0|0|0|1|
+ * |1|1|1|1|1|
+ * We sum all the pixels with value = 1 and apply at the pixel with*
+ * the position "C".
+ */
+void BlurFX::farBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance)
+{
+ if (Distance < 1) return;
+
+ // we need to create our kernel
+ // e.g. distance = 3, so kernel={3 1 1 2 1 1 3}
+
+ int *nKern = new int[Distance * 2 + 1];
+
+ for (int i = 0; i < Distance * 2 + 1; i++)
+ {
+ // the first element is 3
+ if (i == 0)
+ nKern[i] = 2;
+ // the center element is 2
+ else if (i == Distance)
+ nKern[i] = 3;
+ // the last element is 3
+ else if (i == Distance * 2)
+ nKern[i] = 3;
+ // all other elements will be 1
+ else
+ nKern[i] = 1;
+ }
+
+ // now, we apply a convolution with kernel
+ MakeConvolution(orgImage, destImage, Distance, nKern);
+
+ // we must delete to free memory
+ delete [] nKern;
+}
+
+/* Function to apply the SmartBlur effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Radius => blur matrix radius.
+ * Strenght => Color strenght.
+ *
+ * Theory => Similar to SmartBlur from Photoshop, this function has the
+ * same engine as Blur function, but, in a matrix with n
+ * dimentions, we take only colors that pass by sensibility filter
+ * The result is a clean image, not totally blurred, but a image
+ * with correction between pixels.
+ */
+
+void BlurFX::smartBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Radius, int Strength)
+{
+ if (Radius <= 0) return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int progress;
+ int sumR, sumG, sumB, nCount, w, h, a;
+
+ int StrengthRange = Strength;
+ if (sixteenBit)
+ StrengthRange = (StrengthRange + 1) * 256 - 1;
+
+ Digikam::DColor color, radiusColor, radiusColorBlur;
+ int offset, loopOffset;
+
+ uchar* pBlur = new uchar[orgImage->numBytes()];
+
+ // We need to copy our bits to blur bits
+
+ memcpy (pBlur, data, orgImage->numBytes());
+
+ // we have reached the main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ // we initialize the variables
+ sumR = sumG = sumB = nCount = 0;
+
+ // read color
+ offset = GetOffset(Width, w, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // ...we enter this loop to sum the bits
+ for (a = -Radius; !m_cancel && (a <= Radius); a++)
+ {
+ // verify if is inside the rect
+ if (IsInside( Width, Height, w + a, h))
+ {
+ // read color
+ loopOffset = GetOffset(Width, w+a, h, bytesDepth);
+ radiusColor.setColor(data + loopOffset, sixteenBit);
+
+ // now, we have to check if is inside the sensibility filter
+ if (IsColorInsideTheRange (color.red(), color.green(), color.blue(),
+ radiusColor.red(), radiusColor.green(), radiusColor.blue(),
+ StrengthRange))
+ {
+ // finally we sum the bits
+ sumR += radiusColor.red();
+ sumG += radiusColor.green();
+ sumB += radiusColor.blue();
+ }
+ else
+ {
+ // finally we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ }
+
+ // increment counter
+ nCount++;
+ }
+ }
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pBlur + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 50.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // we have reached the second part of main loop
+
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ for (h = 0;!m_cancel && ( h < Height); h++)
+ {
+ // we initialize the variables
+ sumR = sumG = sumB = nCount = 0;
+
+ // read color
+ offset = GetOffset(Width, w, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // ...we enter this loop to sum the bits
+ for (a = -Radius; !m_cancel && (a <= Radius); a++)
+ {
+ // verify if is inside the rect
+ if (IsInside( Width, Height, w, h + a))
+ {
+ // read color
+ loopOffset = GetOffset(Width, w, h+a, bytesDepth);
+ radiusColor.setColor(data + loopOffset, sixteenBit);
+
+ // now, we have to check if is inside the sensibility filter
+ if (IsColorInsideTheRange (color.red(), color.green(), color.blue(),
+ radiusColor.red(), radiusColor.green(), radiusColor.blue(),
+ StrengthRange))
+ {
+ radiusColorBlur.setColor(pBlur + loopOffset, sixteenBit);
+ // finally we sum the bits
+ sumR += radiusColorBlur.red();
+ sumG += radiusColorBlur.green();
+ sumB += radiusColorBlur.blue();
+ }
+ else
+ {
+ // finally we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ }
+
+ // increment counter
+ nCount++;
+ }
+ }
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (50.0 + ((double)w * 50.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // now, we must free memory
+ delete [] pBlur;
+}
+
+/* Function to apply the motionBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Distance => Distance value
+ * Angle => Angle direction (degrees)
+ *
+ * Theory => Similar to MotionBlur from Photoshop, the engine is very
+ * simple to undertand, we take a pixel (duh!), with the angle we
+ * will taking near pixels. After this we blur (add and do a
+ * division).
+ */
+void BlurFX::motionBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance, double Angle)
+{
+ if (Distance == 0) return;
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ Digikam::DColor color;
+ int offset;
+
+ // we try to avoid division by 0 (zero)
+ if (Angle == 0.0) Angle = 360.0;
+
+ int sumR, sumG, sumB, nCount, nw, nh;
+ double nAngX, nAngY;
+
+ // we initialize cos and sin for a best performance
+ nAngX = cos ((2.0 * M_PI) / (360.0 / Angle));
+ nAngY = sin ((2.0 * M_PI) / (360.0 / Angle));
+
+ // total of bits to be taken is given by this formula
+ nCount = Distance * 2 + 1;
+
+ // we will alloc size and calc the possible results
+ int *lpXArray = new int[nCount];
+ int *lpYArray = new int[nCount];
+
+ for (int i = 0; i < nCount; i++)
+ {
+ lpXArray[i] = lround( (double)(i - Distance) * nAngX);
+ lpYArray[i] = lround( (double)(i - Distance) * nAngY);
+ }
+
+ // we have reached the main loop
+
+ for (int h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (int w = 0; !m_cancel && (w < Width); w++)
+ {
+ // we initialize the variables
+ sumR = sumG = sumB = 0;
+
+ // ...we enter this loop to sum the bits
+ for (int a = -Distance; !m_cancel && (a <= Distance); a++)
+ {
+ // we need to calc the positions
+ nw = w + lpXArray[a + Distance];
+ nh = h + lpYArray[a + Distance];
+
+ offset = GetOffsetAdjusted(Width, Height, nw, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] lpXArray;
+ delete [] lpYArray;
+}
+
+/* Function to apply the softenerBlur effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ *
+ * Theory => An interesting blur-like function. In dark tones we apply a
+ * blur with 3x3 dimentions, in light tones, we apply a blur with
+ * 5x5 dimentions. Easy, hun?
+ */
+void BlurFX::softenerBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int SomaR = 0, SomaG = 0, SomaB = 0;
+ int Gray;
+
+ Digikam::DColor color, colorSoma;
+ int offset, offsetSoma;
+
+ int grayLimit = sixteenBit ? 32767 : 127;
+
+ for (int h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (int w = 0; !m_cancel && (w < Width); w++)
+ {
+ SomaR = SomaG = SomaB = 0;
+
+ offset = GetOffset(Width, w, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ Gray = (color.red() + color.green() + color.blue()) / 3;
+
+ if (Gray > grayLimit)
+ {
+ // 7x7
+ for (int a = -3; !m_cancel && (a <= 3); a++)
+ {
+ for (int b = -3; !m_cancel && (b <= 3); b++)
+ {
+ if ((h + a < 0) || (w + b < 0))
+ offsetSoma = offset;
+ else
+ offsetSoma = GetOffset(Width, (w + Lim_Max (w, b, Width)),
+ (h + Lim_Max (h, a, Height)), bytesDepth);
+ colorSoma.setColor(data + offsetSoma, sixteenBit);
+
+ SomaR += colorSoma.red();
+ SomaG += colorSoma.green();
+ SomaB += colorSoma.blue();
+ }
+ }
+
+ // 7*7 = 49
+ color.setRed (SomaR / 49);
+ color.setGreen(SomaG / 49);
+ color.setBlue (SomaB / 49);
+ color.setPixel(pResBits + offset);
+ }
+ else
+ {
+ // 3x3
+ for (int a = -1; !m_cancel && (a <= 1); a++)
+ {
+ for (int b = -1; !m_cancel && (b <= 1); b++)
+ {
+ if ((h + a < 0) || (w + b < 0))
+ offsetSoma = offset;
+ else
+ offsetSoma = GetOffset(Width, (w + Lim_Max (w, b, Width)),
+ (h + Lim_Max (h, a, Height)), bytesDepth);
+ colorSoma.setColor(data + offsetSoma, sixteenBit);
+
+ SomaR += colorSoma.red();
+ SomaG += colorSoma.green();
+ SomaB += colorSoma.blue();
+ }
+ }
+
+ // 3*3 = 9
+ color.setRed (SomaR / 9);
+ color.setGreen(SomaG / 9);
+ color.setBlue (SomaB / 9);
+ color.setPixel(pResBits + offset);
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the shake blur effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Distance => Distance between layers (from origin)
+ *
+ * Theory => Similar to Fragment effect from Photoshop. We create 4 layers
+ * each one has the same distance from the origin, but have
+ * different positions (top, button, left and right), with these 4
+ * layers, we join all the pixels.
+ */
+void BlurFX::shakeBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ Digikam::DColor color, colorLayer, color1, color2, color3, color4;
+ int offset, offsetLayer;
+
+ int numBytes = orgImage->numBytes();
+ uchar* Layer1 = new uchar[numBytes];
+ uchar* Layer2 = new uchar[numBytes];
+ uchar* Layer3 = new uchar[numBytes];
+ uchar* Layer4 = new uchar[numBytes];
+
+ int h, w, nw, nh;
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ offsetLayer = GetOffset(Width, w, h, bytesDepth);
+
+ nh = (h + Distance >= Height) ? Height - 1 : h + Distance;
+ offset = GetOffset(Width, w, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(Layer1 + offsetLayer);
+
+ nh = (h - Distance < 0) ? 0 : h - Distance;
+ offset = GetOffset(Width, w, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(Layer2 + offsetLayer);
+
+ nw = (w + Distance >= Width) ? Width - 1 : w + Distance;
+ offset = GetOffset(Width, nw, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(Layer3 + offsetLayer);
+
+ nw = (w - Distance < 0) ? 0 : w - Distance;
+ offset = GetOffset(Width, nw, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(Layer4 + offsetLayer);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 50.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ for (int h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (int w = 0; !m_cancel && (w < Width); w++)
+ {
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read original data to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+ // read colors from all four layers
+ color1.setColor(Layer1 + offset, sixteenBit);
+ color2.setColor(Layer2 + offset, sixteenBit);
+ color3.setColor(Layer3 + offset, sixteenBit);
+ color4.setColor(Layer4 + offset, sixteenBit);
+
+ // set color components of resulting color
+ color.setRed ( (color1.red() + color2.red() + color3.red() + color4.red()) / 4 );
+ color.setGreen( (color1.green() + color2.green() + color3.green() + color4.green()) / 4 );
+ color.setBlue ( (color1.blue() + color2.blue() + color3.blue() + color4.blue()) / 4 );
+
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (50.0 + ((double)h * 50.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] Layer1;
+ delete [] Layer2;
+ delete [] Layer3;
+ delete [] Layer4;
+}
+
+/* Function to apply the frostGlass effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Frost => Frost value
+ *
+ * Theory => Similar to Diffuse effect, but the random byte is defined
+ * in a matrix. Diffuse uses a random diagonal byte.
+ */
+void BlurFX::frostGlass(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Frost)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ Frost = (Frost < 1) ? 1 : (Frost > 10) ? 10 : Frost;
+
+ int h, w;
+
+ Digikam::DColor color;
+ int offset;
+
+ // Randomize.
+
+ TQDateTime dt = TQDateTime::currentDateTime();
+ TQDateTime Y2000( TQDate(2000, 1, 1), TQTime(0, 0, 0) );
+ uint seed = dt.secsTo(Y2000);
+
+ int range = sixteenBit ? 65535 : 255;
+
+ // it is a huge optimizsation to allocate these here once
+ uchar *IntensityCount = new uchar[range + 1];
+ uint *AverageColorR = new uint[range + 1];
+ uint *AverageColorG = new uint[range + 1];
+ uint *AverageColorB = new uint[range + 1];
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // get random color from surrounding of w|h
+ color = RandomColor (data, Width, Height, sixteenBit, bytesDepth,
+ w, h, Frost, color.alpha(), &seed, range, IntensityCount,
+ AverageColorR, AverageColorG, AverageColorB);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] IntensityCount;
+ delete [] AverageColorR;
+ delete [] AverageColorG;
+ delete [] AverageColorB;
+}
+
+/* Function to apply the mosaic effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Size => Size of mosaic .
+ *
+ * Theory => Ok, you can find some mosaic effects on PSC, but this one
+ * has a great feature, if you see a mosaic in other code you will
+ * see that the corner pixel doesn't change. The explanation is
+ * simple, the color of the mosaic is the same as the first pixel
+ * get. Here, the color of the mosaic is the same as the mosaic
+ * center pixel.
+ * Now the function scan the rows from the top (like photoshop).
+ */
+void BlurFX::mosaic(Digikam::DImg *orgImage, Digikam::DImg *destImage, int SizeW, int SizeH)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ // we need to check for valid values
+ if (SizeW < 1) SizeW = 1;
+ if (SizeH < 1) SizeH = 1;
+ if ((SizeW == 1) && (SizeH == 1)) return;
+
+ Digikam::DColor color;
+ int offsetCenter, offset;
+
+ // this loop will never look for transparent colors
+
+ for (int h = 0; !m_cancel && (h < Height); h += SizeH)
+ {
+ for (int w = 0; !m_cancel && (w < Width); w += SizeW)
+ {
+ // we have to find the center pixel for mosaic's rectangle
+
+ offsetCenter = GetOffsetAdjusted(Width, Height, w + (SizeW / 2), h + (SizeH / 2), bytesDepth);
+ color.setColor(data + offsetCenter, sixteenBit);
+
+ // now, we fill the mosaic's rectangle with the center pixel color
+
+ for (int subw = w; !m_cancel && (subw <= w + SizeW); subw++)
+ {
+ for (int subh = h; !m_cancel && (subh <= h + SizeH); subh++)
+ {
+ // if is inside...
+ if (IsInside(Width, Height, subw, subh))
+ {
+ // set color
+ offset = GetOffset(Width, subw, subh, bytesDepth);
+ color.setPixel(pResBits + offset);
+ }
+ }
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to get a color in a matriz with a determined size
+ *
+ * Bits => Bits array
+ * Width => Image width
+ * Height => Image height
+ * X => Position horizontal
+ * Y => Position vertical
+ * Radius => The radius of the matrix to be created
+ *
+ * Theory => This function takes from a distinct matrix a random color
+ */
+Digikam::DColor BlurFX::RandomColor(uchar *Bits, int Width, int Height, bool sixteenBit, int bytesDepth,
+ int X, int Y, int Radius,
+ int alpha, uint *randomSeed, int range, uchar *IntensityCount,
+ uint *AverageColorR, uint *AverageColorG, uint *AverageColorB)
+{
+ Digikam::DColor color;
+ int offset;
+
+ int w, h, counter = 0;
+
+ int I;
+
+ // For 16 bit we have a problem here because this takes 255 times longer,
+ // and the algorithm is really slow for 16 bit, but I think this cannot be avoided.
+ memset(IntensityCount, 0, range );
+ memset(AverageColorR, 0, range );
+ memset(AverageColorG, 0, range );
+ memset(AverageColorB, 0, range );
+
+ for (w = X - Radius; !m_cancel && (w <= X + Radius); w++)
+ {
+ for (h = Y - Radius; !m_cancel && (h <= Y + Radius); h++)
+ {
+ if ((w >= 0) && (w < Width) && (h >= 0) && (h < Height))
+ {
+ offset = GetOffset(Width, w, h, bytesDepth);
+ color.setColor(Bits + offset, sixteenBit);
+ I = GetIntensity (color.red(), color.green(), color.blue());
+ IntensityCount[I]++;
+ counter++;
+
+ if (IntensityCount[I] == 1)
+ {
+ AverageColorR[I] = color.red();
+ AverageColorG[I] = color.green();
+ AverageColorB[I] = color.blue();
+ }
+ else
+ {
+ AverageColorR[I] += color.red();
+ AverageColorG[I] += color.green();
+ AverageColorB[I] += color.blue();
+ }
+ }
+ }
+ }
+
+ // check for m_cancel here before entering the do loop (will crash with SIGFPE otherwise)
+ if (m_cancel)
+ return Digikam::DColor(0, 0, 0, 0, sixteenBit);
+
+ int RandNumber, count, Index, ErrorCount = 0;
+ int J;
+
+ do
+ {
+ RandNumber = abs( (int)((rand_r(randomSeed) + 1) * ((double)counter / (1 + (double) RAND_MAX))) );
+ count = 0;
+ Index = 0;
+
+ do
+ {
+ count += IntensityCount[Index];
+ Index++;
+ }
+ while (count < RandNumber && !m_cancel);
+
+ J = Index - 1;
+ ErrorCount++;
+ }
+ while ((IntensityCount[J] == 0) && (ErrorCount <= counter) && !m_cancel);
+
+ if (m_cancel)
+ return Digikam::DColor(0, 0, 0, 0, sixteenBit);
+
+
+ color.setSixteenBit(sixteenBit);
+ color.setAlpha(alpha);
+
+ if (ErrorCount >= counter)
+ {
+ color.setRed (AverageColorR[J] / counter);
+ color.setGreen(AverageColorG[J] / counter);
+ color.setBlue (AverageColorB[J] / counter);
+ }
+ else
+ {
+ color.setRed (AverageColorR[J] / IntensityCount[J]);
+ color.setGreen(AverageColorG[J] / IntensityCount[J]);
+ color.setBlue (AverageColorB[J] / IntensityCount[J]);
+ }
+
+ return color;
+}
+
+/* Function to simple convolve a unique pixel with a determined radius
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Radius => kernel radius, e.g. rad=1, so array will be 3X3
+ * Kernel => kernel array to apply.
+ *
+ * Theory => I've worked hard here, but I think this is a very smart
+ * way to convolve an array, its very hard to explain how I reach
+ * this, but the trick here its to store the sum used by the
+ * previous pixel, so we sum with the other pixels that wasn't get
+ */
+void BlurFX::MakeConvolution (Digikam::DImg *orgImage, Digikam::DImg *destImage, int Radius, int Kernel[])
+{
+ if (Radius <= 0) return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pOutBits = destImage->bits();
+
+ int progress;
+ int n, h, w;
+
+ int nSumR, nSumG, nSumB, nCount;
+ int nKernelWidth = Radius * 2 + 1;
+ int range = sixteenBit ? 65536 : 256;
+ Digikam::DColor color;
+ int offset;
+
+ uchar* pBlur = new uchar[orgImage->numBytes()];
+
+ // We need to copy our bits to blur bits
+
+ memcpy (pBlur, data, orgImage->numBytes());
+
+ // We need to alloc a 2d array to help us to store the values
+
+ int** arrMult = Alloc2DArray (nKernelWidth, range);
+
+ for (int i = 0; i < nKernelWidth; i++)
+ for (int j = 0; j < range; j++)
+ arrMult[i][j] = j * Kernel[i];
+
+ // Now, we enter in the main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ // initialize the variables
+ nSumR = nSumG = nSumB = nCount = 0;
+
+ // first of all, we need to blur the horizontal lines
+
+ for (n = -Radius; !m_cancel && (n <= Radius); n++)
+ {
+ // if is inside...
+ if (IsInside (Width, Height, w + n, h))
+ {
+ // read color from orgImage
+ offset = GetOffset(Width, w+n, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // finally, we sum the pixels using a method similar to assigntables
+ nSumR += arrMult[n + Radius][color.red()];
+ nSumG += arrMult[n + Radius][color.green()];
+ nSumB += arrMult[n + Radius][color.blue()];
+
+ // we need to add the kernel value to the counter
+ nCount += Kernel[n + Radius];
+ }
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color from orgImage to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ if (sixteenBit)
+ {
+ color.setRed (LimitValues16(nSumR / nCount));
+ color.setGreen(LimitValues16(nSumG / nCount));
+ color.setBlue (LimitValues16(nSumB / nCount));
+ }
+ else
+ {
+ color.setRed (LimitValues8(nSumR / nCount));
+ color.setGreen(LimitValues8(nSumG / nCount));
+ color.setBlue (LimitValues8(nSumB / nCount));
+ }
+
+ // write color to blur bits
+ color.setPixel(pBlur + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 50.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // We enter in the second main loop
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ // initialize the variables
+ nSumR = nSumG = nSumB = nCount = 0;
+
+ // first of all, we need to blur the vertical lines
+ for (n = -Radius; !m_cancel && (n <= Radius); n++)
+ {
+ // if is inside...
+ if (IsInside(Width, Height, w, h + n))
+ {
+ // read color from blur bits
+ offset = GetOffset(Width, w, h+n, bytesDepth);
+ color.setColor(pBlur + offset, sixteenBit);
+
+ // finally, we sum the pixels using a method similar to assigntables
+ nSumR += arrMult[n + Radius][color.red()];
+ nSumG += arrMult[n + Radius][color.green()];
+ nSumB += arrMult[n + Radius][color.blue()];
+
+ // we need to add the kernel value to the counter
+ nCount += Kernel[n + Radius];
+ }
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color from orgImage to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ if (sixteenBit)
+ {
+ color.setRed (LimitValues16(nSumR / nCount));
+ color.setGreen(LimitValues16(nSumG / nCount));
+ color.setBlue (LimitValues16(nSumB / nCount));
+ }
+ else
+ {
+ color.setRed (LimitValues8(nSumR / nCount));
+ color.setGreen(LimitValues8(nSumG / nCount));
+ color.setBlue (LimitValues8(nSumB / nCount));
+ }
+
+ // write color to destination
+ color.setPixel(pOutBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (50.0 + ((double)w * 50.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // now, we must free memory
+ Free2DArray (arrMult, nKernelWidth);
+ delete [] pBlur;
+}
+
+} // NameSpace DigikamBlurFXImagesPlugin
diff --git a/src/imageplugins/blurfx/blurfx.h b/src/imageplugins/blurfx/blurfx.h
new file mode 100644
index 00000000..4a4397b4
--- /dev/null
+++ b/src/imageplugins/blurfx/blurfx.h
@@ -0,0 +1,191 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Blur FX threaded image filter.
+ *
+ * Copyright 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Blur algorithms copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot com>.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BLURFX_H
+#define BLURFX_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+class BlurFX : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ BlurFX(Digikam::DImg *orgImage, TQObject *parent=0, int blurFXType=ZoomBlur,
+ int distance=100, int level=45);
+
+ ~BlurFX(){};
+
+public:
+
+ enum BlurFXTypes
+ {
+ ZoomBlur=0,
+ RadialBlur,
+ FarBlur,
+ MotionBlur,
+ SoftenerBlur,
+ ShakeBlur,
+ FocusBlur,
+ SmartBlur,
+ FrostGlass,
+ Mosaic
+ };
+
+private: // BlurFX filter data.
+
+ int m_blurFXType;
+ int m_distance;
+ int m_level;
+
+private: // BlurFX filter methods.
+
+ virtual void filterImage(void);
+
+ // Backported from ImageProcessing version 1
+ void softenerBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage);
+ void shakeBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance);
+ void frostGlass(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Frost);
+
+ // Backported from ImageProcessing version 2
+ void zoomBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int X, int Y, int Distance, TQRect pArea=TQRect());
+ void radialBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int X, int Y, int Distance, TQRect pArea=TQRect());
+ void focusBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int X, int Y, int BlurRadius, int BlendRadius,
+ bool bInversed=false, TQRect pArea=TQRect());
+ void farBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance);
+ void motionBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance, double Angle=0.0);
+ void smartBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Radius, int Strenght);
+ void mosaic(Digikam::DImg *orgImage, Digikam::DImg *destImage, int SizeW, int SizeH);
+
+private: // Internal filter methods.
+
+ void MakeConvolution(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Radius, int Kernel[]);
+
+ Digikam::DColor RandomColor(uchar *Bits, int Width, int Height, bool sixteenBit, int bytesDepth,
+ int X, int Y, int Radius,
+ int alpha, uint *randomSeed, int range, uchar *IntensityCount,
+ uint *AverageColorR, uint *AverageColorG, uint *AverageColorB);
+
+ // Return the limit defined the max and min values.
+ inline int Lim_Max(int Now, int Up, int Max)
+ {
+ --Max;
+ while (Now > Max - Up) --Up;
+ return (Up);
+ };
+
+ // Return the luminance (Y) component of YIQ color model.
+ inline int GetIntensity (int R, int G, int B)
+ {
+ return (int)(R * 0.3 + G * 0.59 + B * 0.11);
+ };
+
+ // function to allocate a 2d array
+ inline int** Alloc2DArray (int Columns, int Rows)
+ {
+ // First, we declare our future 2d array to be returned
+ int** lpcArray = NULL;
+
+ // Now, we alloc the main pointer with Columns
+ lpcArray = new int*[Columns];
+
+ for (int i = 0; i < Columns; i++)
+ lpcArray[i] = new int[Rows];
+
+ return (lpcArray);
+ }
+
+ // Function to deallocates the 2d array previously created
+ inline void Free2DArray (int** lpcArray, int Columns)
+ {
+ // loop to dealocate the columns
+ for (int i = 0; i < Columns; i++)
+ delete [] lpcArray[i];
+
+ // now, we delete the main pointer
+ delete [] lpcArray;
+ }
+
+ inline bool IsInside (int Width, int Height, int X, int Y)
+ {
+ bool bIsWOk = ((X < 0) ? false : (X >= Width ) ? false : true);
+ bool bIsHOk = ((Y < 0) ? false : (Y >= Height) ? false : true);
+ return (bIsWOk && bIsHOk);
+ };
+
+ inline uchar LimitValues8(int ColorValue)
+ {
+ if (ColorValue > 255) ColorValue = 255;
+ if (ColorValue < 0) ColorValue = 0;
+ return ((uchar) ColorValue);
+ };
+
+
+ inline int LimitValues16(int ColorValue)
+ {
+ if (ColorValue > 65535) ColorValue = 65535;
+ if (ColorValue < 0) ColorValue = 0;
+ return ColorValue;
+ };
+
+ inline int GetOffset(int Width, int X, int Y, int bytesDepth)
+ {
+ return (Y * Width * bytesDepth) + (X * bytesDepth);
+ };
+
+ inline int GetOffsetAdjusted(int Width, int Height, int X, int Y, int bytesDepth)
+ {
+ X = (X < 0) ? 0 : ((X >= Width ) ? (Width - 1) : X);
+ Y = (Y < 0) ? 0 : ((Y >= Height) ? (Height - 1) : Y);
+ return GetOffset(Width, X, Y, bytesDepth);
+ };
+
+ inline bool IsColorInsideTheRange (int cR, int cG, int cB,
+ int nR, int nG, int nB,
+ int Range)
+ {
+ if ((nR >= cR - Range) && (nR <= cR + Range))
+ if ((nG >= cG - Range) && (nG <= cG + Range))
+ if ((nB >= cB - Range) && (nB <= cB + Range))
+ return (true);
+
+ return (false);
+ };
+
+};
+
+} // NameSpace DigikamBlurFXImagesPlugin
+
+#endif /* BLURFX_H */
diff --git a/src/imageplugins/blurfx/blurfxtool.cpp b/src/imageplugins/blurfx/blurfxtool.cpp
new file mode 100644
index 00000000..2998dbde
--- /dev/null
+++ b/src/imageplugins/blurfx/blurfxtool.cpp
@@ -0,0 +1,402 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqdatetime.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqslider.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "blurfx.h"
+#include "blurfxtool.h"
+#include "blurfxtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+BlurFXTool::BlurFXTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("blurfx");
+ setToolName(i18n("Blur FX"));
+ setToolIcon(SmallIcon("blurfx"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 6, 1);
+
+ m_effectTypeLabel = new TQLabel(i18n("Type:"), m_gboxSettings->plainPage());
+
+ m_effectType = new RComboBox(m_gboxSettings->plainPage());
+ m_effectType->insertItem(i18n("Zoom Blur"));
+ m_effectType->insertItem(i18n("Radial Blur"));
+ m_effectType->insertItem(i18n("Far Blur"));
+ m_effectType->insertItem(i18n("Motion Blur"));
+ m_effectType->insertItem(i18n("Softener Blur"));
+ m_effectType->insertItem(i18n("Skake Blur"));
+ m_effectType->insertItem(i18n("Focus Blur"));
+ m_effectType->insertItem(i18n("Smart Blur"));
+ m_effectType->insertItem(i18n("Frost Glass"));
+ m_effectType->insertItem(i18n("Mosaic"));
+ m_effectType->setDefaultItem(BlurFX::ZoomBlur);
+ TQWhatsThis::add( m_effectType, i18n("<p>Select the blurring effect to apply to the image.<p>"
+ "<b>Zoom Blur</b>: blurs the image along radial lines starting from "
+ "a specified center point. This simulates the blur of a zooming camera.<p>"
+ "<b>Radial Blur</b>: blurs the image by rotating the pixels around "
+ "the specified center point. This simulates the blur of a rotating camera.<p>"
+ "<b>Far Blur</b>: blurs the image by using far pixels. This simulates the blur "
+ "of an unfocalized camera lens.<p>"
+ "<b>Motion Blur</b>: blurs the image by moving the pixels horizontally. "
+ "This simulates the blur of a linear moving camera.<p>"
+ "<b>Softener Blur</b>: blurs the image softly in dark tones and hardly in light "
+ "tones. This gives images a dreamy and glossy soft focus effect. It's ideal "
+ "for creating romantic portraits, glamour photographs, or giving images a warm "
+ "and subtle glow.<p>"
+ "<b>Skake Blur</b>: blurs the image by skaking randomly the pixels. "
+ "This simulates the blur of a random moving camera.<p>"
+ "<b>Focus Blur</b>: blurs the image corners to reproduce the astigmatism distortion "
+ "of a lens.<p>"
+ "<b>Smart Blur</b>: finds the edges of color in your image and blurs them without "
+ "muddying the rest of the image.<p>"
+ "<b>Frost Glass</b>: blurs the image by randomly disperse light coming through "
+ "a frosted glass.<p>"
+ "<b>Mosaic</b>: divides the photograph into rectangular cells and then "
+ "recreates it by filling those cells with average pixel value."));
+
+ m_distanceLabel = new TQLabel(i18n("Distance:"), m_gboxSettings->plainPage());
+ m_distanceInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_distanceInput->setRange(0, 100, 1);
+ m_distanceInput->setDefaultValue(3);
+ TQWhatsThis::add( m_distanceInput, i18n("<p>Set here the blur distance in pixels."));
+
+ m_levelLabel = new TQLabel(i18n("Level:"), m_gboxSettings->plainPage());
+ m_levelInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_levelInput->setRange(0, 360, 1);
+ m_levelInput->setDefaultValue(128);
+ TQWhatsThis::add( m_levelInput, i18n("<p>This value controls the level to use with the current effect."));
+
+ grid->addMultiCellWidget(m_effectTypeLabel, 0, 0, 0, 1);
+ grid->addMultiCellWidget(m_effectType, 1, 1, 0, 1);
+ grid->addMultiCellWidget(m_distanceLabel, 2, 2, 0, 1);
+ grid->addMultiCellWidget(m_distanceInput, 3, 3, 0, 1);
+ grid->addMultiCellWidget(m_levelLabel, 4, 4, 0, 1);
+ grid->addMultiCellWidget(m_levelInput, 5, 5, 0, 1);
+ grid->setRowStretch(6, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "blurfx Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_effectType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffectTypeChanged(int)));
+
+ connect(m_distanceInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_levelInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+BlurFXTool::~BlurFXTool()
+{
+}
+
+void BlurFXTool::renderingFinished(void)
+{
+
+ m_effectTypeLabel->setEnabled(true);
+ m_effectType->setEnabled(true);
+ m_distanceInput->setEnabled(true);
+ m_distanceLabel->setEnabled(true);
+
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FarBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ break;
+
+ case BlurFX::MotionBlur:
+ case BlurFX::FocusBlur:
+ case BlurFX::SmartBlur:
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ break;
+
+ case BlurFX::SoftenerBlur:
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ break;
+ }
+}
+
+void BlurFXTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("blurfx Tool");
+ m_effectType->blockSignals(true);
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+
+ m_effectType->setCurrentItem(config->readNumEntry("EffectType", m_effectType->defaultItem()));
+ m_distanceInput->setValue(config->readNumEntry("DistanceAjustment", m_distanceInput->defaultValue()));
+ m_levelInput->setValue(config->readNumEntry("LevelAjustment", m_levelInput->defaultValue()));
+
+ m_effectType->blockSignals(false);
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+}
+
+void BlurFXTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("blurfx Tool");
+ config->writeEntry("EffectType", m_effectType->currentItem());
+ config->writeEntry("DistanceAjustment", m_distanceInput->value());
+ config->writeEntry("LevelAjustment", m_levelInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void BlurFXTool::slotResetSettings()
+{
+ m_effectType->blockSignals(true);
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+
+ m_effectType->slotReset();
+ m_distanceInput->slotReset();
+ m_levelInput->slotReset();
+
+ m_effectType->blockSignals(false);
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+
+ slotEffectTypeChanged(m_effectType->defaultItem());
+}
+
+void BlurFXTool::slotEffectTypeChanged(int type)
+{
+ m_distanceInput->setEnabled(true);
+ m_distanceLabel->setEnabled(true);
+
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+
+ m_distanceInput->setRange(0, 200, 1);
+ m_distanceInput->setValue(100);
+ m_levelInput->setRange(0, 360, 1);
+ m_levelInput->setValue(45);
+
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ switch (type)
+ {
+ case BlurFX::ZoomBlur:
+ break;
+
+ case BlurFX::RadialBlur:
+ case BlurFX::FrostGlass:
+ m_distanceInput->setRange(0, 10, 1);
+ m_distanceInput->setValue(3);
+ break;
+
+ case BlurFX::FarBlur:
+ m_distanceInput->setRange(0, 20, 1);
+ m_distanceInput->input()->setMaxValue(20);
+ m_distanceInput->setValue(10);
+ break;
+
+ case BlurFX::MotionBlur:
+ case BlurFX::FocusBlur:
+ m_distanceInput->setRange(0, 100, 1);
+ m_distanceInput->setValue(20);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ break;
+
+ case BlurFX::SoftenerBlur:
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ break;
+
+ case BlurFX::ShakeBlur:
+ m_distanceInput->setRange(0, 100, 1);
+ m_distanceInput->setValue(20);
+ break;
+
+ case BlurFX::SmartBlur:
+ m_distanceInput->setRange(0, 20, 1);
+ m_distanceInput->setValue(3);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ m_levelInput->setRange(0, 255, 1);
+ m_levelInput->setValue(128);
+ break;
+
+ case BlurFX::Mosaic:
+ m_distanceInput->setRange(0, 50, 1);
+ m_distanceInput->setValue(3);
+ break;
+ }
+
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void BlurFXTool::prepareEffect()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ DImg image;
+
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FocusBlur:
+ {
+ ImageIface iface(0, 0);
+ image = *iface.getOriginalImg();
+ break;
+ }
+
+ case BlurFX::FarBlur:
+ case BlurFX::MotionBlur:
+ case BlurFX::SoftenerBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::SmartBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ image = m_previewWidget->getOriginalRegionImage();
+ break;
+ }
+
+ int t = m_effectType->currentItem();
+ int d = m_distanceInput->value();
+ int l = m_levelInput->value();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new BlurFX(&image, this, t, d, l)));
+}
+
+void BlurFXTool::prepareFinal()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ int t = m_effectType->currentItem();
+ int d = m_distanceInput->value();
+ int l = m_levelInput->value();
+
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter *>(new BlurFX(iface.getOriginalImg(), this, t, d, l)));
+}
+
+void BlurFXTool::putPreviewData()
+{
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FocusBlur:
+ {
+ TQRect pRect = m_previewWidget->getOriginalImageRegionToRender();
+ DImg destImg = filter()->getTargetImage().copy(pRect);
+ m_previewWidget->setPreviewImage(destImg);
+ break;
+ }
+ case BlurFX::FarBlur:
+ case BlurFX::MotionBlur:
+ case BlurFX::SoftenerBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::SmartBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+ break;
+ }
+}
+
+void BlurFXTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Blur Effects"), filter()->getTargetImage().bits());
+}
+
+} // NameSpace DigikamBlurFXImagesPlugin
diff --git a/src/imageplugins/blurfx/blurfxtool.h b/src/imageplugins/blurfx/blurfxtool.h
new file mode 100644
index 00000000..9726e65d
--- /dev/null
+++ b/src/imageplugins/blurfx/blurfxtool.h
@@ -0,0 +1,93 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BLURFXTOOL_H
+#define BLURFXTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+class BlurFXTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ BlurFXTool(TQObject *parent);
+ ~BlurFXTool();
+
+private slots:
+
+ void slotEffectTypeChanged(int type);
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_effectTypeLabel;
+ TQLabel *m_distanceLabel;
+ TQLabel *m_levelLabel;
+
+ KDcrawIface::RComboBox *m_effectType;
+
+ KDcrawIface::RIntNumInput *m_distanceInput;
+ KDcrawIface::RIntNumInput *m_levelInput;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamBlurFXImagesPlugin
+
+#endif /* BLURFXTOOL_H */
diff --git a/src/imageplugins/blurfx/digikamimageplugin_blurfx.desktop b/src/imageplugins/blurfx/digikamimageplugin_blurfx.desktop
new file mode 100644
index 00000000..e7968a80
--- /dev/null
+++ b/src/imageplugins/blurfx/digikamimageplugin_blurfx.desktop
@@ -0,0 +1,49 @@
+[Desktop Entry]
+Name=ImagePlugin_BlurFX
+Name[bg]=Приставка за снимки - Ефекти за замъгляване
+Name[el]=ΠρόσθετοΕικόνας_ΕφέΘολώματος
+Name[fi]=Sumennus
+Name[hr]=Zamućenje
+Name[it]=PluginImmagini_EffettiDiSfocatura
+Name[nl]=Afbeeldingsplugin_Vervaageffect
+Name[sr]=Ефекти замућења
+Name[sr@Latn]=Efekti zamućenja
+Name[sv]=Insticksprogram för oskärpeeffekt
+Name[tr]=ResimEklentisi_Bulanıklaştır
+Name[xx]=xxImagePlugin_BlurFXxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Blur special effects plugin for digiKam
+Comment[bg]=Приставка на digiKam с ефекти за замъгляване на снимки
+Comment[ca]=Connector pel digiKam d'efectes especials de difuminat
+Comment[da]=Digikam plugin med specialeffekter for udviskning
+Comment[de]=digiKam-Modul zum Erzeugen von speziellen Unschärfe-Effekten
+Comment[el]=Πρόσθετο ειδικών εφέ θολώματος για το digiKam
+Comment[es]=Plugin para digiKam con efectos especiales de difusión
+Comment[et]=DigiKami spetsiaalsete hägustamisefektide plugin
+Comment[fa]=وصلۀ جلوه‌های ویژۀ محو برای digiKam
+Comment[fi]=Sumennustehosteita
+Comment[gl]=Un plugin de digiKam para efeitos especiais de borrón
+Comment[hr]=digiKam dodatak za efekt zamućenja
+Comment[is]=Íforrit fyrir digiKam sem mýkir eða afskerpir myndir
+Comment[it]=Plugin degli effetti speciali di sfocatura per digiKam
+Comment[ja]=digiKam ぼかし特殊効果プラグイン
+Comment[nds]=digiKam-Moduul för't Opstellen vun Weekteek-Effekten
+Comment[nl]=Digikam-plugin voor vervaageffect
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਬਲੱਰ (ਧੁੰਧਲਾਪਨ) ਖਾਸ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka specjalnych efektów rozmycia do programu digiKam
+Comment[pt]=Um 'plugin' do digiKam para efeitos especiais de borrão
+Comment[pt_BR]=Plugin de efeitos especiais de desfocalização
+Comment[ru]=Модуль специальных эффектов размытия для digiKam
+Comment[sk]=digiKam plugin pre špeciálne efekty rozmazania
+Comment[sr]=Прикључак ефеката замућења за digiKam
+Comment[sr@Latn]=Priključak efekata zamućenja za digiKam
+Comment[sv]=Digikam insticksprogram med specialeffekter för oskärpa
+Comment[tr]=digiKam için bulanıklaştırma eklentisi
+Comment[uk]=Втулок спеціальних ефектів розмивання для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng che mờ cho digiKam
+Comment[xx]=xxBlur special effects plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_blurfx
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/blurfx/digikamimageplugin_blurfx_ui.rc b/src/imageplugins/blurfx/digikamimageplugin_blurfx_ui.rc
new file mode 100644
index 00000000..085b4c68
--- /dev/null
+++ b/src/imageplugins/blurfx/digikamimageplugin_blurfx_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_blurfx" >
+
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_blurfx" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_blurfx" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/blurfx/imageeffect_blurfx.cpp b/src/imageplugins/blurfx/imageeffect_blurfx.cpp
new file mode 100644
index 00000000..62bcd525
--- /dev/null
+++ b/src/imageplugins/blurfx/imageeffect_blurfx.cpp
@@ -0,0 +1,388 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqslider.h>
+#include <tqimage.h>
+#include <tqcombobox.h>
+#include <tqdatetime.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <knuminput.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "blurfx.h"
+#include "imageeffect_blurfx.h"
+#include "imageeffect_blurfx.moc"
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+ImageEffect_BlurFX::ImageEffect_BlurFX(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Apply Blurring Special Effect to Photograph"),
+ "blurfx", false, false, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Blur Effects"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to apply blurring special effect "
+ "to an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pieter Z. Voloshyn", I18N_NOOP("Blurring algorithms"),
+ "pieter dot voloshyn at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 5, 1, 0, spacingHint());
+
+ m_effectTypeLabel = new TQLabel(i18n("Type:"), gboxSettings);
+
+ m_effectType = new TQComboBox( false, gboxSettings );
+ m_effectType->insertItem( i18n("Zoom Blur") );
+ m_effectType->insertItem( i18n("Radial Blur") );
+ m_effectType->insertItem( i18n("Far Blur") );
+ m_effectType->insertItem( i18n("Motion Blur") );
+ m_effectType->insertItem( i18n("Softener Blur") );
+ m_effectType->insertItem( i18n("Skake Blur") );
+ m_effectType->insertItem( i18n("Focus Blur") );
+ m_effectType->insertItem( i18n("Smart Blur") );
+ m_effectType->insertItem( i18n("Frost Glass") );
+ m_effectType->insertItem( i18n("Mosaic") );
+ TQWhatsThis::add( m_effectType, i18n("<p>Select the blurring effect to apply to the image.<p>"
+ "<b>Zoom Blur</b>: blurs the image along radial lines starting from "
+ "a specified center point. This simulates the blur of a zooming camera.<p>"
+ "<b>Radial Blur</b>: blurs the image by rotating the pixels around "
+ "the specified center point. This simulates the blur of a rotating camera.<p>"
+ "<b>Far Blur</b>: blurs the image by using far pixels. This simulates the blur "
+ "of an unfocalized camera lens.<p>"
+ "<b>Motion Blur</b>: blurs the image by moving the pixels horizontally. "
+ "This simulates the blur of a linear moving camera.<p>"
+ "<b>Softener Blur</b>: blurs the image softly in dark tones and hardly in light "
+ "tones. This gives images a dreamy and glossy soft focus effect. It's ideal "
+ "for creating romantic portraits, glamour photographs, or giving images a warm "
+ "and subtle glow.<p>"
+ "<b>Skake Blur</b>: blurs the image by skaking randomly the pixels. "
+ "This simulates the blur of a random moving camera.<p>"
+ "<b>Focus Blur</b>: blurs the image corners to reproduce the astigmatism distortion "
+ "of a lens.<p>"
+ "<b>Smart Blur</b>: finds the edges of color in your image and blurs them without "
+ "muddying the rest of the image.<p>"
+ "<b>Frost Glass</b>: blurs the image by randomly disperse light coming through "
+ "a frosted glass.<p>"
+ "<b>Mosaic</b>: divides the photograph into rectangular cells and then "
+ "recreates it by filling those cells with average pixel value."));
+ gridSettings->addMultiCellWidget(m_effectTypeLabel, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_effectType, 1, 1, 0, 1);
+
+ m_distanceLabel = new TQLabel(i18n("Distance:"), gboxSettings);
+ m_distanceInput = new KIntNumInput(gboxSettings);
+ m_distanceInput->setRange(0, 100, 1, true);
+ TQWhatsThis::add( m_distanceInput, i18n("<p>Set here the blur distance in pixels."));
+
+ gridSettings->addMultiCellWidget(m_distanceLabel, 2, 2, 0, 1);
+ gridSettings->addMultiCellWidget(m_distanceInput, 3, 3, 0, 1);
+
+ m_levelLabel = new TQLabel(i18n("Level:"), gboxSettings);
+ m_levelInput = new KIntNumInput(gboxSettings);
+ m_levelInput->setRange(0, 360, 1, true);
+ TQWhatsThis::add( m_levelInput, i18n("<p>This value controls the level to use with the current effect."));
+
+ gridSettings->addMultiCellWidget(m_levelLabel, 4, 4, 0, 1);
+ gridSettings->addMultiCellWidget(m_levelInput, 5, 5, 0, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_effectType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffectTypeChanged(int)));
+
+ connect(m_distanceInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_levelInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_BlurFX::~ImageEffect_BlurFX()
+{
+}
+
+void ImageEffect_BlurFX::renderingFinished(void)
+{
+
+ m_effectTypeLabel->setEnabled(true);
+ m_effectType->setEnabled(true);
+ m_distanceInput->setEnabled(true);
+ m_distanceLabel->setEnabled(true);
+
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FarBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ break;
+
+ case BlurFX::MotionBlur:
+ case BlurFX::FocusBlur:
+ case BlurFX::SmartBlur:
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ break;
+
+ case BlurFX::SoftenerBlur:
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ break;
+ }
+}
+
+void ImageEffect_BlurFX::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("blurfx Tool Dialog");
+ m_effectType->blockSignals(true);
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+ m_effectType->setCurrentItem(config->readNumEntry("EffectType", BlurFX::ZoomBlur));
+ m_distanceInput->setValue(config->readNumEntry("DistanceAjustment", 3));
+ m_levelInput->setValue(config->readNumEntry("LevelAjustment", 128));
+ m_effectType->blockSignals(false);
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+}
+
+void ImageEffect_BlurFX::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("blurfx Tool Dialog");
+ config->writeEntry("EffectType", m_effectType->currentItem());
+ config->writeEntry("DistanceAjustment", m_distanceInput->value());
+ config->writeEntry("LevelAjustment", m_levelInput->value());
+ config->sync();
+}
+
+void ImageEffect_BlurFX::resetValues()
+{
+ m_effectType->setCurrentItem(BlurFX::ZoomBlur);
+ slotEffectTypeChanged(BlurFX::ZoomBlur);
+}
+
+void ImageEffect_BlurFX::slotEffectTypeChanged(int type)
+{
+ m_distanceInput->setEnabled(true);
+ m_distanceLabel->setEnabled(true);
+
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+ m_distanceInput->setRange(0, 200, 1, true);
+ m_distanceInput->setValue(100);
+ m_levelInput->setRange(0, 360, 1, true);
+ m_levelInput->setValue(45);
+
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ switch (type)
+ {
+ case BlurFX::ZoomBlur:
+ break;
+
+ case BlurFX::RadialBlur:
+ case BlurFX::FrostGlass:
+ m_distanceInput->setRange(0, 10, 1, true);
+ m_distanceInput->setValue(3);
+ break;
+
+ case BlurFX::FarBlur:
+ m_distanceInput->setRange(0, 20, 1, true);
+ m_distanceInput->setMaxValue(20);
+ m_distanceInput->setValue(10);
+ break;
+
+ case BlurFX::MotionBlur:
+ case BlurFX::FocusBlur:
+ m_distanceInput->setRange(0, 100, 1, true);
+ m_distanceInput->setValue(20);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ break;
+
+ case BlurFX::SoftenerBlur:
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ break;
+
+ case BlurFX::ShakeBlur:
+ m_distanceInput->setRange(0, 100, 1, true);
+ m_distanceInput->setValue(20);
+ break;
+
+ case BlurFX::SmartBlur:
+ m_distanceInput->setRange(0, 20, 1, true);
+ m_distanceInput->setValue(3);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ m_levelInput->setRange(0, 255, 1, true);
+ m_levelInput->setValue(128);
+ break;
+
+ case BlurFX::Mosaic:
+ m_distanceInput->setRange(0, 50, 1, true);
+ m_distanceInput->setValue(3);
+ break;
+ }
+
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_BlurFX::prepareEffect()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ Digikam::DImg image;
+
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FocusBlur:
+ {
+ Digikam::ImageIface iface(0, 0);
+ image = *iface.getOriginalImg();
+ break;
+ }
+
+ case BlurFX::FarBlur:
+ case BlurFX::MotionBlur:
+ case BlurFX::SoftenerBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::SmartBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ image = m_imagePreviewWidget->getOriginalRegionImage();
+ break;
+ }
+
+ int t = m_effectType->currentItem();
+ int d = m_distanceInput->value();
+ int l = m_levelInput->value();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new BlurFX(&image, this, t, d, l));
+}
+
+void ImageEffect_BlurFX::prepareFinal()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ int t = m_effectType->currentItem();
+ int d = m_distanceInput->value();
+ int l = m_levelInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new BlurFX(iface.getOriginalImg(), this, t, d, l));
+}
+
+void ImageEffect_BlurFX::putPreviewData(void)
+{
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FocusBlur:
+ {
+ TQRect pRect = m_imagePreviewWidget->getOriginalImageRegionToRender();
+ Digikam::DImg destImg = m_threadedFilter->getTargetImage().copy(pRect);
+ m_imagePreviewWidget->setPreviewImage(destImg);
+ break;
+ }
+ case BlurFX::FarBlur:
+ case BlurFX::MotionBlur:
+ case BlurFX::SoftenerBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::SmartBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+ break;
+ }
+}
+
+void ImageEffect_BlurFX::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Blur Effects"),
+ m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamBlurFXImagesPlugin
+
diff --git a/src/imageplugins/blurfx/imageeffect_blurfx.h b/src/imageplugins/blurfx/imageeffect_blurfx.h
new file mode 100644
index 00000000..e2517d4f
--- /dev/null
+++ b/src/imageplugins/blurfx/imageeffect_blurfx.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_BLURFX_H
+#define IMAGEEFFECT_BLURFX_H
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+class TQComboBox;
+class TQLabel;
+
+class KIntNumInput;
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+class ImageEffect_BlurFX : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_BlurFX(TQWidget *parent);
+ ~ImageEffect_BlurFX();
+
+private slots:
+
+ void slotEffectTypeChanged(int type);
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQComboBox *m_effectType;
+
+ TQLabel *m_effectTypeLabel;
+ TQLabel *m_distanceLabel;
+ TQLabel *m_levelLabel;
+
+ KIntNumInput *m_distanceInput;
+ KIntNumInput *m_levelInput;
+};
+
+} // NameSpace DigikamBlurFXImagesPlugin
+
+#endif /* IMAGEEFFECT_BLURFX_H */
diff --git a/src/imageplugins/blurfx/imageplugin_blurfx.cpp b/src/imageplugins/blurfx/imageplugin_blurfx.cpp
new file mode 100644
index 00000000..3bbd05e0
--- /dev/null
+++ b/src/imageplugins/blurfx/imageplugin_blurfx.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "blurfxtool.h"
+#include "imageplugin_blurfx.h"
+#include "imageplugin_blurfx.moc"
+
+using namespace DigikamBlurFXImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_blurfx,
+ KGenericFactory<ImagePlugin_BlurFX>("digikamimageplugin_blurfx"));
+
+ImagePlugin_BlurFX::ImagePlugin_BlurFX(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_BlurFX")
+{
+ m_blurfxAction = new TDEAction(i18n("Blur Effects..."), "blurfx", 0,
+ this, TQ_SLOT(slotBlurFX()),
+ actionCollection(), "imageplugin_blurfx");
+
+ setXMLFile( "digikamimageplugin_blurfx_ui.rc" );
+
+ DDebug() << "ImagePlugin_BlurFX plugin loaded" << endl;
+}
+
+ImagePlugin_BlurFX::~ImagePlugin_BlurFX()
+{
+}
+
+void ImagePlugin_BlurFX::setEnabledActions(bool enable)
+{
+ m_blurfxAction->setEnabled(enable);
+}
+
+void ImagePlugin_BlurFX::slotBlurFX()
+{
+ BlurFXTool *tool = new BlurFXTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/blurfx/imageplugin_blurfx.h b/src/imageplugins/blurfx/imageplugin_blurfx.h
new file mode 100644
index 00000000..13df6534
--- /dev/null
+++ b/src/imageplugins/blurfx/imageplugin_blurfx.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_BLURFX_H
+#define IMAGEPLUGIN_BLURFX_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_BlurFX : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_BlurFX(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_BlurFX();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotBlurFX();
+
+private:
+
+ TDEAction *m_blurfxAction;
+};
+
+#endif /* IMAGEPLUGIN_BLURFX_H */