1 /* 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org> 4 * Copyright (C) 2005 Eric Seidel <eric (at) webkit.org> 5 * Copyright (C) 2009 Dirk Schulze <krit (at) 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 * along 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 "Filter.h" 30 #include "GraphicsContext.h" 31 #include "RenderTreeAsText.h" 32 #include "TextStream.h" 33 34 #include <wtf/ByteArray.h> 35 #include <wtf/MathExtras.h> 36 37 namespace WebCore { 38 39 typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&); 40 41 FEComponentTransfer::FEComponentTransfer(Filter* filter, const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, 42 const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc) 43 : FilterEffect(filter) 44 , m_redFunc(redFunc) 45 , m_greenFunc(greenFunc) 46 , m_blueFunc(blueFunc) 47 , m_alphaFunc(alphaFunc) 48 { 49 } 50 51 PassRefPtr<FEComponentTransfer> FEComponentTransfer::create(Filter* filter, const ComponentTransferFunction& redFunc, 52 const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc) 53 { 54 return adoptRef(new FEComponentTransfer(filter, redFunc, greenFunc, blueFunc, alphaFunc)); 55 } 56 57 ComponentTransferFunction FEComponentTransfer::redFunction() const 58 { 59 return m_redFunc; 60 } 61 62 void FEComponentTransfer::setRedFunction(const ComponentTransferFunction& func) 63 { 64 m_redFunc = func; 65 } 66 67 ComponentTransferFunction FEComponentTransfer::greenFunction() const 68 { 69 return m_greenFunc; 70 } 71 72 void FEComponentTransfer::setGreenFunction(const ComponentTransferFunction& func) 73 { 74 m_greenFunc = func; 75 } 76 77 ComponentTransferFunction FEComponentTransfer::blueFunction() const 78 { 79 return m_blueFunc; 80 } 81 82 void FEComponentTransfer::setBlueFunction(const ComponentTransferFunction& func) 83 { 84 m_blueFunc = func; 85 } 86 87 ComponentTransferFunction FEComponentTransfer::alphaFunction() const 88 { 89 return m_alphaFunc; 90 } 91 92 void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func) 93 { 94 m_alphaFunc = func; 95 } 96 97 static void identity(unsigned char*, const ComponentTransferFunction&) 98 { 99 } 100 101 static void table(unsigned char* values, const ComponentTransferFunction& transferFunction) 102 { 103 const Vector<float>& tableValues = transferFunction.tableValues; 104 unsigned n = tableValues.size(); 105 if (n < 1) 106 return; 107 for (unsigned i = 0; i < 256; ++i) { 108 double c = i / 255.0; 109 unsigned k = static_cast<unsigned>(c * (n - 1)); 110 double v1 = tableValues[k]; 111 double v2 = tableValues[std::min((k + 1), (n - 1))]; 112 double val = 255.0 * (v1 + (c * (n - 1) - k) * (v2 - v1)); 113 val = std::max(0.0, std::min(255.0, val)); 114 values[i] = static_cast<unsigned char>(val); 115 } 116 } 117 118 static void discrete(unsigned char* values, const ComponentTransferFunction& transferFunction) 119 { 120 const Vector<float>& tableValues = transferFunction.tableValues; 121 unsigned n = tableValues.size(); 122 if (n < 1) 123 return; 124 for (unsigned i = 0; i < 256; ++i) { 125 unsigned k = static_cast<unsigned>((i * n) / 255.0); 126 k = std::min(k, n - 1); 127 double val = 255 * tableValues[k]; 128 val = std::max(0.0, std::min(255.0, val)); 129 values[i] = static_cast<unsigned char>(val); 130 } 131 } 132 133 static void linear(unsigned char* values, const ComponentTransferFunction& transferFunction) 134 { 135 for (unsigned i = 0; i < 256; ++i) { 136 double val = transferFunction.slope * i + 255 * transferFunction.intercept; 137 val = std::max(0.0, std::min(255.0, val)); 138 values[i] = static_cast<unsigned char>(val); 139 } 140 } 141 142 static void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction) 143 { 144 for (unsigned i = 0; i < 256; ++i) { 145 double exponent = transferFunction.exponent; // RCVT doesn't like passing a double and a float to pow, so promote this to double 146 double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), exponent) + transferFunction.offset); 147 val = std::max(0.0, std::min(255.0, val)); 148 values[i] = static_cast<unsigned char>(val); 149 } 150 } 151 152 void FEComponentTransfer::apply() 153 { 154 if (hasResult()) 155 return; 156 FilterEffect* in = inputEffect(0); 157 in->apply(); 158 if (!in->hasResult()) 159 return; 160 161 ByteArray* pixelArray = createUnmultipliedImageResult(); 162 if (!pixelArray) 163 return; 164 165 unsigned char rValues[256], gValues[256], bValues[256], aValues[256]; 166 for (unsigned i = 0; i < 256; ++i) 167 rValues[i] = gValues[i] = bValues[i] = aValues[i] = i; 168 unsigned char* tables[] = { rValues, gValues, bValues, aValues }; 169 ComponentTransferFunction transferFunction[] = {m_redFunc, m_greenFunc, m_blueFunc, m_alphaFunc}; 170 TransferType callEffect[] = {identity, identity, table, discrete, linear, gamma}; 171 172 for (unsigned channel = 0; channel < 4; channel++) 173 (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]); 174 175 IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); 176 in->copyUnmultipliedImage(pixelArray, drawingRect); 177 178 unsigned pixelArrayLength = pixelArray->length(); 179 for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) { 180 for (unsigned channel = 0; channel < 4; ++channel) { 181 unsigned char c = pixelArray->get(pixelOffset + channel); 182 pixelArray->set(pixelOffset + channel, tables[channel][c]); 183 } 184 } 185 } 186 187 void FEComponentTransfer::dump() 188 { 189 } 190 191 static TextStream& operator<<(TextStream& ts, const ComponentTransferType& type) 192 { 193 switch (type) { 194 case FECOMPONENTTRANSFER_TYPE_UNKNOWN: 195 ts << "UNKNOWN"; 196 break; 197 case FECOMPONENTTRANSFER_TYPE_IDENTITY: 198 ts << "IDENTITY"; 199 break; 200 case FECOMPONENTTRANSFER_TYPE_TABLE: 201 ts << "TABLE"; 202 break; 203 case FECOMPONENTTRANSFER_TYPE_DISCRETE: 204 ts << "DISCRETE"; 205 break; 206 case FECOMPONENTTRANSFER_TYPE_LINEAR: 207 ts << "LINEAR"; 208 break; 209 case FECOMPONENTTRANSFER_TYPE_GAMMA: 210 ts << "GAMMA"; 211 break; 212 } 213 return ts; 214 } 215 216 static TextStream& operator<<(TextStream& ts, const ComponentTransferFunction& function) 217 { 218 ts << "type=\"" << function.type 219 << "\" slope=\"" << function.slope 220 << "\" intercept=\"" << function.intercept 221 << "\" amplitude=\"" << function.amplitude 222 << "\" exponent=\"" << function.exponent 223 << "\" offset=\"" << function.offset << "\""; 224 return ts; 225 } 226 227 TextStream& FEComponentTransfer::externalRepresentation(TextStream& ts, int indent) const 228 { 229 writeIndent(ts, indent); 230 ts << "[feComponentTransfer"; 231 FilterEffect::externalRepresentation(ts); 232 ts << " \n"; 233 writeIndent(ts, indent + 2); 234 ts << "{red: " << m_redFunc << "}\n"; 235 writeIndent(ts, indent + 2); 236 ts << "{green: " << m_greenFunc << "}\n"; 237 writeIndent(ts, indent + 2); 238 ts << "{blue: " << m_blueFunc << "}\n"; 239 writeIndent(ts, indent + 2); 240 ts << "{alpha: " << m_alphaFunc << "}]\n"; 241 inputEffect(0)->externalRepresentation(ts, indent + 1); 242 return ts; 243 } 244 245 } // namespace WebCore 246 247 #endif // ENABLE(FILTERS) 248