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