• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3                   2004, 2005 Rob Buis <buis@kde.org>
4                   2005 Eric Seidel <eric@webkit.org>
5                   2009 Dirk Schulze <krit@webkit.org>
6 
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11 
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Library General Public License for more details.
16 
17     You should have received a copy of the GNU Library General Public License
18     aint with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20     Boston, MA 02110-1301, USA.
21 */
22 
23 #include "config.h"
24 
25 #if ENABLE(FILTERS)
26 #include "FEGaussianBlur.h"
27 
28 #include "CanvasPixelArray.h"
29 #include "Filter.h"
30 #include "GraphicsContext.h"
31 #include "ImageData.h"
32 #include <math.h>
33 #include <wtf/MathExtras.h>
34 
35 using std::max;
36 
37 namespace WebCore {
38 
FEGaussianBlur(FilterEffect * in,const float & x,const float & y)39 FEGaussianBlur::FEGaussianBlur(FilterEffect* in, const float& x, const float& y)
40     : FilterEffect()
41     , m_in(in)
42     , m_x(x)
43     , m_y(y)
44 {
45 }
46 
create(FilterEffect * in,const float & x,const float & y)47 PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(FilterEffect* in, const float& x, const float& y)
48 {
49     return adoptRef(new FEGaussianBlur(in, x, y));
50 }
51 
stdDeviationX() const52 float FEGaussianBlur::stdDeviationX() const
53 {
54     return m_x;
55 }
56 
setStdDeviationX(float x)57 void FEGaussianBlur::setStdDeviationX(float x)
58 {
59     m_x = x;
60 }
61 
stdDeviationY() const62 float FEGaussianBlur::stdDeviationY() const
63 {
64     return m_y;
65 }
66 
setStdDeviationY(float y)67 void FEGaussianBlur::setStdDeviationY(float y)
68 {
69     m_y = y;
70 }
71 
boxBlur(CanvasPixelArray * & srcPixelArray,CanvasPixelArray * & dstPixelArray,unsigned dx,int stride,int strideLine,int effectWidth,int effectHeight,bool alphaImage)72 static void boxBlur(CanvasPixelArray*& srcPixelArray, CanvasPixelArray*& dstPixelArray,
73                  unsigned dx, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage)
74 {
75     int dxLeft = dx / 2;
76     int dxRight = dx - dxLeft;
77 
78     for (int y = 0; y < effectHeight; ++y) {
79         int line = y * strideLine;
80         for (int channel = 3; channel >= 0; --channel) {
81             int sum = 0;
82             // Fill the kernel
83             int maxKernelSize = std::min(dxRight, effectWidth);
84             for (int i = 0; i < maxKernelSize; ++i)
85                 sum += srcPixelArray->get(line + i * stride + channel);
86 
87             // Blurring
88             for (int x = 0; x < effectWidth; ++x) {
89                 int pixelByteOffset = line + x * stride + channel;
90                 dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
91                 if (x >= dxLeft)
92                     sum -= srcPixelArray->get(pixelByteOffset - dxLeft * stride);
93                 if (x + dxRight < effectWidth)
94                     sum += srcPixelArray->get(pixelByteOffset + dxRight * stride);
95             }
96             if (alphaImage) // Source image is black, it just has different alpha values
97                 break;
98         }
99     }
100 }
101 
apply(Filter * filter)102 void FEGaussianBlur::apply(Filter* filter)
103 {
104     m_in->apply(filter);
105     if (!m_in->resultImage())
106         return;
107 
108     if (!getEffectContext())
109         return;
110 
111     setIsAlphaImage(m_in->isAlphaImage());
112 
113     if (m_x == 0 || m_y == 0)
114         return;
115 
116     unsigned sdx = static_cast<unsigned>(floor(m_x * filter->filterResolution().width() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
117     unsigned sdy = static_cast<unsigned>(floor(m_y * filter->filterResolution().height() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
118     sdx = max(sdx, static_cast<unsigned>(1));
119     sdy = max(sdy, static_cast<unsigned>(1));
120 
121     IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
122     RefPtr<ImageData> srcImageData(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect));
123     CanvasPixelArray* srcPixelArray(srcImageData->data());
124 
125     IntRect imageRect(IntPoint(), resultImage()->size());
126     RefPtr<ImageData> tmpImageData = ImageData::create(imageRect.width(), imageRect.height());
127     CanvasPixelArray* tmpPixelArray(tmpImageData->data());
128 
129     int stride = 4 * imageRect.width();
130     for (int i = 0; i < 3; ++i) {
131         boxBlur(srcPixelArray, tmpPixelArray, sdx, 4, stride, imageRect.width(), imageRect.height(), isAlphaImage());
132         boxBlur(tmpPixelArray, srcPixelArray, sdy, stride, 4, imageRect.height(), imageRect.width(), isAlphaImage());
133     }
134 
135     resultImage()->putPremultipliedImageData(srcImageData.get(), imageRect, IntPoint());
136 }
137 
dump()138 void FEGaussianBlur::dump()
139 {
140 }
141 
142 } // namespace WebCore
143 
144 #endif // ENABLE(FILTERS)
145