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 |