• 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     Copyright (C) Research In Motion Limited 2010. All rights reserved.
7 
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Library General Public
10     License as published by the Free Software Foundation; either
11     version 2 of the License, or (at your option) any later version.
12 
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Library General Public License for more details.
17 
18     You should have received a copy of the GNU Library General Public License
19     aint with this library; see the file COPYING.LIB.  If not, write to
20     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21     Boston, MA 02110-1301, USA.
22 */
23 
24 #include "config.h"
25 
26 #if ENABLE(FILTERS)
27 #include "FEComponentTransfer.h"
28 
29 #include "CanvasPixelArray.h"
30 #include "Filter.h"
31 #include "GraphicsContext.h"
32 #include "ImageData.h"
33 #include <math.h>
34 
35 namespace WebCore {
36 
37 typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&);
38 
FEComponentTransfer(FilterEffect * in,const ComponentTransferFunction & redFunc,const ComponentTransferFunction & greenFunc,const ComponentTransferFunction & blueFunc,const ComponentTransferFunction & alphaFunc)39 FEComponentTransfer::FEComponentTransfer(FilterEffect* in, const ComponentTransferFunction& redFunc,
40     const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc)
41     : FilterEffect()
42     , m_in(in)
43     , m_redFunc(redFunc)
44     , m_greenFunc(greenFunc)
45     , m_blueFunc(blueFunc)
46     , m_alphaFunc(alphaFunc)
47 {
48 }
49 
create(FilterEffect * in,const ComponentTransferFunction & redFunc,const ComponentTransferFunction & greenFunc,const ComponentTransferFunction & blueFunc,const ComponentTransferFunction & alphaFunc)50 PassRefPtr<FEComponentTransfer> FEComponentTransfer::create(FilterEffect* in, const ComponentTransferFunction& redFunc,
51     const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc)
52 {
53     return adoptRef(new FEComponentTransfer(in, redFunc, greenFunc, blueFunc, alphaFunc));
54 }
55 
redFunction() const56 ComponentTransferFunction FEComponentTransfer::redFunction() const
57 {
58     return m_redFunc;
59 }
60 
setRedFunction(const ComponentTransferFunction & func)61 void FEComponentTransfer::setRedFunction(const ComponentTransferFunction& func)
62 {
63     m_redFunc = func;
64 }
65 
greenFunction() const66 ComponentTransferFunction FEComponentTransfer::greenFunction() const
67 {
68     return m_greenFunc;
69 }
70 
setGreenFunction(const ComponentTransferFunction & func)71 void FEComponentTransfer::setGreenFunction(const ComponentTransferFunction& func)
72 {
73     m_greenFunc = func;
74 }
75 
blueFunction() const76 ComponentTransferFunction FEComponentTransfer::blueFunction() const
77 {
78     return m_blueFunc;
79 }
80 
setBlueFunction(const ComponentTransferFunction & func)81 void FEComponentTransfer::setBlueFunction(const ComponentTransferFunction& func)
82 {
83     m_blueFunc = func;
84 }
85 
alphaFunction() const86 ComponentTransferFunction FEComponentTransfer::alphaFunction() const
87 {
88     return m_alphaFunc;
89 }
90 
setAlphaFunction(const ComponentTransferFunction & func)91 void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func)
92 {
93     m_alphaFunc = func;
94 }
95 
identity(unsigned char *,const ComponentTransferFunction &)96 static void identity(unsigned char*, const ComponentTransferFunction&)
97 {
98 }
99 
table(unsigned char * values,const ComponentTransferFunction & transferFunction)100 static void table(unsigned char* values, const ComponentTransferFunction& transferFunction)
101 {
102     const Vector<float>& tableValues = transferFunction.tableValues;
103     unsigned n = tableValues.size();
104     if (n < 1)
105         return;
106     for (unsigned i = 0; i < 256; ++i) {
107         double c = i / 255.0;
108         unsigned k = static_cast<unsigned>(c * (n - 1));
109         double v1 = tableValues[k];
110         double v2 = tableValues[std::min((k + 1), (n - 1))];
111         double val = 255.0 * (v1 + (c * (n - 1) - k) * (v2 - v1));
112         val = std::max(0.0, std::min(255.0, val));
113         values[i] = static_cast<unsigned char>(val);
114     }
115 }
116 
discrete(unsigned char * values,const ComponentTransferFunction & transferFunction)117 static void discrete(unsigned char* values, const ComponentTransferFunction& transferFunction)
118 {
119     const Vector<float>& tableValues = transferFunction.tableValues;
120     unsigned n = tableValues.size();
121     if (n < 1)
122         return;
123     for (unsigned i = 0; i < 256; ++i) {
124         unsigned k = static_cast<unsigned>((i * n) / 255.0);
125         k = std::min(k, n - 1);
126         double val = 255 * tableValues[k];
127         val = std::max(0.0, std::min(255.0, val));
128         values[i] = static_cast<unsigned char>(val);
129     }
130 }
131 
linear(unsigned char * values,const ComponentTransferFunction & transferFunction)132 static void linear(unsigned char* values, const ComponentTransferFunction& transferFunction)
133 {
134     for (unsigned i = 0; i < 256; ++i) {
135         double val = transferFunction.slope * i + 255 * transferFunction.intercept;
136         val = std::max(0.0, std::min(255.0, val));
137         values[i] = static_cast<unsigned char>(val);
138     }
139 }
140 
gamma(unsigned char * values,const ComponentTransferFunction & transferFunction)141 static void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction)
142 {
143     for (unsigned i = 0; i < 256; ++i) {
144         double exponent = transferFunction.exponent; // RCVT doesn't like passing a double and a float to pow, so promote this to double
145         double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), exponent) + transferFunction.offset);
146         val = std::max(0.0, std::min(255.0, val));
147         values[i] = static_cast<unsigned char>(val);
148     }
149 }
150 
apply(Filter * filter)151 void FEComponentTransfer::apply(Filter* filter)
152 {
153     m_in->apply(filter);
154     if (!m_in->resultImage())
155         return;
156 
157     if (!getEffectContext())
158         return;
159 
160     unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
161     for (unsigned i = 0; i < 256; ++i)
162         rValues[i] = gValues[i] = bValues[i] = aValues[i] = i;
163     unsigned char* tables[] = { rValues, gValues, bValues, aValues };
164     ComponentTransferFunction transferFunction[] = {m_redFunc, m_greenFunc, m_blueFunc, m_alphaFunc};
165     TransferType callEffect[] = {identity, identity, table, discrete, linear, gamma};
166 
167     for (unsigned channel = 0; channel < 4; channel++)
168         (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
169 
170     IntRect drawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
171     RefPtr<ImageData> imageData(m_in->resultImage()->getUnmultipliedImageData(drawingRect));
172     CanvasPixelArray* srcPixelArray(imageData->data());
173 
174     for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) {
175         for (unsigned channel = 0; channel < 4; ++channel) {
176             unsigned char c = srcPixelArray->get(pixelOffset + channel);
177             imageData->data()->set(pixelOffset + channel, tables[channel][c]);
178         }
179     }
180 
181     resultImage()->putUnmultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
182 }
183 
dump()184 void FEComponentTransfer::dump()
185 {
186 }
187 
188 } // namespace WebCore
189 
190 #endif // ENABLE(FILTERS)
191