コード例 #1
0
ファイル: SkBlurImageFilter.cpp プロジェクト: jiezh/h5vcc
bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
                                      const SkBitmap& source, const SkMatrix& ctm,
                                      SkBitmap* dst, SkIPoint* offset) {
    SkBitmap src = this->getInputResult(proxy, source, ctm, offset);
    if (src.config() != SkBitmap::kARGB_8888_Config) {
        return false;
    }

    SkAutoLockPixels alp(src);
    if (!src.getPixels()) {
        return false;
    }

    dst->setConfig(src.config(), src.width(), src.height());
    dst->allocPixels();
    int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
    int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY;
    getBox3Params(fSigma.width(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
    getBox3Params(fSigma.height(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);

    if (kernelSizeX < 0 || kernelSizeY < 0) {
        return false;
    }

    if (kernelSizeX == 0 && kernelSizeY == 0) {
        src.copyTo(dst, dst->config());
        return true;
    }

    SkBitmap temp;
    temp.setConfig(dst->config(), dst->width(), dst->height());
    if (!temp.allocPixels()) {
        return false;
    }

    if (kernelSizeX > 0 && kernelSizeY > 0) {
        boxBlurX(src,  &temp, kernelSizeX,  lowOffsetX, highOffsetX);
        boxBlurY(temp, dst,   kernelSizeY,  lowOffsetY, highOffsetY);
        boxBlurX(*dst, &temp, kernelSizeX,  highOffsetX,  lowOffsetX);
        boxBlurY(temp, dst,   kernelSizeY,  highOffsetY,  lowOffsetY);
        boxBlurX(*dst, &temp, kernelSizeX3, highOffsetX, highOffsetX);
        boxBlurY(temp, dst,   kernelSizeY3, highOffsetY, highOffsetY);
    } else if (kernelSizeX > 0) {
        boxBlurX(src,  dst,   kernelSizeX,  lowOffsetX, highOffsetX);
        boxBlurX(*dst, &temp, kernelSizeX,  highOffsetX,  lowOffsetX);
        boxBlurX(temp, dst,   kernelSizeX3, highOffsetX, highOffsetX);
    } else if (kernelSizeY > 0) {
        boxBlurY(src,  dst,   kernelSizeY,  lowOffsetY, highOffsetY);
        boxBlurY(*dst, &temp, kernelSizeY,  highOffsetY, lowOffsetY);
        boxBlurY(temp, dst,   kernelSizeY3, highOffsetY, highOffsetY);
    }
    return true;
}
コード例 #2
0
ファイル: SkBlurImageFilter.cpp プロジェクト: Adenilson/skia
bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
                                      const SkBitmap& source, const Context& ctx,
                                      SkBitmap* dst, SkIPoint* offset) const {
    SkBitmap src = source;
    SkIPoint srcOffset = SkIPoint::Make(0, 0);
    if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
        return false;
    }

    if (src.colorType() != kN32_SkColorType) {
        return false;
    }

    SkIRect srcBounds, dstBounds;
    if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &srcBounds, &src)) {
        return false;
    }

    SkAutoLockPixels alp(src);
    if (!src.getPixels()) {
        return false;
    }

    if (!dst->allocPixels(src.info().makeWH(srcBounds.width(), srcBounds.height()))) {
        return false;
    }
    dst->getBounds(&dstBounds);

    SkVector sigma = SkVector::Make(fSigma.width(), fSigma.height());
    ctx.ctm().mapVectors(&sigma, 1);
    sigma.fX = SkMinScalar(sigma.fX, MAX_SIGMA);
    sigma.fY = SkMinScalar(sigma.fY, MAX_SIGMA);

    int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
    int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY;
    getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
    getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);

    if (kernelSizeX < 0 || kernelSizeY < 0) {
        return false;
    }

    if (kernelSizeX == 0 && kernelSizeY == 0) {
        src.copyTo(dst, dst->colorType());
        offset->fX = srcBounds.fLeft;
        offset->fY = srcBounds.fTop;
        return true;
    }

    SkBitmap temp;
    if (!temp.allocPixels(dst->info())) {
        return false;
    }

    offset->fX = srcBounds.fLeft;
    offset->fY = srcBounds.fTop;
    srcBounds.offset(-srcOffset);
    const SkPMColor* s = src.getAddr32(srcBounds.left(), srcBounds.top());
    SkPMColor* t = temp.getAddr32(0, 0);
    SkPMColor* d = dst->getAddr32(0, 0);
    int w = dstBounds.width(), h = dstBounds.height();
    int sw = src.rowBytesAsPixels();
    SkBoxBlurProc boxBlurX, boxBlurY, boxBlurXY, boxBlurYX;
    if (!SkBoxBlurGetPlatformProcs(&boxBlurX, &boxBlurY, &boxBlurXY, &boxBlurYX)) {
        boxBlurX = boxBlur<kX, kX>;
        boxBlurY = boxBlur<kY, kY>;
        boxBlurXY = boxBlur<kX, kY>;
        boxBlurYX = boxBlur<kY, kX>;
    }

    if (kernelSizeX > 0 && kernelSizeY > 0) {
        boxBlurX(s,  sw, t, kernelSizeX,  lowOffsetX,  highOffsetX, w, h);
        boxBlurX(t,  w,  d, kernelSizeX,  highOffsetX, lowOffsetX,  w, h);
        boxBlurXY(d, w,  t, kernelSizeX3, highOffsetX, highOffsetX, w, h);
        boxBlurX(t,  h,  d, kernelSizeY,  lowOffsetY,  highOffsetY, h, w);
        boxBlurX(d,  h,  t, kernelSizeY,  highOffsetY, lowOffsetY,  h, w);
        boxBlurXY(t, h,  d, kernelSizeY3, highOffsetY, highOffsetY, h, w);
    } else if (kernelSizeX > 0) {
        boxBlurX(s,  sw, d, kernelSizeX,  lowOffsetX,  highOffsetX, w, h);
        boxBlurX(d,  w,  t, kernelSizeX,  highOffsetX, lowOffsetX,  w, h);
        boxBlurX(t,  w,  d, kernelSizeX3, highOffsetX, highOffsetX, w, h);
    } else if (kernelSizeY > 0) {
        boxBlurYX(s, sw, d, kernelSizeY,  lowOffsetY,  highOffsetY, h, w);
        boxBlurX(d,  h,  t, kernelSizeY,  highOffsetY, lowOffsetY,  h, w);
        boxBlurXY(t, h,  d, kernelSizeY3, highOffsetY, highOffsetY, h, w);
    }
    return true;
}
コード例 #3
0
ファイル: SkBlurImageFilter.cpp プロジェクト: keinvo/skia
bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
                                      const SkBitmap& source, const Context& ctx,
                                      SkBitmap* dst, SkIPoint* offset) const {
    SkBitmap src = source;
    SkIPoint srcOffset = SkIPoint::Make(0, 0);
    if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) {
        return false;
    }

    if (src.colorType() != kN32_SkColorType) {
        return false;
    }

    SkIRect srcBounds, dstBounds;
    if (!this->applyCropRect(this->mapContext(ctx), src, srcOffset, &dstBounds, &srcBounds)) {
        return false;
    }
    if (!srcBounds.intersect(dstBounds)) {
        return false;
    }

    SkAutoLockPixels alp(src);
    if (!src.getPixels()) {
        return false;
    }

    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height()));
    if (!device) {
        return false;
    }
    *dst = device->accessBitmap(false);
    SkAutoLockPixels alp_dst(*dst);

    SkVector sigma = mapSigma(fSigma, ctx.ctm());

    int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
    int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY;
    getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
    getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);

    if (kernelSizeX < 0 || kernelSizeY < 0) {
        return false;
    }

    if (kernelSizeX == 0 && kernelSizeY == 0) {
        src.copyTo(dst, dst->colorType());
        offset->fX = dstBounds.x() + srcOffset.x();
        offset->fY = dstBounds.y() + srcOffset.y();
        return true;
    }

    SkAutoTUnref<SkBaseDevice> tempDevice(proxy->createDevice(dst->width(), dst->height()));
    if (!tempDevice) {
        return false;
    }
    SkBitmap temp = tempDevice->accessBitmap(false);
    SkAutoLockPixels alpTemp(temp);

    offset->fX = dstBounds.fLeft;
    offset->fY = dstBounds.fTop;
    SkPMColor* t = temp.getAddr32(0, 0);
    SkPMColor* d = dst->getAddr32(0, 0);
    int w = dstBounds.width(), h = dstBounds.height();
    const SkPMColor* s = src.getAddr32(srcBounds.x() - srcOffset.x(), srcBounds.y() - srcOffset.y());
    srcBounds.offset(-dstBounds.x(), -dstBounds.y());
    dstBounds.offset(-dstBounds.x(), -dstBounds.y());
    SkIRect srcBoundsT = SkIRect::MakeLTRB(srcBounds.top(), srcBounds.left(), srcBounds.bottom(), srcBounds.right());
    SkIRect dstBoundsT = SkIRect::MakeWH(dstBounds.height(), dstBounds.width());
    int sw = src.rowBytesAsPixels();

    /**
     *
     * In order to make memory accesses cache-friendly, we reorder the passes to
     * use contiguous memory reads wherever possible.
     *
     * For example, the 6 passes of the X-and-Y blur case are rewritten as
     * follows. Instead of 3 passes in X and 3 passes in Y, we perform
     * 2 passes in X, 1 pass in X transposed to Y on write, 2 passes in X,
     * then 1 pass in X transposed to Y on write.
     *
     * +----+       +----+       +----+        +---+       +---+       +---+        +----+
     * + AB + ----> | AB | ----> | AB | -----> | A | ----> | A | ----> | A | -----> | AB |
     * +----+ blurX +----+ blurX +----+ blurXY | B | blurX | B | blurX | B | blurXY +----+
     *                                         +---+       +---+       +---+
     *
     * In this way, two of the y-blurs become x-blurs applied to transposed
     * images, and all memory reads are contiguous.
     */
    if (kernelSizeX > 0 && kernelSizeY > 0) {
        SkOpts::box_blur_xx(s, sw,  srcBounds,  t, kernelSizeX,  lowOffsetX,  highOffsetX, w, h);
        SkOpts::box_blur_xx(t,  w,  dstBounds,  d, kernelSizeX,  highOffsetX, lowOffsetX,  w, h);
        SkOpts::box_blur_xy(d,  w,  dstBounds,  t, kernelSizeX3, highOffsetX, highOffsetX, w, h);
        SkOpts::box_blur_xx(t,  h,  dstBoundsT, d, kernelSizeY,  lowOffsetY,  highOffsetY, h, w);
        SkOpts::box_blur_xx(d,  h,  dstBoundsT, t, kernelSizeY,  highOffsetY, lowOffsetY,  h, w);
        SkOpts::box_blur_xy(t,  h,  dstBoundsT, d, kernelSizeY3, highOffsetY, highOffsetY, h, w);
    } else if (kernelSizeX > 0) {
        SkOpts::box_blur_xx(s, sw,  srcBounds,  d, kernelSizeX,  lowOffsetX,  highOffsetX, w, h);
        SkOpts::box_blur_xx(d,  w,  dstBounds,  t, kernelSizeX,  highOffsetX, lowOffsetX,  w, h);
        SkOpts::box_blur_xx(t,  w,  dstBounds,  d, kernelSizeX3, highOffsetX, highOffsetX, w, h);
    } else if (kernelSizeY > 0) {
        SkOpts::box_blur_yx(s, sw,  srcBoundsT, d, kernelSizeY,  lowOffsetY,  highOffsetY, h, w);
        SkOpts::box_blur_xx(d,  h,  dstBoundsT, t, kernelSizeY,  highOffsetY, lowOffsetY,  h, w);
        SkOpts::box_blur_xy(t,  h,  dstBoundsT, d, kernelSizeY3, highOffsetY, highOffsetY, h, w);
    }
    return true;
}
コード例 #4
0
bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
                                      const SkBitmap& source, const SkMatrix& ctm,
                                      SkBitmap* dst, SkIPoint* offset) {
    SkBitmap src = source;
    if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) {
        return false;
    }

    if (src.config() != SkBitmap::kARGB_8888_Config) {
        return false;
    }

    SkAutoLockPixels alp(src);
    if (!src.getPixels()) {
        return false;
    }

    SkIRect srcBounds, dstBounds;
    src.getBounds(&srcBounds);
    if (!this->applyCropRect(&srcBounds, ctm)) {
        return false;
    }

    dst->setConfig(src.config(), srcBounds.width(), srcBounds.height());
    dst->getBounds(&dstBounds);
    dst->allocPixels();
    int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
    int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY;
    getBox3Params(fSigma.width(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
    getBox3Params(fSigma.height(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);

    if (kernelSizeX < 0 || kernelSizeY < 0) {
        return false;
    }

    if (kernelSizeX == 0 && kernelSizeY == 0) {
        src.copyTo(dst, dst->config());
        return true;
    }

    SkBitmap temp;
    temp.setConfig(dst->config(), dst->width(), dst->height());
    if (!temp.allocPixels()) {
        return false;
    }

    if (kernelSizeX > 0 && kernelSizeY > 0) {
        boxBlurX(src,  &temp, kernelSizeX,  lowOffsetX,  highOffsetX, srcBounds);
        boxBlurY(temp, dst,   kernelSizeY,  lowOffsetY,  highOffsetY, dstBounds);
        boxBlurX(*dst, &temp, kernelSizeX,  highOffsetX, lowOffsetX, dstBounds);
        boxBlurY(temp, dst,   kernelSizeY,  highOffsetY, lowOffsetY, dstBounds);
        boxBlurX(*dst, &temp, kernelSizeX3, highOffsetX, highOffsetX, dstBounds);
        boxBlurY(temp, dst,   kernelSizeY3, highOffsetY, highOffsetY, dstBounds);
    } else if (kernelSizeX > 0) {
        boxBlurX(src,  dst,   kernelSizeX,  lowOffsetX,  highOffsetX, srcBounds);
        boxBlurX(*dst, &temp, kernelSizeX,  highOffsetX, lowOffsetX, dstBounds);
        boxBlurX(temp, dst,   kernelSizeX3, highOffsetX, highOffsetX, dstBounds);
    } else if (kernelSizeY > 0) {
        boxBlurY(src,  dst,   kernelSizeY,  lowOffsetY,  highOffsetY, srcBounds);
        boxBlurY(*dst, &temp, kernelSizeY,  highOffsetY, lowOffsetY, dstBounds);
        boxBlurY(temp, dst,   kernelSizeY3, highOffsetY, highOffsetY, dstBounds);
    }
    offset->fX += srcBounds.fLeft;
    offset->fY += srcBounds.fTop;
    return true;
}