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