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