| 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_2_bitmaps(SkCanvas* canvas, const SkBitmap& bm, bool doClip, | 25 static void draw_1_bitmap(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 | |
| 47 canvas->translate(SkIntToScalar(bm.width() + 20), 0); | 38 canvas->translate(SkIntToScalar(bm.width() + 20), 0); |
| 48 | 39 |
| 49 if (doClip) { | 40 if (doClip) { |
| 50 canvas->save(); | 41 canvas->save(); |
| 51 canvas->clipRect(clipR); | 42 canvas->clipRect(clipR); |
| 52 } | 43 } |
| 53 canvas->drawBitmap(bm, SkIntToScalar(dx), SkIntToScalar(dy), &paint); | 44 canvas->drawBitmap(bm, SkIntToScalar(dx), SkIntToScalar(dy), &paint); |
| 54 if (doClip) { | 45 if (doClip) { |
| 55 canvas->restore(); | 46 canvas->restore(); |
| 56 } | 47 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 76 void onDraw(SkCanvas* canvas) override { | 67 void onDraw(SkCanvas* canvas) override { |
| 77 SkBitmap bm; | 68 SkBitmap bm; |
| 78 make_bm(&bm); | 69 make_bm(&bm); |
| 79 | 70 |
| 80 int dx = 10; | 71 int dx = 10; |
| 81 int dy = 10; | 72 int dy = 10; |
| 82 | 73 |
| 83 SkScalar sigma = 8; | 74 SkScalar sigma = 8; |
| 84 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(sigma, sigm
a)); | 75 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(sigma, sigm
a)); |
| 85 | 76 |
| 86 draw_2_bitmaps(canvas, bm, false, dx, dy); | 77 draw_1_bitmap(canvas, bm, false, dx, dy); |
| 87 dy += bm.height() + 20; | 78 dy += bm.height() + 20; |
| 88 draw_2_bitmaps(canvas, bm, false, dx, dy, filter); | 79 draw_1_bitmap(canvas, bm, false, dx, dy, filter); |
| 89 dy += bm.height() + 20; | 80 dy += bm.height() + 20; |
| 90 draw_2_bitmaps(canvas, bm, true, dx, dy); | 81 draw_1_bitmap(canvas, bm, true, dx, dy); |
| 91 dy += bm.height() + 20; | 82 dy += bm.height() + 20; |
| 92 draw_2_bitmaps(canvas, bm, true, dx, dy, filter); | 83 draw_1_bitmap(canvas, bm, true, dx, dy, filter); |
| 93 } | 84 } |
| 94 | 85 |
| 95 private: | 86 private: |
| 96 typedef GM INHERITED; | 87 typedef GM INHERITED; |
| 97 }; | 88 }; |
| 98 DEF_GM( return new SpriteBitmapGM; ) | 89 DEF_GM( return new SpriteBitmapGM; ) |
| 99 | 90 |
| 100 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 91 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 101 | 92 |
| 102 #include "SkColorFilterImageFilter.h" | 93 #include "SkColorFilterImageFilter.h" |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 check_same_domain(image0, image2); | 180 check_same_domain(image0, image2); |
| 190 | 181 |
| 191 canvas->save(); | 182 canvas->save(); |
| 192 canvas->translate(30, 30); | 183 canvas->translate(30, 30); |
| 193 show_image(canvas, image0, SkIPoint::Make(0, 0)); // original | 184 show_image(canvas, image0, SkIPoint::Make(0, 0)); // original |
| 194 canvas->translate(spacer, 0); | 185 canvas->translate(spacer, 0); |
| 195 show_image(canvas, image1, offset1); // snug | 186 show_image(canvas, image1, offset1); // snug |
| 196 canvas->translate(spacer, 0); | 187 canvas->translate(spacer, 0); |
| 197 show_image(canvas, image2, offset2); // not snug | 188 show_image(canvas, image2, offset2); // not snug |
| 198 | 189 |
| 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 } | |
| 215 canvas->restore(); | 190 canvas->restore(); |
| 216 | 191 |
| 217 canvas->translate(0, spacer); | 192 canvas->translate(0, spacer); |
| 218 } | 193 } |
| 219 } | 194 } |
| 220 | 195 |
| 221 private: | 196 private: |
| 222 typedef GM INHERITED; | 197 typedef GM INHERITED; |
| 223 }; | 198 }; |
| 224 DEF_GM( return new ApplyFilterGM; ) | 199 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 |