OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "sk_tool_utils.h" | 8 #include "sk_tool_utils.h" |
9 #include "sk_tool_utils_flags.h" | 9 #include "sk_tool_utils_flags.h" |
10 | 10 |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 | 342 |
343 norm_to_rgb(bm, x, y, norm); | 343 norm_to_rgb(bm, x, y, norm); |
344 } | 344 } |
345 } | 345 } |
346 } | 346 } |
347 | 347 |
348 void make_big_path(SkPath& path) { | 348 void make_big_path(SkPath& path) { |
349 #include "BigPathBench.inc" | 349 #include "BigPathBench.inc" |
350 } | 350 } |
351 | 351 |
| 352 static float gaussian2d_value(int x, int y, float sigma) { |
| 353 // don't bother with the scale term since we're just going to normalize the |
| 354 // kernel anyways |
| 355 float temp = exp(-(x*x + y*y)/(2*sigma*sigma)); |
| 356 return temp; |
| 357 } |
| 358 |
| 359 static float* create_2d_kernel(float sigma, int* filterSize) { |
| 360 // We will actually take 2*halfFilterSize+1 samples (i.e., our filter kernel |
| 361 // sizes are always odd) |
| 362 int halfFilterSize = SkScalarCeilToInt(6*sigma)/2; |
| 363 int wh = *filterSize = 2*halfFilterSize + 1; |
| 364 |
| 365 float* temp = new float[wh*wh]; |
| 366 |
| 367 float filterTot = 0.0f; |
| 368 for (int yOff = 0; yOff < wh; ++yOff) { |
| 369 for (int xOff = 0; xOff < wh; ++xOff) { |
| 370 temp[yOff*wh+xOff] = gaussian2d_value(xOff-halfFilterSize, yOff-half
FilterSize, sigma); |
| 371 |
| 372 filterTot += temp[yOff*wh+xOff]; |
| 373 } |
| 374 } |
| 375 |
| 376 // normalize the kernel |
| 377 for (int yOff = 0; yOff < wh; ++yOff) { |
| 378 for (int xOff = 0; xOff < wh; ++xOff) { |
| 379 temp[yOff*wh+xOff] /= filterTot; |
| 380 } |
| 381 } |
| 382 |
| 383 return temp; |
| 384 } |
| 385 |
| 386 static SkPMColor blur_pixel(const SkBitmap& bm, int x, int y, float* kernel, int
wh) { |
| 387 SkASSERT(wh & 0x1); |
| 388 |
| 389 int halfFilterSize = (wh-1)/2; |
| 390 |
| 391 float r = 0.0f, g = 0.0f, b = 0.0f; |
| 392 for (int yOff = 0; yOff < wh; ++yOff) { |
| 393 int ySamp = y + yOff - halfFilterSize; |
| 394 |
| 395 if (ySamp < 0) { |
| 396 ySamp = 0; |
| 397 } else if (ySamp > bm.height()-1) { |
| 398 ySamp = bm.height()-1; |
| 399 } |
| 400 |
| 401 for (int xOff = 0; xOff < wh; ++xOff) { |
| 402 int xSamp = x + xOff - halfFilterSize; |
| 403 |
| 404 if (xSamp < 0) { |
| 405 xSamp = 0; |
| 406 } else if (xSamp > bm.width()-1) { |
| 407 xSamp = bm.width()-1; |
| 408 } |
| 409 |
| 410 float filter = kernel[yOff*wh + xOff]; |
| 411 |
| 412 SkPMColor c = *bm.getAddr32(xSamp, ySamp); |
| 413 |
| 414 r += SkGetPackedR32(c) * filter; |
| 415 g += SkGetPackedG32(c) * filter; |
| 416 b += SkGetPackedB32(c) * filter; |
| 417 } |
| 418 } |
| 419 |
| 420 U8CPU r8, g8, b8; |
| 421 |
| 422 r8 = (U8CPU) (r+0.5f); |
| 423 g8 = (U8CPU) (g+0.5f); |
| 424 b8 = (U8CPU) (b+0.5f); |
| 425 |
| 426 return SkPackARGB32(255, r8, g8, b8); |
| 427 } |
| 428 |
| 429 SkBitmap slow_blur(const SkBitmap& src, float sigma) { |
| 430 SkBitmap dst; |
| 431 |
| 432 dst.allocN32Pixels(src.width(), src.height(), true); |
| 433 |
| 434 int wh; |
| 435 SkAutoTDeleteArray<float> kernel(create_2d_kernel(sigma, &wh)); |
| 436 |
| 437 for (int y = 0; y < src.height(); ++y) { |
| 438 for (int x = 0; x < src.width(); ++x) { |
| 439 *dst.getAddr32(x, y) = blur_pixel(src, x, y, kernel.get(), wh); |
| 440 } |
| 441 } |
| 442 |
| 443 return dst; |
| 444 } |
| 445 |
352 } // namespace sk_tool_utils | 446 } // namespace sk_tool_utils |
OLD | NEW |