diff options
author | reed <reed@google.com> | 2015-10-12 11:30:02 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-12 11:30:02 -0700 |
commit | 88d064d0e481949184305c7b1d6b282dddffac39 (patch) | |
tree | d0e264a2d1289cdfc46a5026ca45a7a57095c250 /gm/spritebitmap.cpp | |
parent | f028003cf4429813ae1ac6624efa51ecbb062ed3 (diff) |
add applyFilter() to SkImage
Result:
- clients can get a filtered version of an image without having to setup a temp drawing environment
- for some cases, the process is more efficient even than (deprecated) drawSprite, since there is no need to draw/copy the result
Impl:
- made Proxy virtual so we don't need to have an existing device to use it
This, in conjunction with LocalMatrixImageFilter, should allow us to simplify and optimize ApplyImageFilter() in cc/output/gl_renderer.cc
BUG=skia:
Review URL: https://codereview.chromium.org/1390913005
Diffstat (limited to 'gm/spritebitmap.cpp')
-rw-r--r-- | gm/spritebitmap.cpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/gm/spritebitmap.cpp b/gm/spritebitmap.cpp index ceed50acaa..0d467ea01a 100644 --- a/gm/spritebitmap.cpp +++ b/gm/spritebitmap.cpp @@ -97,3 +97,121 @@ private: }; DEF_GM( return new SpriteBitmapGM; ) +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "SkColorFilterImageFilter.h" +#include "SkModeColorFilter.h" +#include "SkMorphologyImageFilter.h" +#include "SkOffsetImageFilter.h" + +static SkImage* make_image(SkCanvas* rootCanvas) { + SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100); + SkAutoTUnref<SkSurface> surface(rootCanvas->newSurface(info)); + if (!surface) { + surface.reset(SkSurface::NewRaster(info)); + } + + SkPaint paint; + paint.setAntiAlias(true); + paint.setColor(SK_ColorRED); + surface->getCanvas()->drawCircle(50, 50, 50, paint); + return surface->newImageSnapshot(); +} + +static void show_image(SkCanvas* canvas, SkImage* image, const SkIPoint& offset) { + SkScalar x = SkIntToScalar(offset.x()); + SkScalar y = SkIntToScalar(offset.y()); + + SkPaint paint; + paint.setStyle(SkPaint::kStroke_Style); + + SkRect r = SkRect::MakeIWH(image->width(), image->height()); + r.offset(x, y); + // get on pixel-centers to make the hairline land on a numerical stable boundary + r.outset(SK_ScalarHalf, SK_ScalarHalf); + canvas->drawRect(r, paint); + + canvas->drawImage(image, x, y, nullptr); +} + +typedef SkImageFilter* (*ImageFilterFactory)(); + +// +[]{...} did not work on windows (VS) +// (ImageFilterFactory)[]{...} did not work on linux (gcc) +// hence this cast function +template <typename T> ImageFilterFactory IFCCast(T arg) { return arg; } + +/** + * Compare output of drawSprite and drawBitmap (esp. clipping and imagefilters) + */ +class ApplyFilterGM : public skiagm::GM { +public: + ApplyFilterGM() {} + +protected: + SkString onShortName() override { + return SkString("apply-filter"); + } + + SkISize onISize() override { + return SkISize::Make(640, 480); + } + + void onDraw(SkCanvas* canvas) override { + SkAutoTUnref<SkImage> image0(make_image(canvas)); + + const ImageFilterFactory factories[] = { + IFCCast([]{ return SkBlurImageFilter::Create(8, 8); }), + IFCCast([]{ SkAutoTUnref<SkColorFilter> cf(SkModeColorFilter::Create(SK_ColorBLUE, + SkXfermode::kSrcIn_Mode)); + return SkColorFilterImageFilter::Create(cf); + }), + IFCCast([]{ return SkDilateImageFilter::Create(8, 8); }), + IFCCast([]{ return SkErodeImageFilter::Create(8, 8); }), + IFCCast([]{ return SkOffsetImageFilter::Create(8, 8); }), + }; + + const SkScalar spacer = image0->width() * 3.0f / 2; + + for (auto&& factory : factories) { + SkAutoTUnref<SkImageFilter> filter(factory()); + + SkIPoint offset1, offset2; + SkAutoTUnref<SkImage> image1(image0->applyFilter(filter, &offset1, true)); + SkAutoTUnref<SkImage> image2(image0->applyFilter(filter, &offset2, false)); + + canvas->save(); + canvas->translate(30, 30); + show_image(canvas, image0, SkIPoint::Make(0, 0)); // original + canvas->translate(spacer, 0); + show_image(canvas, image1, offset1); // snug + canvas->translate(spacer, 0); + show_image(canvas, image2, offset2); // not snug + + // Try drawing the original w/ the filter, to see that it "draws" the same as + // when we have manually applied the filter (above). + { + SkPaint paint; + paint.setImageFilter(filter); + + SkBitmap bm; + image0->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode); + SkPoint loc = { 0, 0 }; + canvas->translate(spacer, 0); + canvas->getTotalMatrix().mapPoints(&loc, 1); + canvas->drawSprite(bm, (int)loc.x(), (int)loc.y(), &paint); // like snug + + canvas->translate(spacer, 0); + canvas->drawImage(image0, 0, 0, &paint); // like not snug + } + canvas->restore(); + + canvas->translate(0, spacer); + } + } + +private: + typedef GM INHERITED; +}; +DEF_GM( return new ApplyFilterGM; ) + |