OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm.h" | 8 #include "gm.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkBlurImageFilter.h" | 10 #include "SkBlurImageFilter.h" |
11 #include "SkRSXform.h" | 11 #include "SkRSXform.h" |
12 #include "SkSurface.h" | 12 #include "SkSurface.h" |
13 | 13 |
14 static void make_bm(SkBitmap* bm) { | 14 static void make_bm(SkBitmap* bm) { |
15 bm->allocN32Pixels(100, 100); | 15 bm->allocN32Pixels(100, 100); |
16 bm->eraseColor(SK_ColorBLUE); | 16 bm->eraseColor(SK_ColorBLUE); |
17 | 17 |
18 SkCanvas canvas(*bm); | 18 SkCanvas canvas(*bm); |
19 SkPaint paint; | 19 SkPaint paint; |
20 paint.setAntiAlias(true); | 20 paint.setAntiAlias(true); |
21 paint.setColor(SK_ColorRED); | 21 paint.setColor(SK_ColorRED); |
22 canvas.drawCircle(50, 50, 50, paint); | 22 canvas.drawCircle(50, 50, 50, paint); |
23 } | 23 } |
24 | 24 |
25 static void draw_1_bitmap(SkCanvas* canvas, const SkBitmap& bm, bool doClip, | 25 static void draw_2_bitmaps(SkCanvas* canvas, const SkBitmap& bm, bool doClip, |
26 int dx, int dy, SkImageFilter* filter = nullptr) { | 26 int dx, int dy, SkImageFilter* filter = nullptr) { |
27 SkAutoCanvasRestore acr(canvas, true); | 27 SkAutoCanvasRestore acr(canvas, true); |
28 SkPaint paint; | 28 SkPaint paint; |
29 | 29 |
30 SkRect clipR = SkRect::MakeXYWH(SkIntToScalar(dx), | 30 SkRect clipR = SkRect::MakeXYWH(SkIntToScalar(dx), |
31 SkIntToScalar(dy), | 31 SkIntToScalar(dy), |
32 SkIntToScalar(bm.width()), | 32 SkIntToScalar(bm.width()), |
33 SkIntToScalar(bm.height())); | 33 SkIntToScalar(bm.height())); |
34 | 34 |
35 paint.setImageFilter(filter); | 35 paint.setImageFilter(filter); |
36 clipR.inset(5, 5); | 36 clipR.inset(5, 5); |
37 | 37 |
| 38 if (doClip) { |
| 39 canvas->save(); |
| 40 canvas->clipRect(clipR); |
| 41 } |
| 42 canvas->drawSprite(bm, dx, dy, &paint); |
| 43 if (doClip) { |
| 44 canvas->restore(); |
| 45 } |
| 46 |
38 canvas->translate(SkIntToScalar(bm.width() + 20), 0); | 47 canvas->translate(SkIntToScalar(bm.width() + 20), 0); |
39 | 48 |
40 if (doClip) { | 49 if (doClip) { |
41 canvas->save(); | 50 canvas->save(); |
42 canvas->clipRect(clipR); | 51 canvas->clipRect(clipR); |
43 } | 52 } |
44 canvas->drawBitmap(bm, SkIntToScalar(dx), SkIntToScalar(dy), &paint); | 53 canvas->drawBitmap(bm, SkIntToScalar(dx), SkIntToScalar(dy), &paint); |
45 if (doClip) { | 54 if (doClip) { |
46 canvas->restore(); | 55 canvas->restore(); |
47 } | 56 } |
(...skipping 19 matching lines...) Expand all Loading... |
67 void onDraw(SkCanvas* canvas) override { | 76 void onDraw(SkCanvas* canvas) override { |
68 SkBitmap bm; | 77 SkBitmap bm; |
69 make_bm(&bm); | 78 make_bm(&bm); |
70 | 79 |
71 int dx = 10; | 80 int dx = 10; |
72 int dy = 10; | 81 int dy = 10; |
73 | 82 |
74 SkScalar sigma = 8; | 83 SkScalar sigma = 8; |
75 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(sigma, sigm
a)); | 84 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(sigma, sigm
a)); |
76 | 85 |
77 draw_1_bitmap(canvas, bm, false, dx, dy); | 86 draw_2_bitmaps(canvas, bm, false, dx, dy); |
78 dy += bm.height() + 20; | 87 dy += bm.height() + 20; |
79 draw_1_bitmap(canvas, bm, false, dx, dy, filter); | 88 draw_2_bitmaps(canvas, bm, false, dx, dy, filter); |
80 dy += bm.height() + 20; | 89 dy += bm.height() + 20; |
81 draw_1_bitmap(canvas, bm, true, dx, dy); | 90 draw_2_bitmaps(canvas, bm, true, dx, dy); |
82 dy += bm.height() + 20; | 91 dy += bm.height() + 20; |
83 draw_1_bitmap(canvas, bm, true, dx, dy, filter); | 92 draw_2_bitmaps(canvas, bm, true, dx, dy, filter); |
84 } | 93 } |
85 | 94 |
86 private: | 95 private: |
87 typedef GM INHERITED; | 96 typedef GM INHERITED; |
88 }; | 97 }; |
89 DEF_GM( return new SpriteBitmapGM; ) | 98 DEF_GM( return new SpriteBitmapGM; ) |
90 | 99 |
91 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 100 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
92 | 101 |
93 #include "SkColorFilterImageFilter.h" | 102 #include "SkColorFilterImageFilter.h" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 check_same_domain(image0, image2); | 189 check_same_domain(image0, image2); |
181 | 190 |
182 canvas->save(); | 191 canvas->save(); |
183 canvas->translate(30, 30); | 192 canvas->translate(30, 30); |
184 show_image(canvas, image0, SkIPoint::Make(0, 0)); // original | 193 show_image(canvas, image0, SkIPoint::Make(0, 0)); // original |
185 canvas->translate(spacer, 0); | 194 canvas->translate(spacer, 0); |
186 show_image(canvas, image1, offset1); // snug | 195 show_image(canvas, image1, offset1); // snug |
187 canvas->translate(spacer, 0); | 196 canvas->translate(spacer, 0); |
188 show_image(canvas, image2, offset2); // not snug | 197 show_image(canvas, image2, offset2); // not snug |
189 | 198 |
| 199 // Try drawing the original w/ the filter, to see that it "draws" th
e same as |
| 200 // when we have manually applied the filter (above). |
| 201 { |
| 202 SkPaint paint; |
| 203 paint.setImageFilter(filter); |
| 204 |
| 205 SkBitmap bm; |
| 206 image0->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode); |
| 207 SkPoint loc = { 0, 0 }; |
| 208 canvas->translate(spacer, 0); |
| 209 canvas->getTotalMatrix().mapPoints(&loc, 1); |
| 210 canvas->drawSprite(bm, (int)loc.x(), (int)loc.y(), &paint); // l
ike snug |
| 211 |
| 212 canvas->translate(spacer, 0); |
| 213 canvas->drawImage(image0, 0, 0, &paint); // like not snug |
| 214 } |
190 canvas->restore(); | 215 canvas->restore(); |
191 | 216 |
192 canvas->translate(0, spacer); | 217 canvas->translate(0, spacer); |
193 } | 218 } |
194 } | 219 } |
195 | 220 |
196 private: | 221 private: |
197 typedef GM INHERITED; | 222 typedef GM INHERITED; |
198 }; | 223 }; |
199 DEF_GM( return new ApplyFilterGM; ) | 224 DEF_GM( return new ApplyFilterGM; ) |
| 225 |
| 226 ////////////////////// |
| 227 |
| 228 #include "SkDisplacementMapEffect.h" |
| 229 #include "SkMatrixConvolutionImageFilter.h" |
| 230 |
| 231 static SkPMColor max_component(SkPMColor a, SkPMColor b) { |
| 232 int dr = SkAbs32(SkGetPackedR32(a) - SkGetPackedR32(b)); |
| 233 int dg = SkAbs32(SkGetPackedG32(a) - SkGetPackedG32(b)); |
| 234 int db = SkAbs32(SkGetPackedB32(a) - SkGetPackedB32(b)); |
| 235 int d = SkTMax(dr, SkTMax(dg, db)); |
| 236 d = 0xFF - d; |
| 237 return SkPackARGB32(0xFF, d, d, d); |
| 238 } |
| 239 |
| 240 static SkImage* compute_diff(SkImage* a, SkImage* b) { |
| 241 SkASSERT(a->width() == b->width() && a->height() == b->height()); |
| 242 const SkImageInfo info = SkImageInfo::MakeN32Premul(a->width(), a->height())
; |
| 243 SkBitmap bma, bmb, bmdiff; |
| 244 bma.allocPixels(info); |
| 245 bmb.allocPixels(info); |
| 246 bmdiff.allocPixels(info); |
| 247 |
| 248 a->readPixels(info, bma.getPixels(), bma.rowBytes(), 0, 0); |
| 249 b->readPixels(info, bmb.getPixels(), bmb.rowBytes(), 0, 0); |
| 250 for (int y = 0; y < info.height(); ++y) { |
| 251 for (int x = 0; x < info.width(); ++x) { |
| 252 *bmdiff.getAddr32(x, y) = max_component(*bma.getAddr32(x, y), *bmb.g
etAddr32(x, y)); |
| 253 } |
| 254 } |
| 255 bmdiff.setImmutable(); // avoid the copy |
| 256 return SkImage::NewFromBitmap(bmdiff); |
| 257 } |
| 258 |
| 259 static SkImage* make_native_red_oval(SkCanvas* rootCanvas) { |
| 260 SkImageInfo info = SkImageInfo::MakeN32Premul(160, 90); |
| 261 SkAutoTUnref<SkSurface> surface(rootCanvas->newSurface(info)); |
| 262 if (!surface) { |
| 263 surface.reset(SkSurface::NewRaster(info)); |
| 264 } |
| 265 |
| 266 SkPaint paint; |
| 267 paint.setAntiAlias(true); |
| 268 paint.setColor(SK_ColorRED); |
| 269 surface->getCanvas()->drawOval(SkRect::MakeWH(160, 90), paint); |
| 270 return surface->newImageSnapshot(); |
| 271 } |
| 272 |
| 273 |
| 274 static SkSurface* make_surface(SkCanvas* factory, const SkImageInfo& info) { |
| 275 SkSurface* surface = factory->newSurface(info); |
| 276 if (!surface) { |
| 277 surface = SkSurface::NewRaster(info); |
| 278 } |
| 279 return surface; |
| 280 } |
| 281 |
| 282 template <typename DrawProc> SkImage* snapshot(SkCanvas* canvas, const SkImageIn
fo& info, |
| 283 DrawProc p) { |
| 284 SkAutoTUnref<SkSurface> surface(make_surface(canvas, info)); |
| 285 p(surface->getCanvas()); |
| 286 return surface->newImageSnapshot(); |
| 287 } |
| 288 |
| 289 /** |
| 290 * Try drawing an image+imagefilter in two different ways |
| 291 * 1. as drawSprite |
| 292 * 2. as drawImage + clipped to image bounds |
| 293 * The two should draw the same. To try to visualize this, we draw a 4th column
of the difference |
| 294 * between the two versions. If it is all black (where there is alpha), they dr
ew the same! |
| 295 */ |
| 296 class DrawWithFilterGM : public skiagm::GM { |
| 297 public: |
| 298 DrawWithFilterGM() {} |
| 299 |
| 300 protected: |
| 301 SkString onShortName() override { |
| 302 return SkString("draw-with-filter"); |
| 303 } |
| 304 |
| 305 SkISize onISize() override { |
| 306 return SkISize::Make(780, 780); |
| 307 } |
| 308 |
| 309 void onDraw(SkCanvas* canvas) override { |
| 310 SkAutoTUnref<SkImage> image0(make_native_red_oval(canvas)); |
| 311 SkAutoTUnref<SkImage> image1(make_native_red_oval(canvas)); |
| 312 |
| 313 const ImageFilterFactory factories[] = { |
| 314 IFCCast([]{ return SkBlurImageFilter::Create(8, 8); }), |
| 315 IFCCast([]{ SkAutoTUnref<SkColorFilter> cf(SkModeColorFilter::Create
(SK_ColorBLUE, |
| 316 SkXferm
ode::kSrcIn_Mode)); |
| 317 return SkColorFilterImageFilter::Create(cf); |
| 318 }), |
| 319 IFCCast([]{ return SkDilateImageFilter::Create(8, 8); }), |
| 320 IFCCast([]{ return SkErodeImageFilter::Create(8, 8); }), |
| 321 IFCCast([]{ return SkOffsetImageFilter::Create(8, 8); }), |
| 322 |
| 323 IFCCast([]{ return (SkImageFilter*)SkDisplacementMapEffect::Create( |
| 324 SkDisplacementMapEffect::kR_C
hannelSelectorType, |
| 325 SkDisplacementMapEffect::kG_C
hannelSelectorType, |
| 326 10, nullptr); }), |
| 327 IFCCast([]{ |
| 328 const SkScalar kernel[] = { 1, 1, 1, 1, -7, 1, 1, 1, 1 }; |
| 329 return (SkImageFilter*)SkMatrixConvolutionImageFilter::Create( |
| 330 SkISize::Make(3, 3), |
| 331 kernel, 1, 0, |
| 332 SkIPoint::Make(0, 0), |
| 333 SkMatrixConvolutionImageFilter
::kClamp_TileMode, |
| 334 true); }), |
| 335 }; |
| 336 |
| 337 const SkScalar dx = 180; |
| 338 const SkScalar dy = 110; |
| 339 const SkImageInfo info = SkImageInfo::MakeN32Premul(image0->width(), ima
ge0->height()); |
| 340 |
| 341 canvas->translate(20, 20); |
| 342 for (auto&& factory : factories) { |
| 343 SkAutoTUnref<SkImageFilter> filter(factory()); |
| 344 SkPaint paint; |
| 345 paint.setImageFilter(filter); |
| 346 |
| 347 SkAutoTUnref<SkImage> snap0(snapshot(canvas, info, [&](SkCanvas* c)
{ |
| 348 c->drawImage(image0, 0, 0, &paint); |
| 349 })); |
| 350 canvas->drawImage(snap0, 0, 0); |
| 351 |
| 352 SkAutoTUnref<SkImage> snap1(snapshot(canvas, info, [&](SkCanvas* c)
{ |
| 353 SkBitmap bm; |
| 354 image1->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode); |
| 355 c->drawSprite(bm, 0, 0, &paint); |
| 356 })); |
| 357 canvas->drawImage(snap1, dx, 0); |
| 358 |
| 359 SkAutoTUnref<SkImage> diff(snapshot(canvas, info, [&](SkCanvas* c) { |
| 360 SkAutoTUnref<SkImage> diff(compute_diff(snap0, snap1)); |
| 361 c->drawImage(diff, 0, 0); |
| 362 })); |
| 363 canvas->drawImage(diff, 2*dx, 0); |
| 364 |
| 365 canvas->translate(0, dy); |
| 366 } |
| 367 } |
| 368 |
| 369 private: |
| 370 typedef GM INHERITED; |
| 371 }; |
| 372 DEF_GM( return new DrawWithFilterGM; ) |
| 373 |
OLD | NEW |