Beispiel #1
0
void FEBlend::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);
    FilterEffect* in2 = inputEffect(1);

    ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
    ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);

    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return;

    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);

    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);

    unsigned pixelArrayLength = srcPixelArrayA->length();
    ASSERT(pixelArrayLength == srcPixelArrayB->length());
    for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
        unsigned char alphaA = srcPixelArrayA->item(pixelOffset + 3);
        unsigned char alphaB = srcPixelArrayB->item(pixelOffset + 3);
        for (unsigned channel = 0; channel < 3; ++channel) {
            unsigned char colorA = srcPixelArrayA->item(pixelOffset + channel);
            unsigned char colorB = srcPixelArrayB->item(pixelOffset + channel);
            unsigned char result;

            switch (m_mode) {
            case FEBLEND_MODE_NORMAL:
                result = normal(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_MULTIPLY:
                result = multiply(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_SCREEN:
                result = screen(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_DARKEN:
                result = darken(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_LIGHTEN:
                result = lighten(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_UNKNOWN:
            default:
                result = 0;
                break;
            }

            dstPixelArray->set(pixelOffset + channel, result);
        }
        unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
        dstPixelArray->set(pixelOffset + 3, alphaR);
    }
}
void FEDisplacementMap::applySoftware()
{
    FilterEffect* in = inputEffect(0);
    FilterEffect* in2 = inputEffect(1);

    ASSERT(m_xChannelSelector != CHANNEL_UNKNOWN);
    ASSERT(m_yChannelSelector != CHANNEL_UNKNOWN);

    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return;

    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);

    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asUnmultipliedImage(effectBDrawingRect);

    ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());

    Filter* filter = this->filter();
    IntSize paintSize = absolutePaintRect().size();
    float scaleX = filter->applyHorizontalScale(m_scale);
    float scaleY = filter->applyVerticalScale(m_scale);
    float scaleForColorX = scaleX / 255.0;
    float scaleForColorY = scaleY / 255.0;
    float scaledOffsetX = 0.5 - scaleX * 0.5;
    float scaledOffsetY = 0.5 - scaleY * 0.5;
    int stride = paintSize.width() * 4;
    for (int y = 0; y < paintSize.height(); ++y) {
        int line = y * stride;
        for (int x = 0; x < paintSize.width(); ++x) {
            int dstIndex = line + x * 4;
            int srcX = x + static_cast<int>(scaleForColorX * srcPixelArrayB->item(dstIndex + m_xChannelSelector - 1) + scaledOffsetX);
            int srcY = y + static_cast<int>(scaleForColorY * srcPixelArrayB->item(dstIndex + m_yChannelSelector - 1) + scaledOffsetY);
            for (unsigned channel = 0; channel < 4; ++channel) {
                if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height()) {
                    dstPixelArray->set(dstIndex + channel, static_cast<unsigned char>(0));
                } else {
                    unsigned char pixelValue = srcPixelArrayA->item(srcY * stride + srcX * 4 + channel);
                    dstPixelArray->set(dstIndex + channel, pixelValue);
                }
            }
        }
    }
}
Beispiel #3
0
void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart, int yEnd)
{
    Uint8ClampedArray* srcPixelArray = paintingData->srcPixelArray;
    Uint8ClampedArray* dstPixelArray = paintingData->dstPixelArray;
    const int width = paintingData->width;
    const int height = paintingData->height;
    const int effectWidth = width * 4;
    const int radiusX = paintingData->radiusX;
    const int radiusY = paintingData->radiusY;

    Vector<unsigned char> extrema;
    for (int y = yStart; y < yEnd; ++y) {
        int extremaStartY = std::max(0, y - radiusY);
        int extremaEndY = std::min(height - 1, y + radiusY);
        for (unsigned int clrChannel = 0; clrChannel < 4; ++clrChannel) {
            extrema.clear();
            // Compute extremas for each columns
            for (int x = 0; x <= radiusX; ++x) {
                unsigned char columnExtrema = srcPixelArray->item(extremaStartY * effectWidth + 4 * x + clrChannel);
                for (int eY = extremaStartY + 1; eY < extremaEndY; ++eY) {
                    unsigned char pixel = srcPixelArray->item(eY * effectWidth + 4 * x + clrChannel);
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema)
                        || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema)) {
                        columnExtrema = pixel;
                    }
                }

                extrema.append(columnExtrema);
            }

            // Kernel is filled, get extrema of next column
            for (int x = 0; x < width; ++x) {
                const int endX = std::min(x + radiusX, width - 1);
                unsigned char columnExtrema = srcPixelArray->item(extremaStartY * effectWidth + endX * 4 + clrChannel);
                for (int i = extremaStartY + 1; i <= extremaEndY; ++i) {
                    unsigned char pixel = srcPixelArray->item(i * effectWidth + endX * 4 + clrChannel);
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema)
                        || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema))
                        columnExtrema = pixel;
                }
                if (x - radiusX >= 0)
                    extrema.remove(0);
                if (x + radiusX <= width)
                    extrema.append(columnExtrema);

                unsigned char entireExtrema = extrema[0];
                for (unsigned kernelIndex = 1; kernelIndex < extrema.size(); ++kernelIndex) {
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && extrema[kernelIndex] <= entireExtrema)
                        || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && extrema[kernelIndex] >= entireExtrema))
                        entireExtrema = extrema[kernelIndex];
                }
                dstPixelArray->set(y * effectWidth + 4 * x + clrChannel, entireExtrema);
            }
        }
    }
}
Beispiel #4
0
void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart, int yEnd)
{
    Uint8ClampedArray* srcPixelArray = paintingData->srcPixelArray;
    Uint8ClampedArray* dstPixelArray = paintingData->dstPixelArray;
    const int radiusX = paintingData->radiusX;
    const int radiusY = paintingData->radiusY;
    const int width = paintingData->width;
    const int height = paintingData->height;

    ASSERT(radiusX <= width || radiusY <= height);
    ASSERT(yStart >= 0 && yEnd <= height && yStart < yEnd);

    Vector<unsigned char> extrema;
    for (int y = yStart; y < yEnd; ++y) {
        int yStartExtrema = std::max(0, y - radiusY);
        int yEndExtrema = std::min(height - 1, y + radiusY);

        for (unsigned colorChannel = 0; colorChannel < 4; ++colorChannel) {
            extrema.clear();
            // Compute extremas for each columns
            for (int x = 0; x < radiusX; ++x)
                extrema.append(columnExtremum(srcPixelArray, x, yStartExtrema, yEndExtrema, width, colorChannel, m_type));

            // Kernel is filled, get extrema of next column
            for (int x = 0; x < width; ++x) {
                if (x < width - radiusX) {
                    int xEnd = std::min(x + radiusX, width - 1);
                    extrema.append(columnExtremum(srcPixelArray, xEnd, yStartExtrema, yEndExtrema + 1, width, colorChannel, m_type));
                }

                if (x > radiusX)
                    extrema.remove(0);

                // The extrema original size = radiusX.
                // Number of new addition = width - radiusX.
                // Number of removals = width - radiusX - 1.
                ASSERT(extrema.size() >= static_cast<size_t>(radiusX + 1));
                dstPixelArray->set(pixelArrayIndex(x, y, width, colorChannel), kernelExtremum(extrema, m_type));
            }
        }
    }
}
Beispiel #5
0
void FEComponentTransfer::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);

    Uint8ClampedArray* pixelArray = createUnmultipliedImageResult();
    if (!pixelArray)
        return;

    unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
    getValues(rValues, gValues, bValues, aValues);
    unsigned char* tables[] = { rValues, gValues, bValues, aValues };

    IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    in->copyUnmultipliedImage(pixelArray, drawingRect);

    unsigned pixelArrayLength = pixelArray->length();
    for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
        for (unsigned channel = 0; channel < 4; ++channel) {
            unsigned char c = pixelArray->item(pixelOffset + channel);
            pixelArray->set(pixelOffset + channel, tables[channel][c]);
        }
    }
}