SkBitmap.cpp revision eb9a46cbbb475e862a084aa2224ec18d4ac5e95b
1 2/* 3 * Copyright 2008 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkBitmap.h" 11#include "SkColorPriv.h" 12#include "SkDither.h" 13#include "SkFlattenable.h" 14#include "SkImagePriv.h" 15#include "SkMallocPixelRef.h" 16#include "SkMask.h" 17#include "SkOrderedReadBuffer.h" 18#include "SkOrderedWriteBuffer.h" 19#include "SkPixelRef.h" 20#include "SkThread.h" 21#include "SkUnPreMultiply.h" 22#include "SkUtils.h" 23#include "SkValidationUtils.h" 24#include "SkPackBits.h" 25#include <new> 26 27struct MipLevel { 28 void* fPixels; 29 uint32_t fRowBytes; 30 uint32_t fWidth, fHeight; 31}; 32 33struct SkBitmap::MipMap : SkNoncopyable { 34 int32_t fRefCnt; 35 int fLevelCount; 36// MipLevel fLevel[fLevelCount]; 37// Pixels[] 38 39 static MipMap* Alloc(int levelCount, size_t pixelSize) { 40 if (levelCount < 0) { 41 return NULL; 42 } 43 int64_t size = (levelCount + 1) * sizeof(MipLevel); 44 size += sizeof(MipMap) + pixelSize; 45 if (!sk_64_isS32(size)) { 46 return NULL; 47 } 48 MipMap* mm = (MipMap*)sk_malloc_throw(sk_64_asS32(size)); 49 mm->fRefCnt = 1; 50 mm->fLevelCount = levelCount; 51 return mm; 52 } 53 54 const MipLevel* levels() const { return (const MipLevel*)(this + 1); } 55 MipLevel* levels() { return (MipLevel*)(this + 1); } 56 57 const void* pixels() const { return levels() + fLevelCount; } 58 void* pixels() { return levels() + fLevelCount; } 59 60 void ref() { 61 if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) { 62 sk_throw(); 63 } 64 } 65 void unref() { 66 SkASSERT(fRefCnt > 0); 67 if (sk_atomic_dec(&fRefCnt) == 1) { 68 sk_free(this); 69 } 70 } 71}; 72 73/////////////////////////////////////////////////////////////////////////////// 74/////////////////////////////////////////////////////////////////////////////// 75 76SkBitmap::SkBitmap() { 77 sk_bzero(this, sizeof(*this)); 78} 79 80SkBitmap::SkBitmap(const SkBitmap& src) { 81 SkDEBUGCODE(src.validate();) 82 sk_bzero(this, sizeof(*this)); 83 *this = src; 84 SkDEBUGCODE(this->validate();) 85} 86 87SkBitmap::~SkBitmap() { 88 SkDEBUGCODE(this->validate();) 89 this->freePixels(); 90} 91 92SkBitmap& SkBitmap::operator=(const SkBitmap& src) { 93 if (this != &src) { 94 this->freePixels(); 95 memcpy(this, &src, sizeof(src)); 96 97 // inc src reference counts 98 SkSafeRef(src.fPixelRef); 99 SkSafeRef(src.fMipMap); 100 101 // we reset our locks if we get blown away 102 fPixelLockCount = 0; 103 104 if (fPixelRef) { 105 // ignore the values from the memcpy 106 fPixels = NULL; 107 fColorTable = NULL; 108 // Note that what to for genID is somewhat arbitrary. We have no 109 // way to track changes to raw pixels across multiple SkBitmaps. 110 // Would benefit from an SkRawPixelRef type created by 111 // setPixels. 112 // Just leave the memcpy'ed one but they'll get out of sync 113 // as soon either is modified. 114 } 115 } 116 117 SkDEBUGCODE(this->validate();) 118 return *this; 119} 120 121void SkBitmap::swap(SkBitmap& other) { 122 SkTSwap(fColorTable, other.fColorTable); 123 SkTSwap(fPixelRef, other.fPixelRef); 124 SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin); 125 SkTSwap(fPixelLockCount, other.fPixelLockCount); 126 SkTSwap(fMipMap, other.fMipMap); 127 SkTSwap(fPixels, other.fPixels); 128 SkTSwap(fRowBytes, other.fRowBytes); 129 SkTSwap(fWidth, other.fWidth); 130 SkTSwap(fHeight, other.fHeight); 131 SkTSwap(fConfig, other.fConfig); 132 SkTSwap(fAlphaType, other.fAlphaType); 133 SkTSwap(fFlags, other.fFlags); 134 SkTSwap(fBytesPerPixel, other.fBytesPerPixel); 135 136 SkDEBUGCODE(this->validate();) 137} 138 139void SkBitmap::reset() { 140 this->freePixels(); 141 sk_bzero(this, sizeof(*this)); 142} 143 144int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { 145 int bpp; 146 switch (config) { 147 case kNo_Config: 148 bpp = 0; // not applicable 149 break; 150 case kA8_Config: 151 case kIndex8_Config: 152 bpp = 1; 153 break; 154 case kRGB_565_Config: 155 case kARGB_4444_Config: 156 bpp = 2; 157 break; 158 case kARGB_8888_Config: 159 bpp = 4; 160 break; 161 default: 162 SkDEBUGFAIL("unknown config"); 163 bpp = 0; // error 164 break; 165 } 166 return bpp; 167} 168 169size_t SkBitmap::ComputeRowBytes(Config c, int width) { 170 if (width < 0) { 171 return 0; 172 } 173 174 int64_t rowBytes = 0; 175 176 switch (c) { 177 case kNo_Config: 178 break; 179 case kA8_Config: 180 case kIndex8_Config: 181 rowBytes = width; 182 break; 183 case kRGB_565_Config: 184 case kARGB_4444_Config: 185 // assign and then shift, so we don't overflow int 186 rowBytes = width; 187 rowBytes <<= 1; 188 break; 189 case kARGB_8888_Config: 190 // assign and then shift, so we don't overflow int 191 rowBytes = width; 192 rowBytes <<= 2; 193 break; 194 default: 195 SkDEBUGFAIL("unknown config"); 196 break; 197 } 198 return sk_64_isS32(rowBytes) ? sk_64_asS32(rowBytes) : 0; 199} 200 201int64_t SkBitmap::ComputeSize64(Config config, int width, int height) { 202 int64_t rowBytes = sk_64_mul(ComputeBytesPerPixel(config), width); 203 return rowBytes * height; 204} 205 206size_t SkBitmap::ComputeSize(Config c, int width, int height) { 207 int64_t size = SkBitmap::ComputeSize64(c, width, height); 208 return sk_64_isS32(size) ? sk_64_asS32(size) : 0; 209} 210 211int64_t SkBitmap::ComputeSafeSize64(Config config, 212 uint32_t width, 213 uint32_t height, 214 size_t rowBytes) { 215 int64_t safeSize = 0; 216 if (height > 0) { 217 int64_t lastRow = sk_64_mul(ComputeBytesPerPixel(config), width); 218 safeSize = sk_64_mul(height - 1, rowBytes) + lastRow; 219 } 220 SkASSERT(safeSize >= 0); 221 return safeSize; 222} 223 224size_t SkBitmap::ComputeSafeSize(Config config, 225 uint32_t width, 226 uint32_t height, 227 size_t rowBytes) { 228 int64_t safeSize = ComputeSafeSize64(config, width, height, rowBytes); 229 int32_t safeSize32 = (int32_t)safeSize; 230 231 if (safeSize32 != safeSize) { 232 safeSize32 = 0; 233 } 234 return safeSize32; 235} 236 237void SkBitmap::getBounds(SkRect* bounds) const { 238 SkASSERT(bounds); 239 bounds->set(0, 0, 240 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); 241} 242 243void SkBitmap::getBounds(SkIRect* bounds) const { 244 SkASSERT(bounds); 245 bounds->set(0, 0, fWidth, fHeight); 246} 247 248/////////////////////////////////////////////////////////////////////////////// 249 250static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType, 251 SkAlphaType* canonical = NULL) { 252 switch (config) { 253 case SkBitmap::kNo_Config: 254 alphaType = kIgnore_SkAlphaType; 255 break; 256 case SkBitmap::kA8_Config: 257 if (kUnpremul_SkAlphaType == alphaType) { 258 alphaType = kPremul_SkAlphaType; 259 } 260 // fall-through 261 case SkBitmap::kIndex8_Config: 262 case SkBitmap::kARGB_4444_Config: 263 case SkBitmap::kARGB_8888_Config: 264 if (kIgnore_SkAlphaType == alphaType) { 265 return false; 266 } 267 break; 268 case SkBitmap::kRGB_565_Config: 269 alphaType = kOpaque_SkAlphaType; 270 break; 271 default: 272 return false; 273 } 274 if (canonical) { 275 *canonical = alphaType; 276 } 277 return true; 278} 279 280bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, 281 SkAlphaType alphaType) { 282 if ((width | height) < 0) { 283 goto BAD_CONFIG; 284 } 285 if (rowBytes == 0) { 286 rowBytes = SkBitmap::ComputeRowBytes(config, width); 287 if (0 == rowBytes && kNo_Config != config && width > 0) { 288 goto BAD_CONFIG; 289 } 290 } 291 292 if (!validate_alphaType(config, alphaType, &alphaType)) { 293 goto BAD_CONFIG; 294 } 295 296 this->freePixels(); 297 298 fConfig = SkToU8(config); 299 fAlphaType = SkToU8(alphaType); 300 fWidth = width; 301 fHeight = height; 302 fRowBytes = SkToU32(rowBytes); 303 304 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(config); 305 306 SkDEBUGCODE(this->validate();) 307 return true; 308 309 // if we got here, we had an error, so we reset the bitmap to empty 310BAD_CONFIG: 311 this->reset(); 312 return false; 313} 314 315bool SkBitmap::setConfig(const SkImageInfo& info, size_t rowBytes) { 316 return this->setConfig(SkImageInfoToBitmapConfig(info), info.fWidth, 317 info.fHeight, rowBytes, info.fAlphaType); 318} 319 320bool SkBitmap::setAlphaType(SkAlphaType alphaType) { 321 if (!validate_alphaType(this->config(), alphaType, &alphaType)) { 322 return false; 323 } 324 fAlphaType = SkToU8(alphaType); 325 return true; 326} 327 328void SkBitmap::updatePixelsFromRef() const { 329 if (NULL != fPixelRef) { 330 if (fPixelLockCount > 0) { 331 SkASSERT(fPixelRef->isLocked()); 332 333 void* p = fPixelRef->pixels(); 334 if (NULL != p) { 335 p = (char*)p 336 + fPixelRefOrigin.fY * fRowBytes 337 + fPixelRefOrigin.fX * fBytesPerPixel; 338 } 339 fPixels = p; 340 fColorTable = fPixelRef->colorTable(); 341 } else { 342 SkASSERT(0 == fPixelLockCount); 343 fPixels = NULL; 344 fColorTable = NULL; 345 } 346 } 347} 348 349static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) { 350 SkColorType ct; 351 switch (config) { 352 case SkBitmap::kA8_Config: 353 ct = kAlpha_8_SkColorType; 354 break; 355 case SkBitmap::kIndex8_Config: 356 ct = kIndex_8_SkColorType; 357 break; 358 case SkBitmap::kRGB_565_Config: 359 ct = kRGB_565_SkColorType; 360 break; 361 case SkBitmap::kARGB_4444_Config: 362 ct = kARGB_4444_SkColorType; 363 break; 364 case SkBitmap::kARGB_8888_Config: 365 ct = kPMColor_SkColorType; 366 break; 367 case SkBitmap::kNo_Config: 368 default: 369 return false; 370 } 371 if (ctOut) { 372 *ctOut = ct; 373 } 374 return true; 375} 376 377bool SkBitmap::asImageInfo(SkImageInfo* info) const { 378 SkColorType ct; 379 if (!config_to_colorType(this->config(), &ct)) { 380 return false; 381 } 382 if (info) { 383 info->fWidth = fWidth; 384 info->fHeight = fHeight; 385 info->fAlphaType = this->alphaType(); 386 info->fColorType = ct; 387 } 388 return true; 389} 390 391SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { 392#ifdef SK_DEBUG 393 if (pr) { 394 SkImageInfo info; 395 if (this->asImageInfo(&info)) { 396 const SkImageInfo& prInfo = pr->info(); 397 SkASSERT(info.fWidth <= prInfo.fWidth); 398 SkASSERT(info.fHeight <= prInfo.fHeight); 399 SkASSERT(info.fColorType == prInfo.fColorType); 400 switch (prInfo.fAlphaType) { 401 case kIgnore_SkAlphaType: 402 SkASSERT(fAlphaType == kIgnore_SkAlphaType); 403 break; 404 case kOpaque_SkAlphaType: 405 case kPremul_SkAlphaType: 406 SkASSERT(info.fAlphaType == kOpaque_SkAlphaType || 407 info.fAlphaType == kPremul_SkAlphaType); 408 break; 409 case kUnpremul_SkAlphaType: 410 SkASSERT(info.fAlphaType == kOpaque_SkAlphaType || 411 info.fAlphaType == kUnpremul_SkAlphaType); 412 break; 413 } 414 } 415 } 416#endif 417 418 if (pr) { 419 const SkImageInfo& info = pr->info(); 420 fPixelRefOrigin.set(SkPin32(dx, 0, info.fWidth), 421 SkPin32(dy, 0, info.fHeight)); 422 } else { 423 // ignore dx,dy if there is no pixelref 424 fPixelRefOrigin.setZero(); 425 } 426 427 if (fPixelRef != pr) { 428 if (fPixelRef != pr) { 429 this->freePixels(); 430 SkASSERT(NULL == fPixelRef); 431 432 SkSafeRef(pr); 433 fPixelRef = pr; 434 } 435 this->updatePixelsFromRef(); 436 } 437 438 SkDEBUGCODE(this->validate();) 439 return pr; 440} 441 442void SkBitmap::lockPixels() const { 443 if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) { 444 fPixelRef->lockPixels(); 445 this->updatePixelsFromRef(); 446 } 447 SkDEBUGCODE(this->validate();) 448} 449 450void SkBitmap::unlockPixels() const { 451 SkASSERT(NULL == fPixelRef || fPixelLockCount > 0); 452 453 if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) { 454 fPixelRef->unlockPixels(); 455 this->updatePixelsFromRef(); 456 } 457 SkDEBUGCODE(this->validate();) 458} 459 460bool SkBitmap::lockPixelsAreWritable() const { 461 return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false; 462} 463 464void SkBitmap::setPixels(void* p, SkColorTable* ctable) { 465 if (NULL == p) { 466 this->setPixelRef(NULL); 467 return; 468 } 469 470 SkImageInfo info; 471 if (!this->asImageInfo(&info)) { 472 this->setPixelRef(NULL); 473 return; 474 } 475 476 SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable); 477 if (NULL == pr) { 478 this->setPixelRef(NULL); 479 return; 480 } 481 482 this->setPixelRef(pr)->unref(); 483 484 // since we're already allocated, we lockPixels right away 485 this->lockPixels(); 486 SkDEBUGCODE(this->validate();) 487} 488 489bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) { 490 HeapAllocator stdalloc; 491 492 if (NULL == allocator) { 493 allocator = &stdalloc; 494 } 495 return allocator->allocPixelRef(this, ctable); 496} 497 498/////////////////////////////////////////////////////////////////////////////// 499 500static bool reset_return_false(SkBitmap* bm) { 501 bm->reset(); 502 return false; 503} 504 505bool SkBitmap::allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory, 506 SkColorTable* ctable) { 507 if (kIndex_8_SkColorType == info.fColorType && NULL == ctable) { 508 return reset_return_false(this); 509 } 510 if (!this->setConfig(info)) { 511 return reset_return_false(this); 512 } 513 514 SkMallocPixelRef::PRFactory defaultFactory; 515 if (NULL == factory) { 516 factory = &defaultFactory; 517 } 518 519 SkPixelRef* pr = factory->create(info, ctable); 520 if (NULL == pr) { 521 return reset_return_false(this); 522 } 523 this->setPixelRef(pr)->unref(); 524 525 // TODO: lockPixels could/should return bool or void*/NULL 526 this->lockPixels(); 527 if (NULL == this->getPixels()) { 528 return reset_return_false(this); 529 } 530 return true; 531} 532 533bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb, 534 void (*releaseProc)(void* addr, void* context), 535 void* context) { 536 if (!this->setConfig(info)) { 537 this->reset(); 538 return false; 539 } 540 541 SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, NULL, pixels, 542 releaseProc, context); 543 if (!pr) { 544 this->reset(); 545 return false; 546 } 547 548 this->setPixelRef(pr)->unref(); 549 return true; 550} 551 552bool SkBitmap::allocConfigPixels(Config config, int width, int height, 553 bool isOpaque) { 554 SkColorType ct; 555 if (!config_to_colorType(config, &ct)) { 556 return false; 557 } 558 559 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 560 if (!validate_alphaType(config, at, &at)) { 561 return false; 562 } 563 564 return this->allocPixels(SkImageInfo::Make(width, height, ct, at)); 565} 566 567/////////////////////////////////////////////////////////////////////////////// 568 569void SkBitmap::freePixels() { 570 // if we're gonna free the pixels, we certainly need to free the mipmap 571 this->freeMipMap(); 572 573 if (NULL != fPixelRef) { 574 if (fPixelLockCount > 0) { 575 fPixelRef->unlockPixels(); 576 } 577 fPixelRef->unref(); 578 fPixelRef = NULL; 579 fPixelRefOrigin.setZero(); 580 } 581 fPixelLockCount = 0; 582 fPixels = NULL; 583 fColorTable = NULL; 584} 585 586void SkBitmap::freeMipMap() { 587 if (fMipMap) { 588 fMipMap->unref(); 589 fMipMap = NULL; 590 } 591} 592 593uint32_t SkBitmap::getGenerationID() const { 594 return (fPixelRef) ? fPixelRef->getGenerationID() : 0; 595} 596 597void SkBitmap::notifyPixelsChanged() const { 598 SkASSERT(!this->isImmutable()); 599 if (fPixelRef) { 600 fPixelRef->notifyPixelsChanged(); 601 } 602} 603 604GrTexture* SkBitmap::getTexture() const { 605 return fPixelRef ? fPixelRef->getTexture() : NULL; 606} 607 608/////////////////////////////////////////////////////////////////////////////// 609 610/** We explicitly use the same allocator for our pixels that SkMask does, 611 so that we can freely assign memory allocated by one class to the other. 612 */ 613bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, 614 SkColorTable* ctable) { 615 SkImageInfo info; 616 if (!dst->asImageInfo(&info)) { 617// SkDebugf("unsupported config for info %d\n", dst->config()); 618 return false; 619 } 620 621 SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), 622 ctable); 623 if (NULL == pr) { 624 return false; 625 } 626 627 dst->setPixelRef(pr)->unref(); 628 // since we're already allocated, we lockPixels right away 629 dst->lockPixels(); 630 return true; 631} 632 633/////////////////////////////////////////////////////////////////////////////// 634 635size_t SkBitmap::getSafeSize() const { 636 // This is intended to be a size_t version of ComputeSafeSize64(), just 637 // faster. The computation is meant to be identical. 638 return (fHeight ? ((fHeight - 1) * fRowBytes) + 639 ComputeRowBytes(this->config(), fWidth): 0); 640} 641 642bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize, 643 size_t dstRowBytes, bool preserveDstPad) const { 644 645 if (0 == dstRowBytes) { 646 dstRowBytes = fRowBytes; 647 } 648 649 if (dstRowBytes < ComputeRowBytes(this->config(), fWidth) || 650 dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) 651 return false; 652 653 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) { 654 size_t safeSize = this->getSafeSize(); 655 if (safeSize > dstSize || safeSize == 0) 656 return false; 657 else { 658 SkAutoLockPixels lock(*this); 659 // This implementation will write bytes beyond the end of each row, 660 // excluding the last row, if the bitmap's stride is greater than 661 // strictly required by the current config. 662 memcpy(dst, getPixels(), safeSize); 663 664 return true; 665 } 666 } else { 667 // If destination has different stride than us, then copy line by line. 668 if (ComputeSafeSize(this->config(), fWidth, fHeight, dstRowBytes) > 669 dstSize) 670 return false; 671 else { 672 // Just copy what we need on each line. 673 size_t rowBytes = ComputeRowBytes(this->config(), fWidth); 674 SkAutoLockPixels lock(*this); 675 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels()); 676 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); 677 for (uint32_t row = 0; row < fHeight; 678 row++, srcP += fRowBytes, dstP += dstRowBytes) { 679 memcpy(dstP, srcP, rowBytes); 680 } 681 682 return true; 683 } 684 } 685} 686 687/////////////////////////////////////////////////////////////////////////////// 688 689bool SkBitmap::isImmutable() const { 690 return fPixelRef ? fPixelRef->isImmutable() : 691 fFlags & kImageIsImmutable_Flag; 692} 693 694void SkBitmap::setImmutable() { 695 if (fPixelRef) { 696 fPixelRef->setImmutable(); 697 } else { 698 fFlags |= kImageIsImmutable_Flag; 699 } 700} 701 702bool SkBitmap::isVolatile() const { 703 return (fFlags & kImageIsVolatile_Flag) != 0; 704} 705 706void SkBitmap::setIsVolatile(bool isVolatile) { 707 if (isVolatile) { 708 fFlags |= kImageIsVolatile_Flag; 709 } else { 710 fFlags &= ~kImageIsVolatile_Flag; 711 } 712} 713 714void* SkBitmap::getAddr(int x, int y) const { 715 SkASSERT((unsigned)x < (unsigned)this->width()); 716 SkASSERT((unsigned)y < (unsigned)this->height()); 717 718 char* base = (char*)this->getPixels(); 719 if (base) { 720 base += y * this->rowBytes(); 721 switch (this->config()) { 722 case SkBitmap::kARGB_8888_Config: 723 base += x << 2; 724 break; 725 case SkBitmap::kARGB_4444_Config: 726 case SkBitmap::kRGB_565_Config: 727 base += x << 1; 728 break; 729 case SkBitmap::kA8_Config: 730 case SkBitmap::kIndex8_Config: 731 base += x; 732 break; 733 break; 734 default: 735 SkDEBUGFAIL("Can't return addr for config"); 736 base = NULL; 737 break; 738 } 739 } 740 return base; 741} 742 743SkColor SkBitmap::getColor(int x, int y) const { 744 SkASSERT((unsigned)x < (unsigned)this->width()); 745 SkASSERT((unsigned)y < (unsigned)this->height()); 746 747 switch (this->config()) { 748 case SkBitmap::kA8_Config: { 749 uint8_t* addr = this->getAddr8(x, y); 750 return SkColorSetA(0, addr[0]); 751 } 752 case SkBitmap::kIndex8_Config: { 753 SkPMColor c = this->getIndex8Color(x, y); 754 return SkUnPreMultiply::PMColorToColor(c); 755 } 756 case SkBitmap::kRGB_565_Config: { 757 uint16_t* addr = this->getAddr16(x, y); 758 return SkPixel16ToColor(addr[0]); 759 } 760 case SkBitmap::kARGB_4444_Config: { 761 uint16_t* addr = this->getAddr16(x, y); 762 SkPMColor c = SkPixel4444ToPixel32(addr[0]); 763 return SkUnPreMultiply::PMColorToColor(c); 764 } 765 case SkBitmap::kARGB_8888_Config: { 766 uint32_t* addr = this->getAddr32(x, y); 767 return SkUnPreMultiply::PMColorToColor(addr[0]); 768 } 769 case kNo_Config: 770 default: 771 SkASSERT(false); 772 return 0; 773 } 774 SkASSERT(false); // Not reached. 775 return 0; 776} 777 778bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { 779 SkAutoLockPixels alp(bm); 780 if (!bm.getPixels()) { 781 return false; 782 } 783 784 const int height = bm.height(); 785 const int width = bm.width(); 786 787 switch (bm.config()) { 788 case SkBitmap::kA8_Config: { 789 unsigned a = 0xFF; 790 for (int y = 0; y < height; ++y) { 791 const uint8_t* row = bm.getAddr8(0, y); 792 for (int x = 0; x < width; ++x) { 793 a &= row[x]; 794 } 795 if (0xFF != a) { 796 return false; 797 } 798 } 799 return true; 800 } break; 801 case SkBitmap::kIndex8_Config: { 802 SkAutoLockColors alc(bm); 803 const SkPMColor* table = alc.colors(); 804 if (!table) { 805 return false; 806 } 807 SkPMColor c = (SkPMColor)~0; 808 for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) { 809 c &= table[i]; 810 } 811 return 0xFF == SkGetPackedA32(c); 812 } break; 813 case SkBitmap::kRGB_565_Config: 814 return true; 815 break; 816 case SkBitmap::kARGB_4444_Config: { 817 unsigned c = 0xFFFF; 818 for (int y = 0; y < height; ++y) { 819 const SkPMColor16* row = bm.getAddr16(0, y); 820 for (int x = 0; x < width; ++x) { 821 c &= row[x]; 822 } 823 if (0xF != SkGetPackedA4444(c)) { 824 return false; 825 } 826 } 827 return true; 828 } break; 829 case SkBitmap::kARGB_8888_Config: { 830 SkPMColor c = (SkPMColor)~0; 831 for (int y = 0; y < height; ++y) { 832 const SkPMColor* row = bm.getAddr32(0, y); 833 for (int x = 0; x < width; ++x) { 834 c &= row[x]; 835 } 836 if (0xFF != SkGetPackedA32(c)) { 837 return false; 838 } 839 } 840 return true; 841 } 842 default: 843 break; 844 } 845 return false; 846} 847 848 849/////////////////////////////////////////////////////////////////////////////// 850/////////////////////////////////////////////////////////////////////////////// 851 852static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) { 853 unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | 854 (SkR32To4444(r) << SK_R4444_SHIFT) | 855 (SkG32To4444(g) << SK_G4444_SHIFT) | 856 (SkB32To4444(b) << SK_B4444_SHIFT); 857 return SkToU16(pixel); 858} 859 860void SkBitmap::internalErase(const SkIRect& area, 861 U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 862#ifdef SK_DEBUG 863 SkDEBUGCODE(this->validate();) 864 SkASSERT(!area.isEmpty()); 865 { 866 SkIRect total = { 0, 0, this->width(), this->height() }; 867 SkASSERT(total.contains(area)); 868 } 869#endif 870 871 if (kNo_Config == fConfig || kIndex8_Config == fConfig) { 872 return; 873 } 874 875 SkAutoLockPixels alp(*this); 876 // perform this check after the lock call 877 if (!this->readyToDraw()) { 878 return; 879 } 880 881 int height = area.height(); 882 const int width = area.width(); 883 const int rowBytes = fRowBytes; 884 885 // make rgb premultiplied 886 if (255 != a) { 887 r = SkAlphaMul(r, a); 888 g = SkAlphaMul(g, a); 889 b = SkAlphaMul(b, a); 890 } 891 892 switch (fConfig) { 893 case kA8_Config: { 894 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); 895 while (--height >= 0) { 896 memset(p, a, width); 897 p += rowBytes; 898 } 899 break; 900 } 901 case kARGB_4444_Config: 902 case kRGB_565_Config: { 903 uint16_t* p = this->getAddr16(area.fLeft, area.fTop);; 904 uint16_t v; 905 906 if (kARGB_4444_Config == fConfig) { 907 v = pack_8888_to_4444(a, r, g, b); 908 } else { 909 v = SkPackRGB16(r >> (8 - SK_R16_BITS), 910 g >> (8 - SK_G16_BITS), 911 b >> (8 - SK_B16_BITS)); 912 } 913 while (--height >= 0) { 914 sk_memset16(p, v, width); 915 p = (uint16_t*)((char*)p + rowBytes); 916 } 917 break; 918 } 919 case kARGB_8888_Config: { 920 uint32_t* p = this->getAddr32(area.fLeft, area.fTop); 921 uint32_t v = SkPackARGB32(a, r, g, b); 922 923 while (--height >= 0) { 924 sk_memset32(p, v, width); 925 p = (uint32_t*)((char*)p + rowBytes); 926 } 927 break; 928 } 929 } 930 931 this->notifyPixelsChanged(); 932} 933 934void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 935 SkIRect area = { 0, 0, this->width(), this->height() }; 936 if (!area.isEmpty()) { 937 this->internalErase(area, a, r, g, b); 938 } 939} 940 941void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { 942 SkIRect area = { 0, 0, this->width(), this->height() }; 943 if (area.intersect(rect)) { 944 this->internalErase(area, SkColorGetA(c), SkColorGetR(c), 945 SkColorGetG(c), SkColorGetB(c)); 946 } 947} 948 949////////////////////////////////////////////////////////////////////////////////////// 950////////////////////////////////////////////////////////////////////////////////////// 951 952bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { 953 SkDEBUGCODE(this->validate();) 954 955 if (NULL == result || NULL == fPixelRef) { 956 return false; // no src pixels 957 } 958 959 SkIRect srcRect, r; 960 srcRect.set(0, 0, this->width(), this->height()); 961 if (!r.intersect(srcRect, subset)) { 962 return false; // r is empty (i.e. no intersection) 963 } 964 965 if (fPixelRef->getTexture() != NULL) { 966 // Do a deep copy 967 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); 968 if (pixelRef != NULL) { 969 SkBitmap dst; 970 dst.setConfig(this->config(), subset.width(), subset.height(), 0, 971 this->alphaType()); 972 dst.setIsVolatile(this->isVolatile()); 973 dst.setPixelRef(pixelRef)->unref(); 974 SkDEBUGCODE(dst.validate()); 975 result->swap(dst); 976 return true; 977 } 978 } 979 980 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 981 // exited above. 982 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 983 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 984 985 SkBitmap dst; 986 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), 987 this->alphaType()); 988 dst.setIsVolatile(this->isVolatile()); 989 990 if (fPixelRef) { 991 SkIPoint origin = fPixelRefOrigin; 992 origin.fX += r.fLeft; 993 origin.fY += r.fTop; 994 // share the pixelref with a custom offset 995 dst.setPixelRef(fPixelRef, origin); 996 } 997 SkDEBUGCODE(dst.validate();) 998 999 // we know we're good, so commit to result 1000 result->swap(dst); 1001 return true; 1002} 1003 1004/////////////////////////////////////////////////////////////////////////////// 1005 1006#include "SkCanvas.h" 1007#include "SkPaint.h" 1008 1009bool SkBitmap::canCopyTo(Config dstConfig) const { 1010 if (this->config() == kNo_Config) { 1011 return false; 1012 } 1013 1014 bool sameConfigs = (this->config() == dstConfig); 1015 switch (dstConfig) { 1016 case kA8_Config: 1017 case kRGB_565_Config: 1018 case kARGB_8888_Config: 1019 break; 1020 case kIndex8_Config: 1021 if (!sameConfigs) { 1022 return false; 1023 } 1024 break; 1025 case kARGB_4444_Config: 1026 return sameConfigs || kARGB_8888_Config == this->config(); 1027 default: 1028 return false; 1029 } 1030 return true; 1031} 1032 1033bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { 1034 if (!this->canCopyTo(dstConfig)) { 1035 return false; 1036 } 1037 1038 // if we have a texture, first get those pixels 1039 SkBitmap tmpSrc; 1040 const SkBitmap* src = this; 1041 1042 if (fPixelRef) { 1043 SkIRect subset; 1044 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, fWidth, fHeight); 1045 if (fPixelRef->readPixels(&tmpSrc, &subset)) { 1046 SkASSERT(tmpSrc.width() == this->width()); 1047 SkASSERT(tmpSrc.height() == this->height()); 1048 1049 // did we get lucky and we can just return tmpSrc? 1050 if (tmpSrc.config() == dstConfig && NULL == alloc) { 1051 dst->swap(tmpSrc); 1052 // If the result is an exact copy, clone the gen ID. 1053 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) { 1054 dst->pixelRef()->cloneGenID(*fPixelRef); 1055 } 1056 return true; 1057 } 1058 1059 // fall through to the raster case 1060 src = &tmpSrc; 1061 } 1062 } 1063 1064 // we lock this now, since we may need its colortable 1065 SkAutoLockPixels srclock(*src); 1066 if (!src->readyToDraw()) { 1067 return false; 1068 } 1069 1070 // The only way to be readyToDraw is if fPixelRef is non NULL. 1071 SkASSERT(fPixelRef != NULL); 1072 1073 SkBitmap tmpDst; 1074 tmpDst.setConfig(dstConfig, src->width(), src->height(), 0, 1075 src->alphaType()); 1076 1077 // allocate colortable if srcConfig == kIndex8_Config 1078 SkColorTable* ctable = (dstConfig == kIndex8_Config) ? 1079 new SkColorTable(*src->getColorTable()) : NULL; 1080 SkAutoUnref au(ctable); 1081 if (!tmpDst.allocPixels(alloc, ctable)) { 1082 return false; 1083 } 1084 1085 if (!tmpDst.readyToDraw()) { 1086 // allocator/lock failed 1087 return false; 1088 } 1089 1090 // pixelRef must be non NULL or tmpDst.readyToDraw() would have 1091 // returned false. 1092 SkASSERT(tmpDst.pixelRef() != NULL); 1093 1094 /* do memcpy for the same configs cases, else use drawing 1095 */ 1096 if (src->config() == dstConfig) { 1097 if (tmpDst.getSize() == src->getSize()) { 1098 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); 1099 SkPixelRef* pixelRef = tmpDst.pixelRef(); 1100 1101 // In order to reach this point, we know that the width, config and 1102 // rowbytes of the SkPixelRefs are the same, but it is possible for 1103 // the heights to differ, if this SkBitmap's height is a subset of 1104 // fPixelRef. Only if the SkPixelRefs' heights match are we 1105 // guaranteed that this is an exact copy, meaning we should clone 1106 // the genID. 1107 if (pixelRef->info().fHeight == fPixelRef->info().fHeight) { 1108 // TODO: what to do if the two infos match, BUT 1109 // fPixelRef is premul and pixelRef is opaque? 1110 // skipping assert for now 1111 // https://code.google.com/p/skia/issues/detail?id=2012 1112// SkASSERT(pixelRef->info() == fPixelRef->info()); 1113 SkASSERT(pixelRef->info().fWidth == fPixelRef->info().fWidth); 1114 SkASSERT(pixelRef->info().fColorType == fPixelRef->info().fColorType); 1115 pixelRef->cloneGenID(*fPixelRef); 1116 } 1117 } else { 1118 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); 1119 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); 1120 // to be sure we don't read too much, only copy our logical pixels 1121 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); 1122 for (int y = 0; y < tmpDst.height(); y++) { 1123 memcpy(dstP, srcP, bytesToCopy); 1124 srcP += src->rowBytes(); 1125 dstP += tmpDst.rowBytes(); 1126 } 1127 } 1128 } else if (SkBitmap::kARGB_4444_Config == dstConfig 1129 && SkBitmap::kARGB_8888_Config == src->config()) { 1130 SkASSERT(src->height() == tmpDst.height()); 1131 SkASSERT(src->width() == tmpDst.width()); 1132 for (int y = 0; y < src->height(); ++y) { 1133 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); 1134 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); 1135 DITHER_4444_SCAN(y); 1136 for (int x = 0; x < src->width(); ++x) { 1137 dstRow[x] = SkDitherARGB32To4444(srcRow[x], 1138 DITHER_VALUE(x)); 1139 } 1140 } 1141 } else { 1142 // Always clear the dest in case one of the blitters accesses it 1143 // TODO: switch the allocation of tmpDst to call sk_calloc_throw 1144 tmpDst.eraseColor(SK_ColorTRANSPARENT); 1145 1146 SkCanvas canvas(tmpDst); 1147 SkPaint paint; 1148 1149 paint.setDither(true); 1150 canvas.drawBitmap(*src, 0, 0, &paint); 1151 } 1152 1153 dst->swap(tmpDst); 1154 return true; 1155} 1156 1157bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { 1158 if (!this->canCopyTo(dstConfig)) { 1159 return false; 1160 } 1161 1162 // If we have a PixelRef, and it supports deep copy, use it. 1163 // Currently supported only by texture-backed bitmaps. 1164 if (fPixelRef) { 1165 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); 1166 if (pixelRef) { 1167 uint32_t rowBytes; 1168 if (dstConfig == fConfig) { 1169 // Since there is no subset to pass to deepCopy, and deepCopy 1170 // succeeded, the new pixel ref must be identical. 1171 SkASSERT(fPixelRef->info() == pixelRef->info()); 1172 pixelRef->cloneGenID(*fPixelRef); 1173 // Use the same rowBytes as the original. 1174 rowBytes = fRowBytes; 1175 } else { 1176 // With the new config, an appropriate fRowBytes will be computed by setConfig. 1177 rowBytes = 0; 1178 } 1179 dst->setConfig(dstConfig, fWidth, fHeight, rowBytes); 1180 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); 1181 return true; 1182 } 1183 } 1184 1185 if (this->getTexture()) { 1186 return false; 1187 } else { 1188 return this->copyTo(dst, dstConfig, NULL); 1189 } 1190} 1191 1192/////////////////////////////////////////////////////////////////////////////// 1193/////////////////////////////////////////////////////////////////////////////// 1194 1195static void downsampleby2_proc32(SkBitmap* dst, int x, int y, 1196 const SkBitmap& src) { 1197 x <<= 1; 1198 y <<= 1; 1199 const SkPMColor* p = src.getAddr32(x, y); 1200 const SkPMColor* baseP = p; 1201 SkPMColor c, ag, rb; 1202 1203 c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF; 1204 if (x < src.width() - 1) { 1205 p += 1; 1206 } 1207 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1208 1209 p = baseP; 1210 if (y < src.height() - 1) { 1211 p += src.rowBytes() >> 2; 1212 } 1213 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1214 if (x < src.width() - 1) { 1215 p += 1; 1216 } 1217 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1218 1219 *dst->getAddr32(x >> 1, y >> 1) = 1220 ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00); 1221} 1222 1223static inline uint32_t expand16(U16CPU c) { 1224 return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16); 1225} 1226 1227// returns dirt in the top 16bits, but we don't care, since we only 1228// store the low 16bits. 1229static inline U16CPU pack16(uint32_t c) { 1230 return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE); 1231} 1232 1233static void downsampleby2_proc16(SkBitmap* dst, int x, int y, 1234 const SkBitmap& src) { 1235 x <<= 1; 1236 y <<= 1; 1237 const uint16_t* p = src.getAddr16(x, y); 1238 const uint16_t* baseP = p; 1239 SkPMColor c; 1240 1241 c = expand16(*p); 1242 if (x < src.width() - 1) { 1243 p += 1; 1244 } 1245 c += expand16(*p); 1246 1247 p = baseP; 1248 if (y < src.height() - 1) { 1249 p += src.rowBytes() >> 1; 1250 } 1251 c += expand16(*p); 1252 if (x < src.width() - 1) { 1253 p += 1; 1254 } 1255 c += expand16(*p); 1256 1257 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2); 1258} 1259 1260static uint32_t expand4444(U16CPU c) { 1261 return (c & 0xF0F) | ((c & ~0xF0F) << 12); 1262} 1263 1264static U16CPU collaps4444(uint32_t c) { 1265 return (c & 0xF0F) | ((c >> 12) & ~0xF0F); 1266} 1267 1268static void downsampleby2_proc4444(SkBitmap* dst, int x, int y, 1269 const SkBitmap& src) { 1270 x <<= 1; 1271 y <<= 1; 1272 const uint16_t* p = src.getAddr16(x, y); 1273 const uint16_t* baseP = p; 1274 uint32_t c; 1275 1276 c = expand4444(*p); 1277 if (x < src.width() - 1) { 1278 p += 1; 1279 } 1280 c += expand4444(*p); 1281 1282 p = baseP; 1283 if (y < src.height() - 1) { 1284 p += src.rowBytes() >> 1; 1285 } 1286 c += expand4444(*p); 1287 if (x < src.width() - 1) { 1288 p += 1; 1289 } 1290 c += expand4444(*p); 1291 1292 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2); 1293} 1294 1295void SkBitmap::buildMipMap(bool forceRebuild) { 1296 if (forceRebuild) 1297 this->freeMipMap(); 1298 else if (fMipMap) 1299 return; // we're already built 1300 1301 SkASSERT(NULL == fMipMap); 1302 1303 void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src); 1304 1305 const SkBitmap::Config config = this->config(); 1306 1307 switch (config) { 1308 case kARGB_8888_Config: 1309 proc = downsampleby2_proc32; 1310 break; 1311 case kRGB_565_Config: 1312 proc = downsampleby2_proc16; 1313 break; 1314 case kARGB_4444_Config: 1315 proc = downsampleby2_proc4444; 1316 break; 1317 case kIndex8_Config: 1318 case kA8_Config: 1319 default: 1320 return; // don't build mipmaps for these configs 1321 } 1322 1323 SkAutoLockPixels alp(*this); 1324 if (!this->readyToDraw()) { 1325 return; 1326 } 1327 1328 // whip through our loop to compute the exact size needed 1329 size_t size = 0; 1330 int maxLevels = 0; 1331 { 1332 int width = this->width(); 1333 int height = this->height(); 1334 for (;;) { 1335 width >>= 1; 1336 height >>= 1; 1337 if (0 == width || 0 == height) { 1338 break; 1339 } 1340 size += ComputeRowBytes(config, width) * height; 1341 maxLevels += 1; 1342 } 1343 } 1344 1345 // nothing to build 1346 if (0 == maxLevels) { 1347 return; 1348 } 1349 1350 SkBitmap srcBM(*this); 1351 srcBM.lockPixels(); 1352 if (!srcBM.readyToDraw()) { 1353 return; 1354 } 1355 1356 MipMap* mm = MipMap::Alloc(maxLevels, size); 1357 if (NULL == mm) { 1358 return; 1359 } 1360 1361 MipLevel* level = mm->levels(); 1362 uint8_t* addr = (uint8_t*)mm->pixels(); 1363 int width = this->width(); 1364 int height = this->height(); 1365 uint32_t rowBytes; 1366 SkBitmap dstBM; 1367 1368 for (int i = 0; i < maxLevels; i++) { 1369 width >>= 1; 1370 height >>= 1; 1371 rowBytes = SkToU32(ComputeRowBytes(config, width)); 1372 1373 level[i].fPixels = addr; 1374 level[i].fWidth = width; 1375 level[i].fHeight = height; 1376 level[i].fRowBytes = rowBytes; 1377 1378 dstBM.setConfig(config, width, height, rowBytes); 1379 dstBM.setPixels(addr); 1380 1381 srcBM.lockPixels(); 1382 for (int y = 0; y < height; y++) { 1383 for (int x = 0; x < width; x++) { 1384 proc(&dstBM, x, y, srcBM); 1385 } 1386 } 1387 srcBM.unlockPixels(); 1388 1389 srcBM = dstBM; 1390 addr += height * rowBytes; 1391 } 1392 SkASSERT(addr == (uint8_t*)mm->pixels() + size); 1393 fMipMap = mm; 1394} 1395 1396bool SkBitmap::hasMipMap() const { 1397 return fMipMap != NULL; 1398} 1399 1400int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) { 1401 if (NULL == fMipMap) { 1402 return 0; 1403 } 1404 1405 int level = ComputeMipLevel(sx, sy) >> 16; 1406 SkASSERT(level >= 0); 1407 if (level <= 0) { 1408 return 0; 1409 } 1410 1411 if (level >= fMipMap->fLevelCount) { 1412 level = fMipMap->fLevelCount - 1; 1413 } 1414 if (dst) { 1415 const MipLevel& mip = fMipMap->levels()[level - 1]; 1416 dst->setConfig((SkBitmap::Config)this->config(), 1417 mip.fWidth, mip.fHeight, mip.fRowBytes); 1418 dst->setPixels(mip.fPixels); 1419 } 1420 return level; 1421} 1422 1423SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) { 1424 sx = SkAbs32(sx); 1425 sy = SkAbs32(sy); 1426 if (sx < sy) { 1427 sx = sy; 1428 } 1429 if (sx < SK_Fixed1) { 1430 return 0; 1431 } 1432 int clz = SkCLZ(sx); 1433 SkASSERT(clz >= 1 && clz <= 15); 1434 return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16); 1435} 1436 1437/////////////////////////////////////////////////////////////////////////////// 1438 1439static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, 1440 int alphaRowBytes) { 1441 SkASSERT(alpha != NULL); 1442 SkASSERT(alphaRowBytes >= src.width()); 1443 1444 SkBitmap::Config config = src.config(); 1445 int w = src.width(); 1446 int h = src.height(); 1447 size_t rb = src.rowBytes(); 1448 1449 SkAutoLockPixels alp(src); 1450 if (!src.readyToDraw()) { 1451 // zero out the alpha buffer and return 1452 while (--h >= 0) { 1453 memset(alpha, 0, w); 1454 alpha += alphaRowBytes; 1455 } 1456 return false; 1457 } 1458 1459 if (SkBitmap::kA8_Config == config && !src.isOpaque()) { 1460 const uint8_t* s = src.getAddr8(0, 0); 1461 while (--h >= 0) { 1462 memcpy(alpha, s, w); 1463 s += rb; 1464 alpha += alphaRowBytes; 1465 } 1466 } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) { 1467 const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0); 1468 while (--h >= 0) { 1469 for (int x = 0; x < w; x++) { 1470 alpha[x] = SkGetPackedA32(s[x]); 1471 } 1472 s = (const SkPMColor*)((const char*)s + rb); 1473 alpha += alphaRowBytes; 1474 } 1475 } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) { 1476 const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0); 1477 while (--h >= 0) { 1478 for (int x = 0; x < w; x++) { 1479 alpha[x] = SkPacked4444ToA32(s[x]); 1480 } 1481 s = (const SkPMColor16*)((const char*)s + rb); 1482 alpha += alphaRowBytes; 1483 } 1484 } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) { 1485 SkColorTable* ct = src.getColorTable(); 1486 if (ct) { 1487 const SkPMColor* SK_RESTRICT table = ct->lockColors(); 1488 const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0); 1489 while (--h >= 0) { 1490 for (int x = 0; x < w; x++) { 1491 alpha[x] = SkGetPackedA32(table[s[x]]); 1492 } 1493 s += rb; 1494 alpha += alphaRowBytes; 1495 } 1496 ct->unlockColors(); 1497 } 1498 } else { // src is opaque, so just fill alpha[] with 0xFF 1499 memset(alpha, 0xFF, h * alphaRowBytes); 1500 } 1501 return true; 1502} 1503 1504#include "SkPaint.h" 1505#include "SkMaskFilter.h" 1506#include "SkMatrix.h" 1507 1508bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, 1509 Allocator *allocator, SkIPoint* offset) const { 1510 SkDEBUGCODE(this->validate();) 1511 1512 SkBitmap tmpBitmap; 1513 SkMatrix identity; 1514 SkMask srcM, dstM; 1515 1516 srcM.fBounds.set(0, 0, this->width(), this->height()); 1517 srcM.fRowBytes = SkAlign4(this->width()); 1518 srcM.fFormat = SkMask::kA8_Format; 1519 1520 SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL; 1521 1522 // compute our (larger?) dst bounds if we have a filter 1523 if (NULL != filter) { 1524 identity.reset(); 1525 srcM.fImage = NULL; 1526 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1527 goto NO_FILTER_CASE; 1528 } 1529 dstM.fRowBytes = SkAlign4(dstM.fBounds.width()); 1530 } else { 1531 NO_FILTER_CASE: 1532 tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(), 1533 srcM.fRowBytes); 1534 if (!tmpBitmap.allocPixels(allocator, NULL)) { 1535 // Allocation of pixels for alpha bitmap failed. 1536 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1537 tmpBitmap.width(), tmpBitmap.height()); 1538 return false; 1539 } 1540 GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes); 1541 if (offset) { 1542 offset->set(0, 0); 1543 } 1544 tmpBitmap.swap(*dst); 1545 return true; 1546 } 1547 srcM.fImage = SkMask::AllocImage(srcM.computeImageSize()); 1548 SkAutoMaskFreeImage srcCleanup(srcM.fImage); 1549 1550 GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes); 1551 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1552 goto NO_FILTER_CASE; 1553 } 1554 SkAutoMaskFreeImage dstCleanup(dstM.fImage); 1555 1556 tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(), 1557 dstM.fBounds.height(), dstM.fRowBytes); 1558 if (!tmpBitmap.allocPixels(allocator, NULL)) { 1559 // Allocation of pixels for alpha bitmap failed. 1560 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1561 tmpBitmap.width(), tmpBitmap.height()); 1562 return false; 1563 } 1564 memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize()); 1565 if (offset) { 1566 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); 1567 } 1568 SkDEBUGCODE(tmpBitmap.validate();) 1569 1570 tmpBitmap.swap(*dst); 1571 return true; 1572} 1573 1574/////////////////////////////////////////////////////////////////////////////// 1575 1576enum { 1577 SERIALIZE_PIXELTYPE_NONE, 1578 SERIALIZE_PIXELTYPE_REF_DATA 1579}; 1580 1581void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { 1582 buffer.writeInt(fWidth); 1583 buffer.writeInt(fHeight); 1584 buffer.writeInt(fRowBytes); 1585 buffer.writeInt(fConfig); 1586 buffer.writeInt(fAlphaType); 1587 1588 if (fPixelRef) { 1589 if (fPixelRef->getFactory()) { 1590 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); 1591 buffer.writeInt(fPixelRefOrigin.fX); 1592 buffer.writeInt(fPixelRefOrigin.fY); 1593 buffer.writeFlattenable(fPixelRef); 1594 return; 1595 } 1596 // if we get here, we can't record the pixels 1597 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1598 } else { 1599 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1600 } 1601} 1602 1603void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { 1604 this->reset(); 1605 1606 int width = buffer.readInt(); 1607 int height = buffer.readInt(); 1608 int rowBytes = buffer.readInt(); 1609 Config config = (Config)buffer.readInt(); 1610 SkAlphaType alphaType = (SkAlphaType)buffer.readInt(); 1611 buffer.validate((width >= 0) && (height >= 0) && (rowBytes >= 0) && 1612 SkIsValidConfig(config) && validate_alphaType(config, alphaType)); 1613 1614 bool configIsValid = this->setConfig(config, width, height, rowBytes, alphaType); 1615 // Note : Using (fRowBytes >= (fWidth * fBytesPerPixel)) in the following test can create false 1616 // positives if the multiplication causes an integer overflow. Use the division instead. 1617 buffer.validate(configIsValid && (fBytesPerPixel > 0) && 1618 ((fRowBytes / fBytesPerPixel) >= fWidth)); 1619 1620 int reftype = buffer.readInt(); 1621 if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) || 1622 (SERIALIZE_PIXELTYPE_NONE == reftype))) { 1623 switch (reftype) { 1624 case SERIALIZE_PIXELTYPE_REF_DATA: { 1625 SkIPoint origin; 1626 origin.fX = buffer.readInt(); 1627 origin.fY = buffer.readInt(); 1628 size_t offset = origin.fY * rowBytes + origin.fX * fBytesPerPixel; 1629 SkPixelRef* pr = buffer.readPixelRef(); 1630 if (!buffer.validate((NULL == pr) || 1631 (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) { 1632 origin.setZero(); 1633 } 1634 SkSafeUnref(this->setPixelRef(pr, origin)); 1635 break; 1636 } 1637 case SERIALIZE_PIXELTYPE_NONE: 1638 break; 1639 default: 1640 SkDEBUGFAIL("unrecognized pixeltype in serialized data"); 1641 sk_throw(); 1642 } 1643 } 1644} 1645 1646/////////////////////////////////////////////////////////////////////////////// 1647 1648SkBitmap::RLEPixels::RLEPixels(int width, int height) { 1649 fHeight = height; 1650 fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*)); 1651} 1652 1653SkBitmap::RLEPixels::~RLEPixels() { 1654 sk_free(fYPtrs); 1655} 1656 1657/////////////////////////////////////////////////////////////////////////////// 1658 1659#ifdef SK_DEBUG 1660void SkBitmap::validate() const { 1661 SkASSERT(fConfig < kConfigCount); 1662 SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth)); 1663 uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag; 1664#ifdef SK_BUILD_FOR_ANDROID 1665 allFlags |= kHasHardwareMipMap_Flag; 1666#endif 1667 SkASSERT(fFlags <= allFlags); 1668 SkASSERT(fPixelLockCount >= 0); 1669 SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel); 1670 1671 if (fPixels) { 1672 SkASSERT(fPixelRef); 1673 SkASSERT(fPixelLockCount > 0); 1674 SkASSERT(fPixelRef->isLocked()); 1675#if !defined(SK_SUPPORT_LEGACY_ONLOCKPIXELS) 1676 SkASSERT(fPixelRef->rowBytes() == fRowBytes); 1677#endif 1678 SkASSERT(fPixelRefOrigin.fX >= 0); 1679 SkASSERT(fPixelRefOrigin.fY >= 0); 1680 SkASSERT(fPixelRef->info().fWidth >= (int)fWidth + fPixelRefOrigin.fX); 1681 SkASSERT(fPixelRef->info().fHeight >= (int)fHeight + fPixelRefOrigin.fY); 1682#if !defined(SK_SUPPORT_LEGACY_ONLOCKPIXELS) 1683 SkASSERT(fPixelRef->rowBytes() >= fWidth * fBytesPerPixel); 1684#endif 1685 } else { 1686 SkASSERT(NULL == fColorTable); 1687 } 1688} 1689#endif 1690 1691#ifdef SK_DEVELOPER 1692void SkBitmap::toString(SkString* str) const { 1693 1694 static const char* gConfigNames[kConfigCount] = { 1695 "NONE", "A8", "INDEX8", "565", "4444", "8888" 1696 }; 1697 1698 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), 1699 gConfigNames[this->config()]); 1700 1701 str->append(" ("); 1702 if (this->isOpaque()) { 1703 str->append("opaque"); 1704 } else { 1705 str->append("transparent"); 1706 } 1707 if (this->isImmutable()) { 1708 str->append(", immutable"); 1709 } else { 1710 str->append(", not-immutable"); 1711 } 1712 str->append(")"); 1713 1714 SkPixelRef* pr = this->pixelRef(); 1715 if (NULL == pr) { 1716 // show null or the explicit pixel address (rare) 1717 str->appendf(" pixels:%p", this->getPixels()); 1718 } else { 1719 const char* uri = pr->getURI(); 1720 if (NULL != uri) { 1721 str->appendf(" uri:\"%s\"", uri); 1722 } else { 1723 str->appendf(" pixelref:%p", pr); 1724 } 1725 } 1726 1727 str->append(")"); 1728} 1729#endif 1730