1 /* 2 Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 3 2004, 2005 Rob Buis <buis (at) kde.org> 4 2005 Eric Seidel <eric (at) webkit.org> 5 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 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 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 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 56 ComponentTransferFunction FEComponentTransfer::redFunction() const 57 { 58 return m_redFunc; 59 } 60 61 void FEComponentTransfer::setRedFunction(const ComponentTransferFunction& func) 62 { 63 m_redFunc = func; 64 } 65 66 ComponentTransferFunction FEComponentTransfer::greenFunction() const 67 { 68 return m_greenFunc; 69 } 70 71 void FEComponentTransfer::setGreenFunction(const ComponentTransferFunction& func) 72 { 73 m_greenFunc = func; 74 } 75 76 ComponentTransferFunction FEComponentTransfer::blueFunction() const 77 { 78 return m_blueFunc; 79 } 80 81 void FEComponentTransfer::setBlueFunction(const ComponentTransferFunction& func) 82 { 83 m_blueFunc = func; 84 } 85 86 ComponentTransferFunction FEComponentTransfer::alphaFunction() const 87 { 88 return m_alphaFunc; 89 } 90 91 void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func) 92 { 93 m_alphaFunc = func; 94 } 95 96 static void identity(unsigned char*, const ComponentTransferFunction&) 97 { 98 } 99 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 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 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 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 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 184 void FEComponentTransfer::dump() 185 { 186 } 187 188 } // namespace WebCore 189 190 #endif // ENABLE(FILTERS) 191