Home | History | Annotate | Download | only in filters
      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