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