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 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 "FEColorMatrix.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 namespace WebCore { 36 37 FEColorMatrix::FEColorMatrix(FilterEffect* in, ColorMatrixType type, const Vector<float>& values) 38 : FilterEffect() 39 , m_in(in) 40 , m_type(type) 41 , m_values(values) 42 { 43 } 44 45 PassRefPtr<FEColorMatrix> FEColorMatrix::create(FilterEffect* in, ColorMatrixType type, const Vector<float>& values) 46 { 47 return adoptRef(new FEColorMatrix(in, type, values)); 48 } 49 50 ColorMatrixType FEColorMatrix::type() const 51 { 52 return m_type; 53 } 54 55 void FEColorMatrix::setType(ColorMatrixType type) 56 { 57 m_type = type; 58 } 59 60 const Vector<float>& FEColorMatrix::values() const 61 { 62 return m_values; 63 } 64 65 void FEColorMatrix::setValues(const Vector<float> &values) 66 { 67 m_values = values; 68 } 69 70 inline void matrix(double& red, double& green, double& blue, double& alpha, const Vector<float>& values) 71 { 72 double r = values[0] * red + values[1] * green + values[2] * blue + values[3] * alpha; 73 double g = values[5] * red + values[6] * green + values[7] * blue + values[8] * alpha; 74 double b = values[10] * red + values[11] * green + values[12] * blue + values[13] * alpha; 75 double a = values[15] * red + values[16] * green + values[17] * blue + values[18] * alpha; 76 77 red = r; 78 green = g; 79 blue = b; 80 alpha = a; 81 } 82 83 inline void saturate(double& red, double& green, double& blue, const float& s) 84 { 85 double r = (0.213 + 0.787 * s) * red + (0.715 - 0.715 * s) * green + (0.072 - 0.072 * s) * blue; 86 double g = (0.213 - 0.213 * s) * red + (0.715 + 0.285 * s) * green + (0.072 - 0.072 * s) * blue; 87 double b = (0.213 - 0.213 * s) * red + (0.715 - 0.715 * s) * green + (0.072 + 0.928 * s) * blue; 88 89 red = r; 90 green = g; 91 blue = b; 92 } 93 94 inline void huerotate(double& red, double& green, double& blue, const float& hue) 95 { 96 double cosHue = cos(hue * piDouble / 180); 97 double sinHue = sin(hue * piDouble / 180); 98 double r = red * (0.213 + cosHue * 0.787 - sinHue * 0.213) + 99 green * (0.715 - cosHue * 0.715 - sinHue * 0.715) + 100 blue * (0.072 - cosHue * 0.072 + sinHue * 0.928); 101 double g = red * (0.213 - cosHue * 0.213 + sinHue * 0.143) + 102 green * (0.715 + cosHue * 0.285 + sinHue * 0.140) + 103 blue * (0.072 - cosHue * 0.072 - sinHue * 0.283); 104 double b = red * (0.213 - cosHue * 0.213 - sinHue * 0.787) + 105 green * (0.715 - cosHue * 0.715 + sinHue * 0.715) + 106 blue * (0.072 + cosHue * 0.928 + sinHue * 0.072); 107 108 red = r; 109 green = g; 110 blue = b; 111 } 112 113 inline void luminance(double& red, double& green, double& blue, double& alpha) 114 { 115 alpha = 0.2125 * red + 0.7154 * green + 0.0721 * blue; 116 red = 0.; 117 green = 0.; 118 blue = 0.; 119 } 120 121 template<ColorMatrixType filterType> 122 void effectType(const PassRefPtr<CanvasPixelArray>& srcPixelArray, PassRefPtr<ImageData>& imageData, const Vector<float>& values) 123 { 124 for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset++) { 125 unsigned pixelByteOffset = pixelOffset * 4; 126 127 unsigned char r = 0, g = 0, b = 0, a = 0; 128 srcPixelArray->get(pixelByteOffset, r); 129 srcPixelArray->get(pixelByteOffset + 1, g); 130 srcPixelArray->get(pixelByteOffset + 2, b); 131 srcPixelArray->get(pixelByteOffset + 3, a); 132 133 double red = r, green = g, blue = b, alpha = a; 134 135 switch (filterType) { 136 case FECOLORMATRIX_TYPE_MATRIX: 137 matrix(red, green, blue, alpha, values); 138 break; 139 case FECOLORMATRIX_TYPE_SATURATE: 140 saturate(red, green, blue, values[0]); 141 break; 142 case FECOLORMATRIX_TYPE_HUEROTATE: 143 huerotate(red, green, blue, values[0]); 144 break; 145 case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: 146 luminance(red, green, blue, alpha); 147 break; 148 } 149 150 imageData->data()->set(pixelByteOffset, red); 151 imageData->data()->set(pixelByteOffset + 1, green); 152 imageData->data()->set(pixelByteOffset + 2, blue); 153 imageData->data()->set(pixelByteOffset + 3, alpha); 154 } 155 } 156 157 void FEColorMatrix::apply(Filter* filter) 158 { 159 m_in->apply(filter); 160 if (!m_in->resultImage()) 161 return; 162 163 GraphicsContext* filterContext = getEffectContext(); 164 if (!filterContext) 165 return; 166 167 filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); 168 169 IntRect imageRect(IntPoint(), resultImage()->size()); 170 PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect)); 171 PassRefPtr<CanvasPixelArray> srcPixelArray(imageData->data()); 172 173 switch (m_type) { 174 case FECOLORMATRIX_TYPE_UNKNOWN: 175 break; 176 case FECOLORMATRIX_TYPE_MATRIX: 177 effectType<FECOLORMATRIX_TYPE_MATRIX>(srcPixelArray, imageData, m_values); 178 break; 179 case FECOLORMATRIX_TYPE_SATURATE: 180 effectType<FECOLORMATRIX_TYPE_SATURATE>(srcPixelArray, imageData, m_values); 181 break; 182 case FECOLORMATRIX_TYPE_HUEROTATE: 183 effectType<FECOLORMATRIX_TYPE_HUEROTATE>(srcPixelArray, imageData, m_values); 184 break; 185 case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: 186 effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(srcPixelArray, imageData, m_values); 187 setIsAlphaImage(true); 188 break; 189 } 190 191 resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint()); 192 } 193 194 void FEColorMatrix::dump() 195 { 196 } 197 198 } // namespace WebCore 199 200 #endif // ENABLE(FILTERS) 201