SkMatrixConvolutionImageFilter.cpp revision 8640d5024d57da5508bdf7585849e3b1f1cb365b
15faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org/*
25faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * Copyright 2012 The Android Open Source Project
35faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org *
45faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be
55faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * found in the LICENSE file.
65faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org */
75faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
85faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkMatrixConvolutionImageFilter.h"
95faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkBitmap.h"
105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkColorPriv.h"
115faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkFlattenableBuffers.h"
125faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkRect.h"
138640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org#include "SkUnPreMultiply.h"
145faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
158640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgSkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(const SkISize& kernelSize, const SkScalar* kernel, SkScalar gain, SkScalar bias, const SkIPoint& target, TileMode tileMode, bool convolveAlpha, SkImageFilter* input)
165faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  : INHERITED(input),
175faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernelSize(kernelSize),
185faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fGain(gain),
195faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fBias(bias),
205faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fTarget(target),
218640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    fTileMode(tileMode),
228640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    fConvolveAlpha(convolveAlpha) {
235faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    uint32_t size = fKernelSize.fWidth * fKernelSize.fHeight;
245faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernel = SkNEW_ARRAY(SkScalar, size);
255faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    memcpy(fKernel, kernel, size * sizeof(SkScalar));
265faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkASSERT(target.fX >= 0 && target.fX < kernelSize.fWidth);
275faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkASSERT(target.fY >= 0 && target.fY < kernelSize.fHeight);
285faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
295faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
305faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgSkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
315faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernelSize.fWidth = buffer.readInt();
325faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernelSize.fHeight = buffer.readInt();
335faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    uint32_t size = fKernelSize.fWidth * fKernelSize.fHeight;
345faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernel = SkNEW_ARRAY(SkScalar, size);
355faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    uint32_t readSize = buffer.readScalarArray(fKernel);
365faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkASSERT(readSize == size);
375faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fGain = buffer.readScalar();
385faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fBias = buffer.readScalar();
395faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fTarget.fX = buffer.readScalar();
405faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fTarget.fY = buffer.readScalar();
415faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fTileMode = (TileMode) buffer.readInt();
428640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    fConvolveAlpha = buffer.readBool();
435faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
445faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
455faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
465faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    this->INHERITED::flatten(buffer);
475faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeInt(fKernelSize.fWidth);
485faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeInt(fKernelSize.fHeight);
495faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeScalarArray(fKernel, fKernelSize.fWidth * fKernelSize.fHeight);
505faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeScalar(fGain);
515faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeScalar(fBias);
525faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeScalar(fTarget.fX);
535faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeScalar(fTarget.fY);
545faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeInt((int) fTileMode);
558640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    buffer.writeBool(fConvolveAlpha);
565faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
575faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
585faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgSkMatrixConvolutionImageFilter::~SkMatrixConvolutionImageFilter() {
595faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    delete[] fKernel;
605faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
615faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
625faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgclass UncheckedPixelFetcher {
635faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgpublic:
645faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    static inline SkPMColor fetch(const SkBitmap& src, int x, int y) {
655faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return *src.getAddr32(x, y);
665faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
675faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org};
685faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
695faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgclass ClampPixelFetcher {
705faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgpublic:
715faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    static inline SkPMColor fetch(const SkBitmap& src, int x, int y) {
725faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        x = SkClampMax(x, src.width() - 1);
735faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        y = SkClampMax(y, src.height() - 1);
745faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return *src.getAddr32(x, y);
755faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
765faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org};
775faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
785faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgclass RepeatPixelFetcher {
795faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgpublic:
805faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    static inline SkPMColor fetch(const SkBitmap& src, int x, int y) {
815faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        x %= src.width();
825faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        y %= src.height();
835faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        if (x < 0) {
845faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            x += src.width();
855faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        }
865faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        if (y < 0) {
875faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            y += src.height();
885faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        }
895faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return *src.getAddr32(x, y);
905faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
915faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org};
925faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
935faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgclass ClampToBlackPixelFetcher {
945faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgpublic:
955faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    static inline SkPMColor fetch(const SkBitmap& src, int x, int y) {
965faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        if (x < 0 || x >= src.width() || y < 0 || y >= src.height()) {
975faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            return 0;
985faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        } else {
995faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            return *src.getAddr32(x, y);
1005faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        }
1015faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
1025faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org};
1035faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1048640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgtemplate<class PixelFetcher, bool convolveAlpha>
1055faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) {
1065faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    for (int y = rect.fTop; y < rect.fBottom; ++y) {
1075faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        SkPMColor* dptr = result->getAddr32(rect.fLeft, y);
1085faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        for (int x = rect.fLeft; x < rect.fRight; ++x) {
1095faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            SkScalar sumA = 0, sumR = 0, sumG = 0, sumB = 0;
1105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            for (int cy = 0; cy < fKernelSize.fHeight; cy++) {
1115faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                for (int cx = 0; cx < fKernelSize.fWidth; cx++) {
1125faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    SkPMColor s = PixelFetcher::fetch(src, x + cx - fTarget.fX, y + cy - fTarget.fY);
1135faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    SkScalar k = fKernel[cy * fKernelSize.fWidth + cx];
1148640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                    if (convolveAlpha) {
1158640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                        sumA += SkScalarMul(SkIntToScalar(SkGetPackedA32(s)), k);
1168640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                    }
1175faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    sumR += SkScalarMul(SkIntToScalar(SkGetPackedR32(s)), k);
1185faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    sumG += SkScalarMul(SkIntToScalar(SkGetPackedG32(s)), k);
1195faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    sumB += SkScalarMul(SkIntToScalar(SkGetPackedB32(s)), k);
1205faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                }
1215faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            }
1228640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            int a = convolveAlpha
1238640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                  ? SkClampMax(SkScalarFloorToInt(SkScalarMul(sumA, fGain) + fBias), 255)
1248640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                  : SkGetPackedA32(PixelFetcher::fetch(src, x, y));
125cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org            int r = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumR, fGain) + fBias), a);
126cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org            int g = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumG, fGain) + fBias), a);
127cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org            int b = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumB, fGain) + fBias), a);
1288640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            if (!convolveAlpha) {
1298640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                *dptr++ = SkPreMultiplyARGB(a, r, g, b);
1308640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            } else {
1318640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                *dptr++ = SkPackARGB32(a, r, g, b);
1328640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            }
1335faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        }
1345faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
1355faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
1365faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1378640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgtemplate<class PixelFetcher>
1388640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) {
1398640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    if (fConvolveAlpha) {
1408640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        filterPixels<PixelFetcher, true>(src, result, rect);
1418640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    } else {
1428640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        filterPixels<PixelFetcher, false>(src, result, rect);
1438640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
1448640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org}
1458640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
1465faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) {
1475faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    filterPixels<UncheckedPixelFetcher>(src, result, rect);
1485faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
1495faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1505faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) {
1515faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    switch (fTileMode) {
1525faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        case kClamp_TileMode:
1535faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            filterPixels<ClampPixelFetcher>(src, result, rect);
1545faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            break;
1555faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        case kRepeat_TileMode:
1565faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            filterPixels<RepeatPixelFetcher>(src, result, rect);
1575faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            break;
1585faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        case kClampToBlack_TileMode:
1595faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            filterPixels<ClampToBlackPixelFetcher>(src, result, rect);
1605faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            break;
1615faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
1625faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
1635faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1648640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org// FIXME:  This should be refactored to SkSingleInputImageFilter for
1658640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org// use by other filters.  For now, we assume the input is always
1668640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org// premultiplied and unpremultiply it
1678640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgstatic SkBitmap unpremultiplyBitmap(const SkBitmap& src)
1688640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org{
1698640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    SkAutoLockPixels alp(src);
1708640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    if (!src.getPixels()) {
1718640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        return SkBitmap();
1728640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
1738640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    SkBitmap result;
1748640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    result.setConfig(src.config(), src.width(), src.height());
1758640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    result.allocPixels();
1768640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    if (!result.getPixels()) {
1778640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        return SkBitmap();
1788640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
1798640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    for (int y = 0; y < src.height(); ++y) {
1808640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        const uint32_t* srcRow = src.getAddr32(0, y);
1818640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        uint32_t* dstRow = result.getAddr32(0, y);
1828640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        for (int x = 0; x < src.width(); ++x) {
1838640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            dstRow[x] = SkUnPreMultiply::PMColorToColor(srcRow[x]);
1848640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        }
1858640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
1868640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    return result;
1878640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org}
1888640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
1895faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgbool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
1905faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                                   const SkBitmap& source,
1915faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                                   const SkMatrix& matrix,
1925faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                                   SkBitmap* result,
1935faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                                   SkIPoint* loc) {
1945faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkBitmap src = this->getInputResult(proxy, source, matrix, loc);
1955faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    if (src.config() != SkBitmap::kARGB_8888_Config) {
1965faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return false;
1975faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
1985faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1998640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    if (!fConvolveAlpha && !src.isOpaque()) {
2008640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        src = unpremultiplyBitmap(src);
2018640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
2028640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
2035faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkAutoLockPixels alp(src);
2045faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    if (!src.getPixels()) {
2055faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return false;
2065faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
2075faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2085faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    result->setConfig(src.config(), src.width(), src.height());
2095faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    result->allocPixels();
2105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2115faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkIRect interior = SkIRect::MakeXYWH(fTarget.fX, fTarget.fY,
2125faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                         src.width() - fKernelSize.fWidth + 1,
2135faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                         src.height() - fKernelSize.fHeight + 1);
2145faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkIRect top = SkIRect::MakeWH(src.width(), fTarget.fY);
2155faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkIRect bottom = SkIRect::MakeLTRB(0, interior.bottom(),
2165faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                       src.width(), src.height());
2175faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkIRect left = SkIRect::MakeXYWH(0, interior.top(),
2185faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                     fTarget.fX, interior.height());
2195faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkIRect right = SkIRect::MakeLTRB(interior.right(), interior.top(),
2205faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                      src.width(), interior.bottom());
2215faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    filterBorderPixels(src, result, top);
2225faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    filterBorderPixels(src, result, left);
2235faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    filterInteriorPixels(src, result, interior);
2245faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    filterBorderPixels(src, result, right);
2255faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    filterBorderPixels(src, result, bottom);
2265faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    return true;
2275faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
228