| 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 "SkMipMap.h" | 8 #include "SkMipMap.h" |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 // | 376 // |
| 377 // To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50
,50) | 377 // To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50
,50) |
| 378 // If the starting dimension is odd, we floor the size of the lower level (e.g.
101 -> 50) | 378 // If the starting dimension is odd, we floor the size of the lower level (e.g.
101 -> 50) |
| 379 // In those (odd) cases, we use a triangle filter, with 1-pixel overlap between
samplings, | 379 // In those (odd) cases, we use a triangle filter, with 1-pixel overlap between
samplings, |
| 380 // else for even cases, we just use a 2x box filter. | 380 // else for even cases, we just use a 2x box filter. |
| 381 // | 381 // |
| 382 // This produces 4 possible filters: 2x2 2x3 3x2 3x3 where WxH indicates the nu
mber of src pixels | 382 // This produces 4 possible filters: 2x2 2x3 3x2 3x3 where WxH indicates the nu
mber of src pixels |
| 383 // we need to sample in each dimension to produce 1 dst pixel. | 383 // we need to sample in each dimension to produce 1 dst pixel. |
| 384 // | 384 // |
| 385 | 385 |
| 386 template <typename F> void downsample_2_2(void* dst, const void* src, size_t src
RB) { | 386 template <typename F> void downsample_2_2(void* dst, const void* src, size_t src
RB, int count) { |
| 387 auto p0 = static_cast<const typename F::Type*>(src); | 387 auto p0 = static_cast<const typename F::Type*>(src); |
| 388 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); | 388 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); |
| 389 auto d = static_cast<typename F::Type*>(dst); |
| 389 | 390 |
| 390 auto c00 = F::Expand(p0[0]); | 391 for (int i = 0; i < count; ++i) { |
| 391 auto c01 = F::Expand(p0[1]); | 392 auto c00 = F::Expand(p0[0]); |
| 392 auto c10 = F::Expand(p1[0]); | 393 auto c01 = F::Expand(p0[1]); |
| 393 auto c11 = F::Expand(p1[1]); | 394 auto c10 = F::Expand(p1[0]); |
| 395 auto c11 = F::Expand(p1[1]); |
| 394 | 396 |
| 395 auto c = c00 + c10 + c01 + c11; | 397 auto c = c00 + c10 + c01 + c11; |
| 396 *(typename F::Type*)dst = F::Compact(c >> 2); | 398 d[i] = F::Compact(c >> 2); |
| 399 p0 += 2; |
| 400 p1 += 2; |
| 401 } |
| 397 } | 402 } |
| 398 | 403 |
| 399 template <typename F> void downsample_3_2(void* dst, const void* src, size_t src
RB) { | 404 template <typename F> void downsample_3_2(void* dst, const void* src, size_t src
RB, int count) { |
| 405 SkASSERT(count > 0); |
| 400 auto p0 = static_cast<const typename F::Type*>(src); | 406 auto p0 = static_cast<const typename F::Type*>(src); |
| 401 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); | 407 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); |
| 408 auto d = static_cast<typename F::Type*>(dst); |
| 409 |
| 410 auto c02 = F::Expand(p0[0]); |
| 411 auto c12 = F::Expand(p1[0]); |
| 412 for (int i = 0; i < count; ++i) { |
| 413 auto c00 = c02; |
| 414 auto c01 = F::Expand(p0[1]); |
| 415 c02 = F::Expand(p0[2]); |
| 416 auto c10 = c12; |
| 417 auto c11 = F::Expand(p1[1]); |
| 418 c12 = F::Expand(p1[2]); |
| 402 | 419 |
| 403 auto c00 = F::Expand(p0[0]); | 420 auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12); |
| 404 auto c01 = F::Expand(p0[1]); | 421 d[i] = F::Compact(c >> 3); |
| 405 auto c02 = F::Expand(p0[2]); | 422 p0 += 2; |
| 406 auto c10 = F::Expand(p1[0]); | 423 p1 += 2; |
| 407 auto c11 = F::Expand(p1[1]); | 424 } |
| 408 auto c12 = F::Expand(p1[2]); | |
| 409 | |
| 410 auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12); | |
| 411 *(typename F::Type*)dst = F::Compact(c >> 3); | |
| 412 } | 425 } |
| 413 | 426 |
| 414 template <typename F> void downsample_2_3(void* dst, const void* src, size_t src
RB) { | 427 template <typename F> void downsample_2_3(void* dst, const void* src, size_t src
RB, int count) { |
| 415 auto p0 = static_cast<const typename F::Type*>(src); | 428 auto p0 = static_cast<const typename F::Type*>(src); |
| 416 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); | 429 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); |
| 417 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); | 430 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); |
| 431 auto d = static_cast<typename F::Type*>(dst); |
| 432 |
| 433 for (int i = 0; i < count; ++i) { |
| 434 auto c00 = F::Expand(p0[0]); |
| 435 auto c01 = F::Expand(p0[1]); |
| 436 auto c10 = F::Expand(p1[0]); |
| 437 auto c11 = F::Expand(p1[1]); |
| 438 auto c20 = F::Expand(p2[0]); |
| 439 auto c21 = F::Expand(p2[1]); |
| 418 | 440 |
| 419 auto c00 = F::Expand(p0[0]); | 441 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21); |
| 420 auto c01 = F::Expand(p0[1]); | 442 d[i] = F::Compact(c >> 3); |
| 421 auto c10 = F::Expand(p1[0]); | 443 p0 += 2; |
| 422 auto c11 = F::Expand(p1[1]); | 444 p1 += 2; |
| 423 auto c20 = F::Expand(p2[0]); | 445 p2 += 2; |
| 424 auto c21 = F::Expand(p2[1]); | 446 } |
| 425 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21); | |
| 426 *(typename F::Type*)dst = F::Compact(c >> 3); | |
| 427 } | 447 } |
| 428 | 448 |
| 429 template <typename F> void downsample_3_3(void* dst, const void* src, size_t src
RB) { | 449 template <typename F> void downsample_3_3(void* dst, const void* src, size_t src
RB, int count) { |
| 430 auto p0 = static_cast<const typename F::Type*>(src); | 450 auto p0 = static_cast<const typename F::Type*>(src); |
| 431 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); | 451 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); |
| 432 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); | 452 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); |
| 453 auto d = static_cast<typename F::Type*>(dst); |
| 433 | 454 |
| 434 auto c00 = F::Expand(p0[0]); | 455 auto c02 = F::Expand(p0[0]); |
| 435 auto c01 = F::Expand(p0[1]); | 456 auto c12 = F::Expand(p1[0]); |
| 436 auto c02 = F::Expand(p0[2]); | 457 auto c22 = F::Expand(p2[0]); |
| 437 auto c10 = F::Expand(p1[0]); | 458 for (int i = 0; i < count; ++i) { |
| 438 auto c11 = F::Expand(p1[1]); | 459 auto c00 = c02; |
| 439 auto c12 = F::Expand(p1[2]); | 460 auto c01 = F::Expand(p0[1]); |
| 440 auto c20 = F::Expand(p2[0]); | 461 c02 = F::Expand(p0[2]); |
| 441 auto c21 = F::Expand(p2[1]); | 462 auto c10 = c12; |
| 442 auto c22 = F::Expand(p2[2]); | 463 auto c11 = F::Expand(p1[1]); |
| 464 c12 = F::Expand(p1[2]); |
| 465 auto c20 = c22; |
| 466 auto c21 = F::Expand(p2[1]); |
| 467 c22 = F::Expand(p2[2]); |
| 443 | 468 |
| 444 auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_121(c2
0, c21, c22); | 469 auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_12
1(c20, c21, c22); |
| 445 *(typename F::Type*)dst = F::Compact(c >> 4); | 470 d[i] = F::Compact(c >> 4); |
| 471 p0 += 2; |
| 472 p1 += 2; |
| 473 p2 += 2; |
| 474 } |
| 446 } | 475 } |
| 447 | 476 |
| 448 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 477 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 449 | 478 |
| 450 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { | 479 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { |
| 451 if (levelCount < 0) { | 480 if (levelCount < 0) { |
| 452 return 0; | 481 return 0; |
| 453 } | 482 } |
| 454 int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; | 483 int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; |
| 455 if (!sk_64_isS32(size)) { | 484 if (!sk_64_isS32(size)) { |
| 456 return 0; | 485 return 0; |
| 457 } | 486 } |
| 458 return sk_64_asS32(size); | 487 return sk_64_asS32(size); |
| 459 } | 488 } |
| 460 | 489 |
| 461 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { | 490 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { |
| 462 typedef void FilterProc(void*, const void* srcPtr, size_t srcRB); | 491 typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count); |
| 463 | 492 |
| 464 FilterProc* proc_2_2 = nullptr; | 493 FilterProc* proc_2_2 = nullptr; |
| 465 FilterProc* proc_2_3 = nullptr; | 494 FilterProc* proc_2_3 = nullptr; |
| 466 FilterProc* proc_3_2 = nullptr; | 495 FilterProc* proc_3_2 = nullptr; |
| 467 FilterProc* proc_3_3 = nullptr; | 496 FilterProc* proc_3_3 = nullptr; |
| 468 | 497 |
| 469 const SkColorType ct = src.colorType(); | 498 const SkColorType ct = src.colorType(); |
| 470 const SkAlphaType at = src.alphaType(); | 499 const SkAlphaType at = src.alphaType(); |
| 471 switch (ct) { | 500 switch (ct) { |
| 472 case kRGBA_8888_SkColorType: | 501 case kRGBA_8888_SkColorType: |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 mipmap->fLevels = (Level*)mipmap->writable_data(); | 581 mipmap->fLevels = (Level*)mipmap->writable_data(); |
| 553 | 582 |
| 554 Level* levels = mipmap->fLevels; | 583 Level* levels = mipmap->fLevels; |
| 555 uint8_t* baseAddr = (uint8_t*)&levels[countLevels]; | 584 uint8_t* baseAddr = (uint8_t*)&levels[countLevels]; |
| 556 uint8_t* addr = baseAddr; | 585 uint8_t* addr = baseAddr; |
| 557 int width = src.width(); | 586 int width = src.width(); |
| 558 int height = src.height(); | 587 int height = src.height(); |
| 559 uint32_t rowBytes; | 588 uint32_t rowBytes; |
| 560 SkPixmap srcPM(srcPixmap); | 589 SkPixmap srcPM(srcPixmap); |
| 561 | 590 |
| 562 int prevW = width; | |
| 563 int prevH = height; | |
| 564 for (int i = 0; i < countLevels; ++i) { | 591 for (int i = 0; i < countLevels; ++i) { |
| 592 FilterProc* proc; |
| 593 if (height & 1) { // src-height is 3 |
| 594 if (width & 1) { // src-width is 3 |
| 595 proc = proc_3_3; |
| 596 } else { // src-width is 2 |
| 597 proc = proc_2_3; |
| 598 } |
| 599 } else { // src-height is 2 |
| 600 if (width & 1) { // src-width is 3 |
| 601 proc = proc_3_2; |
| 602 } else { // src-width is 2 |
| 603 proc = proc_2_2; |
| 604 } |
| 605 } |
| 565 width >>= 1; | 606 width >>= 1; |
| 566 height >>= 1; | 607 height >>= 1; |
| 567 rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); | 608 rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); |
| 568 | 609 |
| 569 levels[i].fPixels = addr; | 610 levels[i].fPixels = addr; |
| 570 levels[i].fWidth = width; | 611 levels[i].fWidth = width; |
| 571 levels[i].fHeight = height; | 612 levels[i].fHeight = height; |
| 572 levels[i].fRowBytes = rowBytes; | 613 levels[i].fRowBytes = rowBytes; |
| 573 levels[i].fScale = (float)width / src.width(); | 614 levels[i].fScale = (float)width / src.width(); |
| 574 | 615 |
| 575 SkPixmap dstPM(SkImageInfo::Make(width, height, ct, at), addr, rowBytes)
; | 616 SkPixmap dstPM(SkImageInfo::Make(width, height, ct, at), addr, rowBytes)
; |
| 576 | 617 |
| 577 const size_t pixelSize = srcPM.info().bytesPerPixel(); | |
| 578 | |
| 579 const void* srcBasePtr = srcPM.addr(); | 618 const void* srcBasePtr = srcPM.addr(); |
| 580 void* dstBasePtr = dstPM.writable_addr(); | 619 void* dstBasePtr = dstPM.writable_addr(); |
| 581 | 620 |
| 582 FilterProc* proc; | |
| 583 if (prevH & 1) { // src-height is 3 | |
| 584 if (prevW & 1) { // src-width is 3 | |
| 585 proc = proc_3_3; | |
| 586 } else { // src-width is 2 | |
| 587 proc = proc_2_3; | |
| 588 } | |
| 589 } else { // src-height is 2 | |
| 590 if (prevW & 1) { // src-width is 3 | |
| 591 proc = proc_3_2; | |
| 592 } else { // src-width is 2 | |
| 593 proc = proc_2_2; | |
| 594 } | |
| 595 } | |
| 596 | |
| 597 const size_t srcRB = srcPM.rowBytes(); | 621 const size_t srcRB = srcPM.rowBytes(); |
| 598 for (int y = 0; y < height; y++) { | 622 for (int y = 0; y < height; y++) { |
| 599 const void* srcPtr = srcBasePtr; | 623 proc(dstBasePtr, srcBasePtr, srcRB, width); |
| 600 void* dstPtr = dstBasePtr; | |
| 601 | |
| 602 for (int x = 0; x < width; x++) { | |
| 603 proc(dstPtr, srcPtr, srcRB); | |
| 604 srcPtr = (char*)srcPtr + pixelSize * 2; | |
| 605 dstPtr = (char*)dstPtr + pixelSize; | |
| 606 } | |
| 607 | |
| 608 srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows | 624 srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows |
| 609 dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes(); | 625 dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes(); |
| 610 } | 626 } |
| 611 srcPM = dstPM; | 627 srcPM = dstPM; |
| 612 addr += height * rowBytes; | 628 addr += height * rowBytes; |
| 613 prevW = width; | |
| 614 prevH = height; | |
| 615 } | 629 } |
| 616 SkASSERT(addr == baseAddr + size); | 630 SkASSERT(addr == baseAddr + size); |
| 617 | 631 |
| 618 return mipmap; | 632 return mipmap; |
| 619 } | 633 } |
| 620 #endif | 634 #endif |
| 621 | 635 |
| 622 /////////////////////////////////////////////////////////////////////////////// | 636 /////////////////////////////////////////////////////////////////////////////// |
| 623 | 637 |
| 624 bool SkMipMap::extractLevel(SkScalar scale, Level* levelPtr) const { | 638 bool SkMipMap::extractLevel(SkScalar scale, Level* levelPtr) const { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 645 } | 659 } |
| 646 | 660 |
| 647 if (level > fCount) { | 661 if (level > fCount) { |
| 648 level = fCount; | 662 level = fCount; |
| 649 } | 663 } |
| 650 if (levelPtr) { | 664 if (levelPtr) { |
| 651 *levelPtr = fLevels[level - 1]; | 665 *levelPtr = fLevels[level - 1]; |
| 652 } | 666 } |
| 653 return true; | 667 return true; |
| 654 } | 668 } |
| OLD | NEW |