void FEComposite::apply(Filter* filter) { m_in->apply(filter); m_in2->apply(filter); if (!m_in->resultImage() || !m_in2->resultImage()) return; GraphicsContext* filterContext = getEffectContext(); if (!filterContext) return; FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f); switch (m_type) { case FECOMPOSITE_OPERATOR_OVER: filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); break; case FECOMPOSITE_OPERATOR_IN: filterContext->save(); filterContext->clipToImageBuffer(m_in2->resultImage(), calculateDrawingRect(m_in2->scaledSubRegion())); filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); filterContext->restore(); break; case FECOMPOSITE_OPERATOR_OUT: filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut); break; case FECOMPOSITE_OPERATOR_ATOP: filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop); break; case FECOMPOSITE_OPERATOR_XOR: filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR); break; case FECOMPOSITE_OPERATOR_ARITHMETIC: { IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion()); RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)); CanvasPixelArray* srcPixelArrayB(imageData->data()); arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4); resultImage()->putPremultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint()); } break; default: break; } }
void FEDisplacementMap::apply(Filter* filter) { m_in->apply(filter); m_in2->apply(filter); if (!m_in->resultImage() || !m_in2->resultImage()) return; if (m_xChannelSelector == CHANNEL_UNKNOWN || m_yChannelSelector == CHANNEL_UNKNOWN) return; if (!getEffectContext()) return; IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion()); RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getUnmultipliedImageData(effectBDrawingRect)->data()); IntRect imageRect(IntPoint(), resultImage()->size()); RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length()); float scaleX = m_scale / 255.f * filter->filterResolution().width(); float scaleY = m_scale / 255.f * filter->filterResolution().height(); float scaleAdjustmentX = (0.5f - 0.5f * m_scale) * filter->filterResolution().width(); float scaleAdjustmentY = (0.5f - 0.5f * m_scale) * filter->filterResolution().height(); int stride = imageRect.width() * 4; for (int y = 0; y < imageRect.height(); ++y) { int line = y * stride; for (int x = 0; x < imageRect.width(); ++x) { int dstIndex = line + x * 4; int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX); int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY); for (unsigned channel = 0; channel < 4; ++channel) { if (srcX < 0 || srcX >= imageRect.width() || srcY < 0 || srcY >= imageRect.height()) imageData->data()->set(dstIndex + channel, static_cast<unsigned char>(0)); else { unsigned char pixelValue = srcPixelArrayA->get(srcY * stride + srcX * 4 + channel); imageData->data()->set(dstIndex + channel, pixelValue); } } } } resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint()); }
void FEBlend::apply(Filter* filter) { FilterEffect* in = inputEffect(0); FilterEffect* in2 = inputEffect(1); in->apply(filter); in2->apply(filter); if (!in->resultImage() || !in2->resultImage()) return; if (m_mode == FEBLEND_MODE_UNKNOWN) return; if (!effectContext(filter)) return; IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); RefPtr<CanvasPixelArray> srcPixelArrayB(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data()); IntRect imageRect(IntPoint(), resultImage()->size()); RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); // Keep synchronized with BlendModeType static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten}; ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length()); for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) { unsigned char alphaA = srcPixelArrayA->get(pixelOffset + 3); unsigned char alphaB = srcPixelArrayB->get(pixelOffset + 3); for (unsigned channel = 0; channel < 3; ++channel) { unsigned char colorA = srcPixelArrayA->get(pixelOffset + channel); unsigned char colorB = srcPixelArrayB->get(pixelOffset + channel); unsigned char result = (*callEffect[m_mode])(colorA, colorB, alphaA, alphaB); imageData->data()->set(pixelOffset + channel, result); } unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255; imageData->data()->set(pixelOffset + 3, alphaR); } resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint()); }