SkBitmap.cpp revision 60b5dce19984a5165f6b2f1d6d477f5e8a940761
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 = kN32_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. Should we bzero so the memory is not uninitialized? 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 switch (this->colorType()) { 858 case kAlpha_8_SkColorType: { 859 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); 860 while (--height >= 0) { 861 memset(p, a, width); 862 p += rowBytes; 863 } 864 break; 865 } 866 case kARGB_4444_SkColorType: 867 case kRGB_565_SkColorType: { 868 uint16_t* p = this->getAddr16(area.fLeft, area.fTop);; 869 uint16_t v; 870 871 // make rgb premultiplied 872 if (255 != a) { 873 r = SkAlphaMul(r, a); 874 g = SkAlphaMul(g, a); 875 b = SkAlphaMul(b, a); 876 } 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 kBGRA_8888_SkColorType: 892 case kRGBA_8888_SkColorType: { 893 uint32_t* p = this->getAddr32(area.fLeft, area.fTop); 894 895 if (255 != a && kPremul_SkAlphaType == this->alphaType()) { 896 r = SkAlphaMul(r, a); 897 g = SkAlphaMul(g, a); 898 b = SkAlphaMul(b, a); 899 } 900 uint32_t v = kRGBA_8888_SkColorType == this->colorType() ? 901 SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b); 902 903 while (--height >= 0) { 904 sk_memset32(p, v, width); 905 p = (uint32_t*)((char*)p + rowBytes); 906 } 907 break; 908 } 909 default: 910 return; // no change, so don't call notifyPixelsChanged() 911 } 912 913 this->notifyPixelsChanged(); 914} 915 916void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 917 SkIRect area = { 0, 0, this->width(), this->height() }; 918 if (!area.isEmpty()) { 919 this->internalErase(area, a, r, g, b); 920 } 921} 922 923void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { 924 SkIRect area = { 0, 0, this->width(), this->height() }; 925 if (area.intersect(rect)) { 926 this->internalErase(area, SkColorGetA(c), SkColorGetR(c), 927 SkColorGetG(c), SkColorGetB(c)); 928 } 929} 930 931////////////////////////////////////////////////////////////////////////////////////// 932////////////////////////////////////////////////////////////////////////////////////// 933 934bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { 935 SkDEBUGCODE(this->validate();) 936 937 if (NULL == result || NULL == fPixelRef) { 938 return false; // no src pixels 939 } 940 941 SkIRect srcRect, r; 942 srcRect.set(0, 0, this->width(), this->height()); 943 if (!r.intersect(srcRect, subset)) { 944 return false; // r is empty (i.e. no intersection) 945 } 946 947 if (fPixelRef->getTexture() != NULL) { 948 // Do a deep copy 949 SkPixelRef* pixelRef = fPixelRef->deepCopy(&subset); 950 if (pixelRef != NULL) { 951 SkBitmap dst; 952 dst.setConfig(this->config(), subset.width(), subset.height(), 0, 953 this->alphaType()); 954 dst.setIsVolatile(this->isVolatile()); 955 dst.setPixelRef(pixelRef)->unref(); 956 SkDEBUGCODE(dst.validate()); 957 result->swap(dst); 958 return true; 959 } 960 } 961 962 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 963 // exited above. 964 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 965 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 966 967 SkBitmap dst; 968 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), 969 this->alphaType()); 970 dst.setIsVolatile(this->isVolatile()); 971 972 if (fPixelRef) { 973 SkIPoint origin = fPixelRefOrigin; 974 origin.fX += r.fLeft; 975 origin.fY += r.fTop; 976 // share the pixelref with a custom offset 977 dst.setPixelRef(fPixelRef, origin); 978 } 979 SkDEBUGCODE(dst.validate();) 980 981 // we know we're good, so commit to result 982 result->swap(dst); 983 return true; 984} 985 986/////////////////////////////////////////////////////////////////////////////// 987 988#include "SkCanvas.h" 989#include "SkPaint.h" 990 991bool SkBitmap::canCopyTo(SkColorType dstColorType) const { 992 if (this->colorType() == kUnknown_SkColorType) { 993 return false; 994 } 995 996 bool sameConfigs = (this->colorType() == dstColorType); 997 switch (dstColorType) { 998 case kAlpha_8_SkColorType: 999 case kRGB_565_SkColorType: 1000 case kRGBA_8888_SkColorType: 1001 case kBGRA_8888_SkColorType: 1002 break; 1003 case kIndex_8_SkColorType: 1004 if (!sameConfigs) { 1005 return false; 1006 } 1007 break; 1008 case kARGB_4444_SkColorType: 1009 return sameConfigs || kN32_SkColorType == this->colorType(); 1010 default: 1011 return false; 1012 } 1013 return true; 1014} 1015 1016bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, 1017 Allocator* alloc) const { 1018 if (!this->canCopyTo(dstColorType)) { 1019 return false; 1020 } 1021 1022 // if we have a texture, first get those pixels 1023 SkBitmap tmpSrc; 1024 const SkBitmap* src = this; 1025 1026 if (fPixelRef) { 1027 SkIRect subset; 1028 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, 1029 fInfo.width(), fInfo.height()); 1030 if (fPixelRef->readPixels(&tmpSrc, &subset)) { 1031 SkASSERT(tmpSrc.width() == this->width()); 1032 SkASSERT(tmpSrc.height() == this->height()); 1033 1034 // did we get lucky and we can just return tmpSrc? 1035 if (tmpSrc.colorType() == dstColorType && NULL == alloc) { 1036 dst->swap(tmpSrc); 1037 // If the result is an exact copy, clone the gen ID. 1038 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) { 1039 dst->pixelRef()->cloneGenID(*fPixelRef); 1040 } 1041 return true; 1042 } 1043 1044 // fall through to the raster case 1045 src = &tmpSrc; 1046 } 1047 } 1048 1049 // we lock this now, since we may need its colortable 1050 SkAutoLockPixels srclock(*src); 1051 if (!src->readyToDraw()) { 1052 return false; 1053 } 1054 1055 // The only way to be readyToDraw is if fPixelRef is non NULL. 1056 SkASSERT(fPixelRef != NULL); 1057 1058 SkImageInfo dstInfo = src->info(); 1059 dstInfo.fColorType = dstColorType; 1060 1061 SkBitmap tmpDst; 1062 if (!tmpDst.setConfig(dstInfo)) { 1063 return false; 1064 } 1065 1066 // allocate colortable if srcConfig == kIndex8_Config 1067 SkAutoTUnref<SkColorTable> ctable; 1068 if (dstColorType == kIndex_8_SkColorType) { 1069 // TODO: can we just ref() the src colortable? Is it reentrant-safe? 1070 ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable()))); 1071 } 1072 if (!tmpDst.allocPixels(alloc, ctable)) { 1073 return false; 1074 } 1075 1076 if (!tmpDst.readyToDraw()) { 1077 // allocator/lock failed 1078 return false; 1079 } 1080 1081 // pixelRef must be non NULL or tmpDst.readyToDraw() would have 1082 // returned false. 1083 SkASSERT(tmpDst.pixelRef() != NULL); 1084 1085 /* do memcpy for the same configs cases, else use drawing 1086 */ 1087 if (src->colorType() == dstColorType) { 1088 if (tmpDst.getSize() == src->getSize()) { 1089 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); 1090 SkPixelRef* pixelRef = tmpDst.pixelRef(); 1091 1092 // In order to reach this point, we know that the width, config and 1093 // rowbytes of the SkPixelRefs are the same, but it is possible for 1094 // the heights to differ, if this SkBitmap's height is a subset of 1095 // fPixelRef. Only if the SkPixelRefs' heights match are we 1096 // guaranteed that this is an exact copy, meaning we should clone 1097 // the genID. 1098 if (pixelRef->info().fHeight == fPixelRef->info().fHeight) { 1099 // TODO: what to do if the two infos match, BUT 1100 // fPixelRef is premul and pixelRef is opaque? 1101 // skipping assert for now 1102 // https://code.google.com/p/skia/issues/detail?id=2012 1103// SkASSERT(pixelRef->info() == fPixelRef->info()); 1104 SkASSERT(pixelRef->info().fWidth == fPixelRef->info().fWidth); 1105 SkASSERT(pixelRef->info().fColorType == fPixelRef->info().fColorType); 1106 pixelRef->cloneGenID(*fPixelRef); 1107 } 1108 } else { 1109 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); 1110 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); 1111 // to be sure we don't read too much, only copy our logical pixels 1112 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); 1113 for (int y = 0; y < tmpDst.height(); y++) { 1114 memcpy(dstP, srcP, bytesToCopy); 1115 srcP += src->rowBytes(); 1116 dstP += tmpDst.rowBytes(); 1117 } 1118 } 1119 } else if (kARGB_4444_SkColorType == dstColorType 1120 && kN32_SkColorType == src->colorType()) { 1121 SkASSERT(src->height() == tmpDst.height()); 1122 SkASSERT(src->width() == tmpDst.width()); 1123 for (int y = 0; y < src->height(); ++y) { 1124 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); 1125 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); 1126 DITHER_4444_SCAN(y); 1127 for (int x = 0; x < src->width(); ++x) { 1128 dstRow[x] = SkDitherARGB32To4444(srcRow[x], 1129 DITHER_VALUE(x)); 1130 } 1131 } 1132 } else { 1133 // Always clear the dest in case one of the blitters accesses it 1134 // TODO: switch the allocation of tmpDst to call sk_calloc_throw 1135 tmpDst.eraseColor(SK_ColorTRANSPARENT); 1136 1137 SkCanvas canvas(tmpDst); 1138 SkPaint paint; 1139 1140 paint.setDither(true); 1141 canvas.drawBitmap(*src, 0, 0, &paint); 1142 } 1143 1144 dst->swap(tmpDst); 1145 return true; 1146} 1147 1148bool SkBitmap::deepCopyTo(SkBitmap* dst) const { 1149 const SkColorType dstCT = this->colorType(); 1150 1151 if (!this->canCopyTo(dstCT)) { 1152 return false; 1153 } 1154 1155 // If we have a PixelRef, and it supports deep copy, use it. 1156 // Currently supported only by texture-backed bitmaps. 1157 if (fPixelRef) { 1158 SkPixelRef* pixelRef = fPixelRef->deepCopy(); 1159 if (pixelRef) { 1160 // Since there is no subset to pass to deepCopy, and deepCopy 1161 // succeeded, the new pixel ref must be identical. 1162 SkASSERT(fPixelRef->info() == pixelRef->info()); 1163 pixelRef->cloneGenID(*fPixelRef); 1164 1165 SkImageInfo info = fInfo; 1166 if (!dst->setConfig(info, fRowBytes)) { 1167 return false; 1168 } 1169 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); 1170 return true; 1171 } 1172 } 1173 1174 if (this->getTexture()) { 1175 return false; 1176 } else { 1177 return this->copyTo(dst, dstCT, NULL); 1178 } 1179} 1180 1181/////////////////////////////////////////////////////////////////////////////// 1182/////////////////////////////////////////////////////////////////////////////// 1183 1184static void downsampleby2_proc32(SkBitmap* dst, int x, int y, 1185 const SkBitmap& src) { 1186 x <<= 1; 1187 y <<= 1; 1188 const SkPMColor* p = src.getAddr32(x, y); 1189 const SkPMColor* baseP = p; 1190 SkPMColor c, ag, rb; 1191 1192 c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF; 1193 if (x < src.width() - 1) { 1194 p += 1; 1195 } 1196 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1197 1198 p = baseP; 1199 if (y < src.height() - 1) { 1200 p += src.rowBytes() >> 2; 1201 } 1202 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1203 if (x < src.width() - 1) { 1204 p += 1; 1205 } 1206 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1207 1208 *dst->getAddr32(x >> 1, y >> 1) = 1209 ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00); 1210} 1211 1212static inline uint32_t expand16(U16CPU c) { 1213 return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16); 1214} 1215 1216// returns dirt in the top 16bits, but we don't care, since we only 1217// store the low 16bits. 1218static inline U16CPU pack16(uint32_t c) { 1219 return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE); 1220} 1221 1222static void downsampleby2_proc16(SkBitmap* dst, int x, int y, 1223 const SkBitmap& src) { 1224 x <<= 1; 1225 y <<= 1; 1226 const uint16_t* p = src.getAddr16(x, y); 1227 const uint16_t* baseP = p; 1228 SkPMColor c; 1229 1230 c = expand16(*p); 1231 if (x < src.width() - 1) { 1232 p += 1; 1233 } 1234 c += expand16(*p); 1235 1236 p = baseP; 1237 if (y < src.height() - 1) { 1238 p += src.rowBytes() >> 1; 1239 } 1240 c += expand16(*p); 1241 if (x < src.width() - 1) { 1242 p += 1; 1243 } 1244 c += expand16(*p); 1245 1246 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2); 1247} 1248 1249static uint32_t expand4444(U16CPU c) { 1250 return (c & 0xF0F) | ((c & ~0xF0F) << 12); 1251} 1252 1253static U16CPU collaps4444(uint32_t c) { 1254 return (c & 0xF0F) | ((c >> 12) & ~0xF0F); 1255} 1256 1257static void downsampleby2_proc4444(SkBitmap* dst, int x, int y, 1258 const SkBitmap& src) { 1259 x <<= 1; 1260 y <<= 1; 1261 const uint16_t* p = src.getAddr16(x, y); 1262 const uint16_t* baseP = p; 1263 uint32_t c; 1264 1265 c = expand4444(*p); 1266 if (x < src.width() - 1) { 1267 p += 1; 1268 } 1269 c += expand4444(*p); 1270 1271 p = baseP; 1272 if (y < src.height() - 1) { 1273 p += src.rowBytes() >> 1; 1274 } 1275 c += expand4444(*p); 1276 if (x < src.width() - 1) { 1277 p += 1; 1278 } 1279 c += expand4444(*p); 1280 1281 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2); 1282} 1283 1284void SkBitmap::buildMipMap(bool forceRebuild) { 1285 if (forceRebuild) 1286 this->freeMipMap(); 1287 else if (fMipMap) 1288 return; // we're already built 1289 1290 SkASSERT(NULL == fMipMap); 1291 1292 void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src); 1293 1294 const SkBitmap::Config config = this->config(); 1295 1296 switch (config) { 1297 case kARGB_8888_Config: 1298 proc = downsampleby2_proc32; 1299 break; 1300 case kRGB_565_Config: 1301 proc = downsampleby2_proc16; 1302 break; 1303 case kARGB_4444_Config: 1304 proc = downsampleby2_proc4444; 1305 break; 1306 case kIndex8_Config: 1307 case kA8_Config: 1308 default: 1309 return; // don't build mipmaps for these configs 1310 } 1311 1312 SkAutoLockPixels alp(*this); 1313 if (!this->readyToDraw()) { 1314 return; 1315 } 1316 1317 // whip through our loop to compute the exact size needed 1318 size_t size = 0; 1319 int maxLevels = 0; 1320 { 1321 int width = this->width(); 1322 int height = this->height(); 1323 for (;;) { 1324 width >>= 1; 1325 height >>= 1; 1326 if (0 == width || 0 == height) { 1327 break; 1328 } 1329 size += ComputeRowBytes(config, width) * height; 1330 maxLevels += 1; 1331 } 1332 } 1333 1334 // nothing to build 1335 if (0 == maxLevels) { 1336 return; 1337 } 1338 1339 SkBitmap srcBM(*this); 1340 srcBM.lockPixels(); 1341 if (!srcBM.readyToDraw()) { 1342 return; 1343 } 1344 1345 MipMap* mm = MipMap::Alloc(maxLevels, size); 1346 if (NULL == mm) { 1347 return; 1348 } 1349 1350 MipLevel* level = mm->levels(); 1351 uint8_t* addr = (uint8_t*)mm->pixels(); 1352 int width = this->width(); 1353 int height = this->height(); 1354 uint32_t rowBytes; 1355 SkBitmap dstBM; 1356 1357 for (int i = 0; i < maxLevels; i++) { 1358 width >>= 1; 1359 height >>= 1; 1360 rowBytes = SkToU32(ComputeRowBytes(config, width)); 1361 1362 level[i].fPixels = addr; 1363 level[i].fWidth = width; 1364 level[i].fHeight = height; 1365 level[i].fRowBytes = rowBytes; 1366 1367 dstBM.setConfig(config, width, height, rowBytes); 1368 dstBM.setPixels(addr); 1369 1370 srcBM.lockPixels(); 1371 for (int y = 0; y < height; y++) { 1372 for (int x = 0; x < width; x++) { 1373 proc(&dstBM, x, y, srcBM); 1374 } 1375 } 1376 srcBM.unlockPixels(); 1377 1378 srcBM = dstBM; 1379 addr += height * rowBytes; 1380 } 1381 SkASSERT(addr == (uint8_t*)mm->pixels() + size); 1382 fMipMap = mm; 1383} 1384 1385bool SkBitmap::hasMipMap() const { 1386 return fMipMap != NULL; 1387} 1388 1389int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) { 1390 if (NULL == fMipMap) { 1391 return 0; 1392 } 1393 1394 int level = ComputeMipLevel(sx, sy) >> 16; 1395 SkASSERT(level >= 0); 1396 if (level <= 0) { 1397 return 0; 1398 } 1399 1400 if (level >= fMipMap->fLevelCount) { 1401 level = fMipMap->fLevelCount - 1; 1402 } 1403 if (dst) { 1404 const MipLevel& mip = fMipMap->levels()[level - 1]; 1405 dst->setConfig((SkBitmap::Config)this->config(), 1406 mip.fWidth, mip.fHeight, mip.fRowBytes); 1407 dst->setPixels(mip.fPixels); 1408 } 1409 return level; 1410} 1411 1412SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) { 1413 sx = SkAbs32(sx); 1414 sy = SkAbs32(sy); 1415 if (sx < sy) { 1416 sx = sy; 1417 } 1418 if (sx < SK_Fixed1) { 1419 return 0; 1420 } 1421 int clz = SkCLZ(sx); 1422 SkASSERT(clz >= 1 && clz <= 15); 1423 return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16); 1424} 1425 1426/////////////////////////////////////////////////////////////////////////////// 1427 1428static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, 1429 int alphaRowBytes) { 1430 SkASSERT(alpha != NULL); 1431 SkASSERT(alphaRowBytes >= src.width()); 1432 1433 SkBitmap::Config config = src.config(); 1434 int w = src.width(); 1435 int h = src.height(); 1436 size_t rb = src.rowBytes(); 1437 1438 SkAutoLockPixels alp(src); 1439 if (!src.readyToDraw()) { 1440 // zero out the alpha buffer and return 1441 while (--h >= 0) { 1442 memset(alpha, 0, w); 1443 alpha += alphaRowBytes; 1444 } 1445 return false; 1446 } 1447 1448 if (SkBitmap::kA8_Config == config && !src.isOpaque()) { 1449 const uint8_t* s = src.getAddr8(0, 0); 1450 while (--h >= 0) { 1451 memcpy(alpha, s, w); 1452 s += rb; 1453 alpha += alphaRowBytes; 1454 } 1455 } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) { 1456 const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0); 1457 while (--h >= 0) { 1458 for (int x = 0; x < w; x++) { 1459 alpha[x] = SkGetPackedA32(s[x]); 1460 } 1461 s = (const SkPMColor*)((const char*)s + rb); 1462 alpha += alphaRowBytes; 1463 } 1464 } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) { 1465 const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0); 1466 while (--h >= 0) { 1467 for (int x = 0; x < w; x++) { 1468 alpha[x] = SkPacked4444ToA32(s[x]); 1469 } 1470 s = (const SkPMColor16*)((const char*)s + rb); 1471 alpha += alphaRowBytes; 1472 } 1473 } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) { 1474 SkColorTable* ct = src.getColorTable(); 1475 if (ct) { 1476 const SkPMColor* SK_RESTRICT table = ct->lockColors(); 1477 const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0); 1478 while (--h >= 0) { 1479 for (int x = 0; x < w; x++) { 1480 alpha[x] = SkGetPackedA32(table[s[x]]); 1481 } 1482 s += rb; 1483 alpha += alphaRowBytes; 1484 } 1485 ct->unlockColors(); 1486 } 1487 } else { // src is opaque, so just fill alpha[] with 0xFF 1488 memset(alpha, 0xFF, h * alphaRowBytes); 1489 } 1490 return true; 1491} 1492 1493#include "SkPaint.h" 1494#include "SkMaskFilter.h" 1495#include "SkMatrix.h" 1496 1497bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, 1498 Allocator *allocator, SkIPoint* offset) const { 1499 SkDEBUGCODE(this->validate();) 1500 1501 SkBitmap tmpBitmap; 1502 SkMatrix identity; 1503 SkMask srcM, dstM; 1504 1505 srcM.fBounds.set(0, 0, this->width(), this->height()); 1506 srcM.fRowBytes = SkAlign4(this->width()); 1507 srcM.fFormat = SkMask::kA8_Format; 1508 1509 SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL; 1510 1511 // compute our (larger?) dst bounds if we have a filter 1512 if (NULL != filter) { 1513 identity.reset(); 1514 srcM.fImage = NULL; 1515 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1516 goto NO_FILTER_CASE; 1517 } 1518 dstM.fRowBytes = SkAlign4(dstM.fBounds.width()); 1519 } else { 1520 NO_FILTER_CASE: 1521 tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(), 1522 srcM.fRowBytes); 1523 if (!tmpBitmap.allocPixels(allocator, NULL)) { 1524 // Allocation of pixels for alpha bitmap failed. 1525 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1526 tmpBitmap.width(), tmpBitmap.height()); 1527 return false; 1528 } 1529 GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes); 1530 if (offset) { 1531 offset->set(0, 0); 1532 } 1533 tmpBitmap.swap(*dst); 1534 return true; 1535 } 1536 srcM.fImage = SkMask::AllocImage(srcM.computeImageSize()); 1537 SkAutoMaskFreeImage srcCleanup(srcM.fImage); 1538 1539 GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes); 1540 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1541 goto NO_FILTER_CASE; 1542 } 1543 SkAutoMaskFreeImage dstCleanup(dstM.fImage); 1544 1545 tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(), 1546 dstM.fBounds.height(), dstM.fRowBytes); 1547 if (!tmpBitmap.allocPixels(allocator, NULL)) { 1548 // Allocation of pixels for alpha bitmap failed. 1549 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1550 tmpBitmap.width(), tmpBitmap.height()); 1551 return false; 1552 } 1553 memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize()); 1554 if (offset) { 1555 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); 1556 } 1557 SkDEBUGCODE(tmpBitmap.validate();) 1558 1559 tmpBitmap.swap(*dst); 1560 return true; 1561} 1562 1563/////////////////////////////////////////////////////////////////////////////// 1564 1565enum { 1566 SERIALIZE_PIXELTYPE_NONE, 1567 SERIALIZE_PIXELTYPE_REF_DATA 1568}; 1569 1570void SkBitmap::flatten(SkWriteBuffer& buffer) const { 1571 fInfo.flatten(buffer); 1572 buffer.writeInt(fRowBytes); 1573 1574 if (fPixelRef) { 1575 if (fPixelRef->getFactory()) { 1576 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); 1577 buffer.writeInt(fPixelRefOrigin.fX); 1578 buffer.writeInt(fPixelRefOrigin.fY); 1579 buffer.writeFlattenable(fPixelRef); 1580 return; 1581 } 1582 // if we get here, we can't record the pixels 1583 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1584 } else { 1585 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1586 } 1587} 1588 1589void SkBitmap::unflatten(SkReadBuffer& buffer) { 1590 this->reset(); 1591 1592 SkImageInfo info; 1593 info.unflatten(buffer); 1594 size_t rowBytes = buffer.readInt(); 1595 if (!buffer.validate((info.width() >= 0) && (info.height() >= 0) && 1596 SkColorTypeIsValid(info.fColorType) && 1597 SkAlphaTypeIsValid(info.fAlphaType) && 1598 validate_alphaType(info.fColorType, info.fAlphaType) && 1599 info.validRowBytes(rowBytes))) { 1600 return; 1601 } 1602 1603 bool configIsValid = this->setConfig(info, rowBytes); 1604 buffer.validate(configIsValid); 1605 1606 int reftype = buffer.readInt(); 1607 if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) || 1608 (SERIALIZE_PIXELTYPE_NONE == reftype))) { 1609 switch (reftype) { 1610 case SERIALIZE_PIXELTYPE_REF_DATA: { 1611 SkIPoint origin; 1612 origin.fX = buffer.readInt(); 1613 origin.fY = buffer.readInt(); 1614 size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel(); 1615 SkPixelRef* pr = buffer.readPixelRef(); 1616 if (!buffer.validate((NULL == pr) || 1617 (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) { 1618 origin.setZero(); 1619 } 1620 SkSafeUnref(this->setPixelRef(pr, origin)); 1621 break; 1622 } 1623 case SERIALIZE_PIXELTYPE_NONE: 1624 break; 1625 default: 1626 SkDEBUGFAIL("unrecognized pixeltype in serialized data"); 1627 sk_throw(); 1628 } 1629 } 1630} 1631 1632/////////////////////////////////////////////////////////////////////////////// 1633 1634SkBitmap::RLEPixels::RLEPixels(int width, int height) { 1635 fHeight = height; 1636 fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*)); 1637} 1638 1639SkBitmap::RLEPixels::~RLEPixels() { 1640 sk_free(fYPtrs); 1641} 1642 1643/////////////////////////////////////////////////////////////////////////////// 1644 1645#ifdef SK_DEBUG 1646void SkBitmap::validate() const { 1647 fInfo.validate(); 1648 1649 // ImageInfo may not require this, but Bitmap ensures that opaque-only 1650 // colorTypes report opaque for their alphatype 1651 if (kRGB_565_SkColorType == fInfo.colorType()) { 1652 SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType()); 1653 } 1654 1655 SkASSERT(fInfo.validRowBytes(fRowBytes)); 1656 uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag; 1657#ifdef SK_BUILD_FOR_ANDROID 1658 allFlags |= kHasHardwareMipMap_Flag; 1659#endif 1660 SkASSERT(fFlags <= allFlags); 1661 SkASSERT(fPixelLockCount >= 0); 1662 1663 if (fPixels) { 1664 SkASSERT(fPixelRef); 1665 SkASSERT(fPixelLockCount > 0); 1666 SkASSERT(fPixelRef->isLocked()); 1667 SkASSERT(fPixelRef->rowBytes() == fRowBytes); 1668 SkASSERT(fPixelRefOrigin.fX >= 0); 1669 SkASSERT(fPixelRefOrigin.fY >= 0); 1670 SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX); 1671 SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOrigin.fY); 1672 SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes()); 1673 } else { 1674 SkASSERT(NULL == fColorTable); 1675 } 1676} 1677#endif 1678 1679#ifndef SK_IGNORE_TO_STRING 1680void SkBitmap::toString(SkString* str) const { 1681 1682 static const char* gConfigNames[kConfigCount] = { 1683 "NONE", "A8", "INDEX8", "565", "4444", "8888" 1684 }; 1685 1686 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), 1687 gConfigNames[this->config()]); 1688 1689 str->append(" ("); 1690 if (this->isOpaque()) { 1691 str->append("opaque"); 1692 } else { 1693 str->append("transparent"); 1694 } 1695 if (this->isImmutable()) { 1696 str->append(", immutable"); 1697 } else { 1698 str->append(", not-immutable"); 1699 } 1700 str->append(")"); 1701 1702 SkPixelRef* pr = this->pixelRef(); 1703 if (NULL == pr) { 1704 // show null or the explicit pixel address (rare) 1705 str->appendf(" pixels:%p", this->getPixels()); 1706 } else { 1707 const char* uri = pr->getURI(); 1708 if (NULL != uri) { 1709 str->appendf(" uri:\"%s\"", uri); 1710 } else { 1711 str->appendf(" pixelref:%p", pr); 1712 } 1713 } 1714 1715 str->append(")"); 1716} 1717#endif 1718 1719/////////////////////////////////////////////////////////////////////////////// 1720 1721#ifdef SK_DEBUG 1722void SkImageInfo::validate() const { 1723 SkASSERT(fWidth >= 0); 1724 SkASSERT(fHeight >= 0); 1725 SkASSERT(SkColorTypeIsValid(fColorType)); 1726 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); 1727} 1728#endif 1729