SkBitmap.cpp revision 7403d87db8e43d4c2b5b25ac22a0ebc22bd09d69
1/* 2 * Copyright 2008 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkAtomics.h" 9#include "SkBitmap.h" 10#include "SkColorPriv.h" 11#include "SkData.h" 12#include "SkFilterQuality.h" 13#include "SkMallocPixelRef.h" 14#include "SkMask.h" 15#include "SkMath.h" 16#include "SkPixelRef.h" 17#include "SkReadBuffer.h" 18#include "SkRect.h" 19#include "SkScalar.h" 20#include "SkUnPreMultiply.h" 21#include "SkWriteBuffer.h" 22 23#include <string.h> 24 25static bool reset_return_false(SkBitmap* bm) { 26 bm->reset(); 27 return false; 28} 29 30SkBitmap::SkBitmap() { 31 sk_bzero(this, sizeof(*this)); 32} 33 34SkBitmap::SkBitmap(const SkBitmap& src) { 35 SkDEBUGCODE(src.validate();) 36 sk_bzero(this, sizeof(*this)); 37 *this = src; 38 SkDEBUGCODE(this->validate();) 39} 40 41SkBitmap::~SkBitmap() { 42 SkDEBUGCODE(this->validate();) 43 this->freePixels(); 44} 45 46SkBitmap& SkBitmap::operator=(const SkBitmap& src) { 47 if (this != &src) { 48 this->freePixels(); 49 memcpy(this, &src, sizeof(src)); 50 51 // inc src reference counts 52 SkSafeRef(src.fPixelRef); 53 54 // we reset our locks if we get blown away 55 fPixelLockCount = 0; 56 57 if (fPixelRef) { 58 // ignore the values from the memcpy 59 fPixels = NULL; 60 fColorTable = NULL; 61 // Note that what to for genID is somewhat arbitrary. We have no 62 // way to track changes to raw pixels across multiple SkBitmaps. 63 // Would benefit from an SkRawPixelRef type created by 64 // setPixels. 65 // Just leave the memcpy'ed one but they'll get out of sync 66 // as soon either is modified. 67 } 68 } 69 70 SkDEBUGCODE(this->validate();) 71 return *this; 72} 73 74void SkBitmap::swap(SkBitmap& other) { 75 SkTSwap(fColorTable, other.fColorTable); 76 SkTSwap(fPixelRef, other.fPixelRef); 77 SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin); 78 SkTSwap(fPixelLockCount, other.fPixelLockCount); 79 SkTSwap(fPixels, other.fPixels); 80 SkTSwap(fInfo, other.fInfo); 81 SkTSwap(fRowBytes, other.fRowBytes); 82 SkTSwap(fFlags, other.fFlags); 83 84 SkDEBUGCODE(this->validate();) 85} 86 87void SkBitmap::reset() { 88 this->freePixels(); 89 sk_bzero(this, sizeof(*this)); 90} 91 92void SkBitmap::getBounds(SkRect* bounds) const { 93 SkASSERT(bounds); 94 bounds->set(0, 0, 95 SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height())); 96} 97 98void SkBitmap::getBounds(SkIRect* bounds) const { 99 SkASSERT(bounds); 100 bounds->set(0, 0, fInfo.width(), fInfo.height()); 101} 102 103/////////////////////////////////////////////////////////////////////////////// 104 105bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) { 106 SkAlphaType newAT = info.alphaType(); 107 if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) { 108 return reset_return_false(this); 109 } 110 // don't look at info.alphaType(), since newAT is the real value... 111 112 // require that rowBytes fit in 31bits 113 int64_t mrb = info.minRowBytes64(); 114 if ((int32_t)mrb != mrb) { 115 return reset_return_false(this); 116 } 117 if ((int64_t)rowBytes != (int32_t)rowBytes) { 118 return reset_return_false(this); 119 } 120 121 if (info.width() < 0 || info.height() < 0) { 122 return reset_return_false(this); 123 } 124 125 if (kUnknown_SkColorType == info.colorType()) { 126 rowBytes = 0; 127 } else if (0 == rowBytes) { 128 rowBytes = (size_t)mrb; 129 } else if (!info.validRowBytes(rowBytes)) { 130 return reset_return_false(this); 131 } 132 133 this->freePixels(); 134 135 fInfo = info.makeAlphaType(newAT); 136 fRowBytes = SkToU32(rowBytes); 137 return true; 138} 139 140bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) { 141 if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) { 142 return false; 143 } 144 if (fInfo.alphaType() != newAlphaType) { 145 fInfo = fInfo.makeAlphaType(newAlphaType); 146 if (fPixelRef) { 147 fPixelRef->changeAlphaType(newAlphaType); 148 } 149 } 150 return true; 151} 152 153void SkBitmap::updatePixelsFromRef() const { 154 if (fPixelRef) { 155 if (fPixelLockCount > 0) { 156 SkASSERT(fPixelRef->isLocked()); 157 158 void* p = fPixelRef->pixels(); 159 if (p) { 160 p = (char*)p 161 + fPixelRefOrigin.fY * fRowBytes 162 + fPixelRefOrigin.fX * fInfo.bytesPerPixel(); 163 } 164 fPixels = p; 165 fColorTable = fPixelRef->colorTable(); 166 } else { 167 SkASSERT(0 == fPixelLockCount); 168 fPixels = NULL; 169 fColorTable = NULL; 170 } 171 } 172} 173 174SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { 175#ifdef SK_DEBUG 176 if (pr) { 177 if (kUnknown_SkColorType != fInfo.colorType()) { 178 const SkImageInfo& prInfo = pr->info(); 179 SkASSERT(fInfo.width() <= prInfo.width()); 180 SkASSERT(fInfo.height() <= prInfo.height()); 181 SkASSERT(fInfo.colorType() == prInfo.colorType()); 182 switch (prInfo.alphaType()) { 183 case kUnknown_SkAlphaType: 184 SkASSERT(fInfo.alphaType() == kUnknown_SkAlphaType); 185 break; 186 case kOpaque_SkAlphaType: 187 case kPremul_SkAlphaType: 188 SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType || 189 fInfo.alphaType() == kPremul_SkAlphaType); 190 break; 191 case kUnpremul_SkAlphaType: 192 SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType || 193 fInfo.alphaType() == kUnpremul_SkAlphaType); 194 break; 195 } 196 } 197 } 198#endif 199 200 if (pr) { 201 const SkImageInfo& info = pr->info(); 202 fPixelRefOrigin.set(SkPin32(dx, 0, info.width()), SkPin32(dy, 0, info.height())); 203 } else { 204 // ignore dx,dy if there is no pixelref 205 fPixelRefOrigin.setZero(); 206 } 207 208 if (fPixelRef != pr) { 209 this->freePixels(); 210 SkASSERT(NULL == fPixelRef); 211 212 SkSafeRef(pr); 213 fPixelRef = pr; 214 this->updatePixelsFromRef(); 215 } 216 217 SkDEBUGCODE(this->validate();) 218 return pr; 219} 220 221void SkBitmap::lockPixels() const { 222 if (fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) { 223 fPixelRef->lockPixels(); 224 this->updatePixelsFromRef(); 225 } 226 SkDEBUGCODE(this->validate();) 227} 228 229void SkBitmap::unlockPixels() const { 230 SkASSERT(NULL == fPixelRef || fPixelLockCount > 0); 231 232 if (fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) { 233 fPixelRef->unlockPixels(); 234 this->updatePixelsFromRef(); 235 } 236 SkDEBUGCODE(this->validate();) 237} 238 239bool SkBitmap::lockPixelsAreWritable() const { 240 return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false; 241} 242 243void SkBitmap::setPixels(void* p, SkColorTable* ctable) { 244 if (NULL == p) { 245 this->setPixelRef(NULL); 246 return; 247 } 248 249 if (kUnknown_SkColorType == fInfo.colorType()) { 250 this->setPixelRef(NULL); 251 return; 252 } 253 254 SkPixelRef* pr = SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable); 255 if (NULL == pr) { 256 this->setPixelRef(NULL); 257 return; 258 } 259 260 this->setPixelRef(pr)->unref(); 261 262 // since we're already allocated, we lockPixels right away 263 this->lockPixels(); 264 SkDEBUGCODE(this->validate();) 265} 266 267bool SkBitmap::tryAllocPixels(Allocator* allocator, SkColorTable* ctable) { 268 HeapAllocator stdalloc; 269 270 if (NULL == allocator) { 271 allocator = &stdalloc; 272 } 273 return allocator->allocPixelRef(this, ctable); 274} 275 276/////////////////////////////////////////////////////////////////////////////// 277 278bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) { 279 if (kIndex_8_SkColorType == requestedInfo.colorType()) { 280 return reset_return_false(this); 281 } 282 if (!this->setInfo(requestedInfo, rowBytes)) { 283 return reset_return_false(this); 284 } 285 286 // setInfo may have corrected info (e.g. 565 is always opaque). 287 const SkImageInfo& correctedInfo = this->info(); 288 // setInfo may have computed a valid rowbytes if 0 were passed in 289 rowBytes = this->rowBytes(); 290 291 SkMallocPixelRef::PRFactory defaultFactory; 292 293 SkPixelRef* pr = defaultFactory.create(correctedInfo, rowBytes, NULL); 294 if (NULL == pr) { 295 return reset_return_false(this); 296 } 297 this->setPixelRef(pr)->unref(); 298 299 // TODO: lockPixels could/should return bool or void*/NULL 300 this->lockPixels(); 301 if (NULL == this->getPixels()) { 302 return reset_return_false(this); 303 } 304 return true; 305} 306 307bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory, 308 SkColorTable* ctable) { 309 if (kIndex_8_SkColorType == requestedInfo.colorType() && NULL == ctable) { 310 return reset_return_false(this); 311 } 312 if (!this->setInfo(requestedInfo)) { 313 return reset_return_false(this); 314 } 315 316 // setInfo may have corrected info (e.g. 565 is always opaque). 317 const SkImageInfo& correctedInfo = this->info(); 318 319 SkMallocPixelRef::PRFactory defaultFactory; 320 if (NULL == factory) { 321 factory = &defaultFactory; 322 } 323 324 SkPixelRef* pr = factory->create(correctedInfo, correctedInfo.minRowBytes(), ctable); 325 if (NULL == pr) { 326 return reset_return_false(this); 327 } 328 this->setPixelRef(pr)->unref(); 329 330 // TODO: lockPixels could/should return bool or void*/NULL 331 this->lockPixels(); 332 if (NULL == this->getPixels()) { 333 return reset_return_false(this); 334 } 335 return true; 336} 337 338static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) { 339 if (proc) { 340 proc(pixels, ctx); 341 } 342} 343 344bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb, 345 SkColorTable* ct, void (*releaseProc)(void* addr, void* context), 346 void* context) { 347 if (!this->setInfo(requestedInfo, rb)) { 348 invoke_release_proc(releaseProc, pixels, context); 349 this->reset(); 350 return false; 351 } 352 if (NULL == pixels) { 353 invoke_release_proc(releaseProc, pixels, context); 354 return true; // we behaved as if they called setInfo() 355 } 356 357 // setInfo may have corrected info (e.g. 565 is always opaque). 358 const SkImageInfo& correctedInfo = this->info(); 359 360 SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc, 361 context); 362 if (!pr) { 363 this->reset(); 364 return false; 365 } 366 367 this->setPixelRef(pr)->unref(); 368 369 // since we're already allocated, we lockPixels right away 370 this->lockPixels(); 371 SkDEBUGCODE(this->validate();) 372 return true; 373} 374 375bool SkBitmap::installMaskPixels(const SkMask& mask) { 376 if (SkMask::kA8_Format != mask.fFormat) { 377 this->reset(); 378 return false; 379 } 380 return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), 381 mask.fBounds.height()), 382 mask.fImage, mask.fRowBytes); 383} 384 385/////////////////////////////////////////////////////////////////////////////// 386 387void SkBitmap::freePixels() { 388 if (fPixelRef) { 389 if (fPixelLockCount > 0) { 390 fPixelRef->unlockPixels(); 391 } 392 fPixelRef->unref(); 393 fPixelRef = NULL; 394 fPixelRefOrigin.setZero(); 395 } 396 fPixelLockCount = 0; 397 fPixels = NULL; 398 fColorTable = NULL; 399} 400 401uint32_t SkBitmap::getGenerationID() const { 402 return (fPixelRef) ? fPixelRef->getGenerationID() : 0; 403} 404 405void SkBitmap::notifyPixelsChanged() const { 406 SkASSERT(!this->isImmutable()); 407 if (fPixelRef) { 408 fPixelRef->notifyPixelsChanged(); 409 } 410} 411 412GrTexture* SkBitmap::getTexture() const { 413 return fPixelRef ? fPixelRef->getTexture() : NULL; 414} 415 416/////////////////////////////////////////////////////////////////////////////// 417 418/** We explicitly use the same allocator for our pixels that SkMask does, 419 so that we can freely assign memory allocated by one class to the other. 420 */ 421bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, 422 SkColorTable* ctable) { 423 const SkImageInfo info = dst->info(); 424 if (kUnknown_SkColorType == info.colorType()) { 425// SkDebugf("unsupported config for info %d\n", dst->config()); 426 return false; 427 } 428 429 SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable); 430 if (NULL == pr) { 431 return false; 432 } 433 434 dst->setPixelRef(pr)->unref(); 435 // since we're already allocated, we lockPixels right away 436 dst->lockPixels(); 437 return true; 438} 439 440/////////////////////////////////////////////////////////////////////////////// 441 442static bool copy_pixels_to(const SkPixmap& src, void* const dst, size_t dstSize, 443 size_t dstRowBytes, bool preserveDstPad) { 444 const SkImageInfo& info = src.info(); 445 446 if (0 == dstRowBytes) { 447 dstRowBytes = src.rowBytes(); 448 } 449 if (dstRowBytes < info.minRowBytes()) { 450 return false; 451 } 452 453 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == src.rowBytes()) { 454 size_t safeSize = src.getSafeSize(); 455 if (safeSize > dstSize || safeSize == 0) 456 return false; 457 else { 458 // This implementation will write bytes beyond the end of each row, 459 // excluding the last row, if the bitmap's stride is greater than 460 // strictly required by the current config. 461 memcpy(dst, src.addr(), safeSize); 462 return true; 463 } 464 } else { 465 // If destination has different stride than us, then copy line by line. 466 if (info.getSafeSize(dstRowBytes) > dstSize) { 467 return false; 468 } else { 469 // Just copy what we need on each line. 470 size_t rowBytes = info.minRowBytes(); 471 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(src.addr()); 472 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); 473 for (int row = 0; row < info.height(); ++row) { 474 memcpy(dstP, srcP, rowBytes); 475 srcP += src.rowBytes(); 476 dstP += dstRowBytes; 477 } 478 479 return true; 480 } 481 } 482} 483 484bool SkBitmap::copyPixelsTo(void* dst, size_t dstSize, size_t dstRB, bool preserveDstPad) const { 485 if (NULL == dst) { 486 return false; 487 } 488 SkAutoPixmapUnlock result; 489 if (!this->requestLock(&result)) { 490 return false; 491 } 492 return copy_pixels_to(result.pixmap(), dst, dstSize, dstRB, preserveDstPad); 493} 494 495/////////////////////////////////////////////////////////////////////////////// 496 497bool SkBitmap::isImmutable() const { 498 return fPixelRef ? fPixelRef->isImmutable() : false; 499} 500 501void SkBitmap::setImmutable() { 502 if (fPixelRef) { 503 fPixelRef->setImmutable(); 504 } 505} 506 507bool SkBitmap::isVolatile() const { 508 return (fFlags & kImageIsVolatile_Flag) != 0; 509} 510 511void SkBitmap::setIsVolatile(bool isVolatile) { 512 if (isVolatile) { 513 fFlags |= kImageIsVolatile_Flag; 514 } else { 515 fFlags &= ~kImageIsVolatile_Flag; 516 } 517} 518 519void* SkBitmap::getAddr(int x, int y) const { 520 SkASSERT((unsigned)x < (unsigned)this->width()); 521 SkASSERT((unsigned)y < (unsigned)this->height()); 522 523 char* base = (char*)this->getPixels(); 524 if (base) { 525 base += y * this->rowBytes(); 526 switch (this->colorType()) { 527 case kRGBA_8888_SkColorType: 528 case kBGRA_8888_SkColorType: 529 base += x << 2; 530 break; 531 case kARGB_4444_SkColorType: 532 case kRGB_565_SkColorType: 533 base += x << 1; 534 break; 535 case kAlpha_8_SkColorType: 536 case kIndex_8_SkColorType: 537 case kGray_8_SkColorType: 538 base += x; 539 break; 540 default: 541 SkDEBUGFAIL("Can't return addr for config"); 542 base = NULL; 543 break; 544 } 545 } 546 return base; 547} 548 549SkColor SkBitmap::getColor(int x, int y) const { 550 SkASSERT((unsigned)x < (unsigned)this->width()); 551 SkASSERT((unsigned)y < (unsigned)this->height()); 552 553 switch (this->colorType()) { 554 case kGray_8_SkColorType: { 555 uint8_t* addr = this->getAddr8(x, y); 556 return SkColorSetRGB(*addr, *addr, *addr); 557 } 558 case kAlpha_8_SkColorType: { 559 uint8_t* addr = this->getAddr8(x, y); 560 return SkColorSetA(0, addr[0]); 561 } 562 case kIndex_8_SkColorType: { 563 SkPMColor c = this->getIndex8Color(x, y); 564 return SkUnPreMultiply::PMColorToColor(c); 565 } 566 case kRGB_565_SkColorType: { 567 uint16_t* addr = this->getAddr16(x, y); 568 return SkPixel16ToColor(addr[0]); 569 } 570 case kARGB_4444_SkColorType: { 571 uint16_t* addr = this->getAddr16(x, y); 572 SkPMColor c = SkPixel4444ToPixel32(addr[0]); 573 return SkUnPreMultiply::PMColorToColor(c); 574 } 575 case kBGRA_8888_SkColorType: 576 case kRGBA_8888_SkColorType: { 577 uint32_t* addr = this->getAddr32(x, y); 578 return SkUnPreMultiply::PMColorToColor(addr[0]); 579 } 580 default: 581 SkASSERT(false); 582 return 0; 583 } 584 SkASSERT(false); // Not reached. 585 return 0; 586} 587 588static bool compute_is_opaque(const SkPixmap& pmap) { 589 const int height = pmap.height(); 590 const int width = pmap.width(); 591 592 switch (pmap.colorType()) { 593 case kAlpha_8_SkColorType: { 594 unsigned a = 0xFF; 595 for (int y = 0; y < height; ++y) { 596 const uint8_t* row = pmap.addr8(0, y); 597 for (int x = 0; x < width; ++x) { 598 a &= row[x]; 599 } 600 if (0xFF != a) { 601 return false; 602 } 603 } 604 return true; 605 } break; 606 case kIndex_8_SkColorType: { 607 const SkColorTable* ctable = pmap.ctable(); 608 if (NULL == ctable) { 609 return false; 610 } 611 const SkPMColor* table = ctable->readColors(); 612 SkPMColor c = (SkPMColor)~0; 613 for (int i = ctable->count() - 1; i >= 0; --i) { 614 c &= table[i]; 615 } 616 return 0xFF == SkGetPackedA32(c); 617 } break; 618 case kRGB_565_SkColorType: 619 case kGray_8_SkColorType: 620 return true; 621 break; 622 case kARGB_4444_SkColorType: { 623 unsigned c = 0xFFFF; 624 for (int y = 0; y < height; ++y) { 625 const SkPMColor16* row = pmap.addr16(0, y); 626 for (int x = 0; x < width; ++x) { 627 c &= row[x]; 628 } 629 if (0xF != SkGetPackedA4444(c)) { 630 return false; 631 } 632 } 633 return true; 634 } break; 635 case kBGRA_8888_SkColorType: 636 case kRGBA_8888_SkColorType: { 637 SkPMColor c = (SkPMColor)~0; 638 for (int y = 0; y < height; ++y) { 639 const SkPMColor* row = pmap.addr32(0, y); 640 for (int x = 0; x < width; ++x) { 641 c &= row[x]; 642 } 643 if (0xFF != SkGetPackedA32(c)) { 644 return false; 645 } 646 } 647 return true; 648 } 649 default: 650 break; 651 } 652 return false; 653} 654 655bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { 656 SkAutoPixmapUnlock result; 657 if (!bm.requestLock(&result)) { 658 return false; 659 } 660 return compute_is_opaque(result.pixmap()); 661} 662 663 664/////////////////////////////////////////////////////////////////////////////// 665/////////////////////////////////////////////////////////////////////////////// 666 667void SkBitmap::erase(SkColor c, const SkIRect& area) const { 668 SkDEBUGCODE(this->validate();) 669 670 switch (fInfo.colorType()) { 671 case kUnknown_SkColorType: 672 case kIndex_8_SkColorType: 673 // TODO: can we ASSERT that we never get here? 674 return; // can't erase. Should we bzero so the memory is not uninitialized? 675 default: 676 break; 677 } 678 679 SkAutoPixmapUnlock result; 680 if (!this->requestLock(&result)) { 681 return; 682 } 683 684 if (result.pixmap().erase(c, area)) { 685 this->notifyPixelsChanged(); 686 } 687} 688 689void SkBitmap::eraseColor(SkColor c) const { 690 this->erase(c, SkIRect::MakeWH(this->width(), this->height())); 691} 692 693////////////////////////////////////////////////////////////////////////////////////// 694////////////////////////////////////////////////////////////////////////////////////// 695 696bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { 697 SkDEBUGCODE(this->validate();) 698 699 if (NULL == result || NULL == fPixelRef) { 700 return false; // no src pixels 701 } 702 703 SkIRect srcRect, r; 704 srcRect.set(0, 0, this->width(), this->height()); 705 if (!r.intersect(srcRect, subset)) { 706 return false; // r is empty (i.e. no intersection) 707 } 708 709 if (fPixelRef->getTexture() != NULL) { 710 // Do a deep copy 711 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), this->profileType(), &subset); 712 if (pixelRef != NULL) { 713 SkBitmap dst; 714 dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(), 715 this->colorType(), this->alphaType())); 716 dst.setIsVolatile(this->isVolatile()); 717 dst.setPixelRef(pixelRef)->unref(); 718 SkDEBUGCODE(dst.validate()); 719 result->swap(dst); 720 return true; 721 } 722 } 723 724 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 725 // exited above. 726 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 727 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 728 729 SkBitmap dst; 730 dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()), 731 this->rowBytes()); 732 dst.setIsVolatile(this->isVolatile()); 733 734 if (fPixelRef) { 735 SkIPoint origin = fPixelRefOrigin; 736 origin.fX += r.fLeft; 737 origin.fY += r.fTop; 738 // share the pixelref with a custom offset 739 dst.setPixelRef(fPixelRef, origin); 740 } 741 SkDEBUGCODE(dst.validate();) 742 743 // we know we're good, so commit to result 744 result->swap(dst); 745 return true; 746} 747 748/////////////////////////////////////////////////////////////////////////////// 749 750bool SkBitmap::canCopyTo(SkColorType dstColorType) const { 751 const SkColorType srcCT = this->colorType(); 752 753 if (srcCT == kUnknown_SkColorType) { 754 return false; 755 } 756 757 bool sameConfigs = (srcCT == dstColorType); 758 switch (dstColorType) { 759 case kAlpha_8_SkColorType: 760 case kRGB_565_SkColorType: 761 case kRGBA_8888_SkColorType: 762 case kBGRA_8888_SkColorType: 763 break; 764 case kIndex_8_SkColorType: 765 if (!sameConfigs) { 766 return false; 767 } 768 break; 769 case kARGB_4444_SkColorType: 770 return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorType == srcCT; 771 case kGray_8_SkColorType: 772 switch (srcCT) { 773 case kGray_8_SkColorType: 774 case kRGBA_8888_SkColorType: 775 case kBGRA_8888_SkColorType: 776 return true; 777 default: 778 break; 779 } 780 return false; 781 default: 782 return false; 783 } 784 return true; 785} 786 787bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB, 788 int x, int y) const { 789 SkAutoPixmapUnlock src; 790 if (!this->requestLock(&src)) { 791 return false; 792 } 793 return src.pixmap().readPixels(requestedDstInfo, dstPixels, dstRB, x, y); 794} 795 796bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const { 797 if (!this->canCopyTo(dstColorType)) { 798 return false; 799 } 800 801 // if we have a texture, first get those pixels 802 SkBitmap tmpSrc; 803 const SkBitmap* src = this; 804 805 if (fPixelRef) { 806 SkIRect subset; 807 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, 808 fInfo.width(), fInfo.height()); 809 if (fPixelRef->readPixels(&tmpSrc, &subset)) { 810 if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) { 811 // FIXME: The only meaningful implementation of readPixels 812 // (GrPixelRef) assumes premultiplied pixels. 813 return false; 814 } 815 SkASSERT(tmpSrc.width() == this->width()); 816 SkASSERT(tmpSrc.height() == this->height()); 817 818 // did we get lucky and we can just return tmpSrc? 819 if (tmpSrc.colorType() == dstColorType && NULL == alloc) { 820 dst->swap(tmpSrc); 821 // If the result is an exact copy, clone the gen ID. 822 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) { 823 dst->pixelRef()->cloneGenID(*fPixelRef); 824 } 825 return true; 826 } 827 828 // fall through to the raster case 829 src = &tmpSrc; 830 } 831 } 832 833 SkAutoPixmapUnlock srcUnlocker; 834 if (!src->requestLock(&srcUnlocker)) { 835 return false; 836 } 837 const SkPixmap& srcPM = srcUnlocker.pixmap(); 838 839 const SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType); 840 SkBitmap tmpDst; 841 if (!tmpDst.setInfo(dstInfo)) { 842 return false; 843 } 844 845 // allocate colortable if srcConfig == kIndex8_Config 846 SkAutoTUnref<SkColorTable> ctable; 847 if (dstColorType == kIndex_8_SkColorType) { 848 ctable.reset(SkRef(srcPM.ctable())); 849 } 850 if (!tmpDst.tryAllocPixels(alloc, ctable)) { 851 return false; 852 } 853 854 SkAutoPixmapUnlock dstUnlocker; 855 if (!tmpDst.requestLock(&dstUnlocker)) { 856 return false; 857 } 858 859 if (!srcPM.readPixels(dstUnlocker.pixmap())) { 860 return false; 861 } 862 863 // (for BitmapHeap) Clone the pixelref genID even though we have a new pixelref. 864 // The old copyTo impl did this, so we continue it for now. 865 // 866 // TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be 867 // if (src_pixelref->info == dst_pixelref->info) 868 // 869 if (srcPM.colorType() == dstColorType && tmpDst.getSize() == srcPM.getSize64()) { 870 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); 871 if (dstPixelRef->info() == fPixelRef->info()) { 872 dstPixelRef->cloneGenID(*fPixelRef); 873 } 874 } 875 876 dst->swap(tmpDst); 877 return true; 878} 879 880bool SkBitmap::deepCopyTo(SkBitmap* dst) const { 881 const SkColorType dstCT = this->colorType(); 882 const SkColorProfileType dstPT = this->profileType(); 883 884 if (!this->canCopyTo(dstCT)) { 885 return false; 886 } 887 888 // If we have a PixelRef, and it supports deep copy, use it. 889 // Currently supported only by texture-backed bitmaps. 890 if (fPixelRef) { 891 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, dstPT, NULL); 892 if (pixelRef) { 893 uint32_t rowBytes; 894 if (this->colorType() == dstCT && this->profileType() == dstPT) { 895 // Since there is no subset to pass to deepCopy, and deepCopy 896 // succeeded, the new pixel ref must be identical. 897 SkASSERT(fPixelRef->info() == pixelRef->info()); 898 pixelRef->cloneGenID(*fPixelRef); 899 // Use the same rowBytes as the original. 900 rowBytes = fRowBytes; 901 } else { 902 // With the new config, an appropriate fRowBytes will be computed by setInfo. 903 rowBytes = 0; 904 } 905 906 const SkImageInfo info = fInfo.makeColorType(dstCT); 907 if (!dst->setInfo(info, rowBytes)) { 908 return false; 909 } 910 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); 911 return true; 912 } 913 } 914 915 if (this->getTexture()) { 916 return false; 917 } else { 918 return this->copyTo(dst, dstCT, NULL); 919 } 920} 921 922/////////////////////////////////////////////////////////////////////////////// 923 924static void rect_memset(uint8_t* array, U8CPU value, SkISize size, size_t rowBytes) { 925 for (int y = 0; y < size.height(); ++y) { 926 memset(array, value, size.width()); 927 array += rowBytes; 928 } 929} 930 931static void get_bitmap_alpha(const SkPixmap& pmap, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) { 932 SkColorType colorType = pmap.colorType(); 933 int w = pmap.width(); 934 int h = pmap.height(); 935 size_t rb = pmap.rowBytes(); 936 937 if (kAlpha_8_SkColorType == colorType && !pmap.isOpaque()) { 938 const uint8_t* s = pmap.addr8(0, 0); 939 while (--h >= 0) { 940 memcpy(alpha, s, w); 941 s += rb; 942 alpha += alphaRowBytes; 943 } 944 } else if (kN32_SkColorType == colorType && !pmap.isOpaque()) { 945 const SkPMColor* SK_RESTRICT s = pmap.addr32(0, 0); 946 while (--h >= 0) { 947 for (int x = 0; x < w; x++) { 948 alpha[x] = SkGetPackedA32(s[x]); 949 } 950 s = (const SkPMColor*)((const char*)s + rb); 951 alpha += alphaRowBytes; 952 } 953 } else if (kARGB_4444_SkColorType == colorType && !pmap.isOpaque()) { 954 const SkPMColor16* SK_RESTRICT s = pmap.addr16(0, 0); 955 while (--h >= 0) { 956 for (int x = 0; x < w; x++) { 957 alpha[x] = SkPacked4444ToA32(s[x]); 958 } 959 s = (const SkPMColor16*)((const char*)s + rb); 960 alpha += alphaRowBytes; 961 } 962 } else if (kIndex_8_SkColorType == colorType && !pmap.isOpaque()) { 963 const SkColorTable* ct = pmap.ctable(); 964 if (ct) { 965 const SkPMColor* SK_RESTRICT table = ct->readColors(); 966 const uint8_t* SK_RESTRICT s = pmap.addr8(0, 0); 967 while (--h >= 0) { 968 for (int x = 0; x < w; x++) { 969 alpha[x] = SkGetPackedA32(table[s[x]]); 970 } 971 s += rb; 972 alpha += alphaRowBytes; 973 } 974 } 975 } else { // src is opaque, so just fill alpha[] with 0xFF 976 rect_memset(alpha, 0xFF, pmap.info().dimensions(), alphaRowBytes); 977 } 978} 979 980static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) { 981 SkASSERT(alpha != NULL); 982 SkASSERT(alphaRowBytes >= src.width()); 983 984 SkAutoPixmapUnlock apl; 985 if (!src.requestLock(&apl)) { 986 rect_memset(alpha, 0, src.info().dimensions(), alphaRowBytes); 987 return false; 988 } 989 get_bitmap_alpha(apl.pixmap(), alpha, alphaRowBytes); 990 return true; 991} 992 993#include "SkPaint.h" 994#include "SkMaskFilter.h" 995#include "SkMatrix.h" 996 997bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, 998 Allocator *allocator, SkIPoint* offset) const { 999 SkDEBUGCODE(this->validate();) 1000 1001 SkBitmap tmpBitmap; 1002 SkMatrix identity; 1003 SkMask srcM, dstM; 1004 1005 srcM.fBounds.set(0, 0, this->width(), this->height()); 1006 srcM.fRowBytes = SkAlign4(this->width()); 1007 srcM.fFormat = SkMask::kA8_Format; 1008 1009 SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL; 1010 1011 // compute our (larger?) dst bounds if we have a filter 1012 if (filter) { 1013 identity.reset(); 1014 srcM.fImage = NULL; 1015 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1016 goto NO_FILTER_CASE; 1017 } 1018 dstM.fRowBytes = SkAlign4(dstM.fBounds.width()); 1019 } else { 1020 NO_FILTER_CASE: 1021 tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes); 1022 if (!tmpBitmap.tryAllocPixels(allocator, NULL)) { 1023 // Allocation of pixels for alpha bitmap failed. 1024 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1025 tmpBitmap.width(), tmpBitmap.height()); 1026 return false; 1027 } 1028 GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes); 1029 if (offset) { 1030 offset->set(0, 0); 1031 } 1032 tmpBitmap.swap(*dst); 1033 return true; 1034 } 1035 srcM.fImage = SkMask::AllocImage(srcM.computeImageSize()); 1036 SkAutoMaskFreeImage srcCleanup(srcM.fImage); 1037 1038 GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes); 1039 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1040 goto NO_FILTER_CASE; 1041 } 1042 SkAutoMaskFreeImage dstCleanup(dstM.fImage); 1043 1044 tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()), 1045 dstM.fRowBytes); 1046 if (!tmpBitmap.tryAllocPixels(allocator, NULL)) { 1047 // Allocation of pixels for alpha bitmap failed. 1048 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1049 tmpBitmap.width(), tmpBitmap.height()); 1050 return false; 1051 } 1052 memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize()); 1053 if (offset) { 1054 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); 1055 } 1056 SkDEBUGCODE(tmpBitmap.validate();) 1057 1058 tmpBitmap.swap(*dst); 1059 return true; 1060} 1061 1062/////////////////////////////////////////////////////////////////////////////// 1063 1064static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) { 1065 const SkImageInfo& info = pmap.info(); 1066 const size_t snugRB = info.width() * info.bytesPerPixel(); 1067 const char* src = (const char*)pmap.addr(); 1068 const size_t ramRB = pmap.rowBytes(); 1069 1070 buffer->write32(SkToU32(snugRB)); 1071 info.flatten(*buffer); 1072 1073 const size_t size = snugRB * info.height(); 1074 SkAutoMalloc storage(size); 1075 char* dst = (char*)storage.get(); 1076 for (int y = 0; y < info.height(); ++y) { 1077 memcpy(dst, src, snugRB); 1078 dst += snugRB; 1079 src += ramRB; 1080 } 1081 buffer->writeByteArray(storage.get(), size); 1082 1083 const SkColorTable* ct = pmap.ctable(); 1084 if (kIndex_8_SkColorType == info.colorType() && ct) { 1085 buffer->writeBool(true); 1086 ct->writeToBuffer(*buffer); 1087 } else { 1088 buffer->writeBool(false); 1089 } 1090} 1091 1092void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) { 1093 const SkImageInfo info = bitmap.info(); 1094 if (0 == info.width() || 0 == info.height() || NULL == bitmap.pixelRef()) { 1095 buffer->writeUInt(0); // instead of snugRB, signaling no pixels 1096 return; 1097 } 1098 1099 SkAutoPixmapUnlock result; 1100 if (!bitmap.requestLock(&result)) { 1101 buffer->writeUInt(0); // instead of snugRB, signaling no pixels 1102 return; 1103 } 1104 1105 write_raw_pixels(buffer, result.pixmap()); 1106} 1107 1108bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) { 1109 const size_t snugRB = buffer->readUInt(); 1110 if (0 == snugRB) { // no pixels 1111 return false; 1112 } 1113 1114 SkImageInfo info; 1115 info.unflatten(*buffer); 1116 1117 // If there was an error reading "info", don't use it to compute minRowBytes() 1118 if (!buffer->validate(true)) { 1119 return false; 1120 } 1121 1122 const size_t ramRB = info.minRowBytes(); 1123 const int height = SkMax32(info.height(), 0); 1124 const uint64_t snugSize = sk_64_mul(snugRB, height); 1125 const uint64_t ramSize = sk_64_mul(ramRB, height); 1126 static const uint64_t max_size_t = (size_t)(-1); 1127 if (!buffer->validate((snugSize <= ramSize) && (ramSize <= max_size_t))) { 1128 return false; 1129 } 1130 1131 SkAutoDataUnref data(SkData::NewUninitialized(SkToSizeT(ramSize))); 1132 unsigned char* dst = (unsigned char*)data->writable_data(); 1133 buffer->readByteArray(dst, SkToSizeT(snugSize)); 1134 1135 if (snugSize != ramSize) { 1136 const unsigned char* srcRow = dst + snugRB * (height - 1); 1137 unsigned char* dstRow = dst + ramRB * (height - 1); 1138 for (int y = height - 1; y >= 1; --y) { 1139 memmove(dstRow, srcRow, snugRB); 1140 srcRow -= snugRB; 1141 dstRow -= ramRB; 1142 } 1143 SkASSERT(srcRow == dstRow); // first row does not need to be moved 1144 } 1145 1146 SkAutoTUnref<SkColorTable> ctable; 1147 if (buffer->readBool()) { 1148 ctable.reset(SkNEW_ARGS(SkColorTable, (*buffer))); 1149 1150 unsigned char maxIndex = ctable->count() ? ctable->count()-1 : 0; 1151 for (uint64_t i = 0; i < ramSize; ++i) { 1152 dst[i] = SkTMin(dst[i], maxIndex); 1153 } 1154 } 1155 1156 SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(), 1157 ctable.get(), data.get())); 1158 if (!pr.get()) { 1159 return false; 1160 } 1161 bitmap->setInfo(pr->info()); 1162 bitmap->setPixelRef(pr, 0, 0); 1163 return true; 1164} 1165 1166enum { 1167 SERIALIZE_PIXELTYPE_NONE, 1168 SERIALIZE_PIXELTYPE_REF_DATA 1169}; 1170 1171/////////////////////////////////////////////////////////////////////////////// 1172 1173SkBitmap::RLEPixels::RLEPixels(int width, int height) { 1174 fHeight = height; 1175 fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*)); 1176} 1177 1178SkBitmap::RLEPixels::~RLEPixels() { 1179 sk_free(fYPtrs); 1180} 1181 1182/////////////////////////////////////////////////////////////////////////////// 1183 1184#ifdef SK_DEBUG 1185void SkBitmap::validate() const { 1186 fInfo.validate(); 1187 1188 // ImageInfo may not require this, but Bitmap ensures that opaque-only 1189 // colorTypes report opaque for their alphatype 1190 if (kRGB_565_SkColorType == fInfo.colorType()) { 1191 SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType()); 1192 } 1193 1194 SkASSERT(fInfo.validRowBytes(fRowBytes)); 1195 uint8_t allFlags = kImageIsVolatile_Flag; 1196#ifdef SK_BUILD_FOR_ANDROID 1197 allFlags |= kHasHardwareMipMap_Flag; 1198#endif 1199 SkASSERT((~allFlags & fFlags) == 0); 1200 SkASSERT(fPixelLockCount >= 0); 1201 1202 if (fPixels) { 1203 SkASSERT(fPixelRef); 1204 SkASSERT(fPixelLockCount > 0); 1205 SkASSERT(fPixelRef->isLocked()); 1206 SkASSERT(fPixelRef->rowBytes() == fRowBytes); 1207 SkASSERT(fPixelRefOrigin.fX >= 0); 1208 SkASSERT(fPixelRefOrigin.fY >= 0); 1209 SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX); 1210 SkASSERT(fPixelRef->info().height() >= (int)this->height() + fPixelRefOrigin.fY); 1211 SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes()); 1212 } else { 1213 SkASSERT(NULL == fColorTable); 1214 } 1215} 1216#endif 1217 1218#ifndef SK_IGNORE_TO_STRING 1219#include "SkString.h" 1220void SkBitmap::toString(SkString* str) const { 1221 1222 static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = { 1223 "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8", 1224 }; 1225 1226 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), 1227 gColorTypeNames[this->colorType()]); 1228 1229 str->append(" ("); 1230 if (this->isOpaque()) { 1231 str->append("opaque"); 1232 } else { 1233 str->append("transparent"); 1234 } 1235 if (this->isImmutable()) { 1236 str->append(", immutable"); 1237 } else { 1238 str->append(", not-immutable"); 1239 } 1240 str->append(")"); 1241 1242 SkPixelRef* pr = this->pixelRef(); 1243 if (NULL == pr) { 1244 // show null or the explicit pixel address (rare) 1245 str->appendf(" pixels:%p", this->getPixels()); 1246 } else { 1247 const char* uri = pr->getURI(); 1248 if (uri) { 1249 str->appendf(" uri:\"%s\"", uri); 1250 } else { 1251 str->appendf(" pixelref:%p", pr); 1252 } 1253 } 1254 1255 str->append(")"); 1256} 1257#endif 1258 1259/////////////////////////////////////////////////////////////////////////////// 1260 1261bool SkBitmap::requestLock(SkAutoPixmapUnlock* result) const { 1262 SkASSERT(result); 1263 1264 SkPixelRef* pr = fPixelRef; 1265 if (NULL == pr) { 1266 return false; 1267 } 1268 1269 // We have to lock the whole thing (using the pixelref's dimensions) until the api supports 1270 // a partial lock (with offset/origin). Hence we can't use our fInfo. 1271 SkPixelRef::LockRequest req = { pr->info().dimensions(), kNone_SkFilterQuality }; 1272 SkPixelRef::LockResult res; 1273 if (pr->requestLock(req, &res)) { 1274 SkASSERT(res.fPixels); 1275 // The bitmap may be a subset of the pixelref's dimensions 1276 SkASSERT(fPixelRefOrigin.x() + fInfo.width() <= res.fSize.width()); 1277 SkASSERT(fPixelRefOrigin.y() + fInfo.height() <= res.fSize.height()); 1278 const void* addr = (const char*)res.fPixels + SkColorTypeComputeOffset(fInfo.colorType(), 1279 fPixelRefOrigin.x(), 1280 fPixelRefOrigin.y(), 1281 res.fRowBytes); 1282 1283 result->reset(SkPixmap(this->info(), addr, res.fRowBytes, res.fCTable), 1284 res.fUnlockProc, res.fUnlockContext); 1285 return true; 1286 } 1287 return false; 1288} 1289 1290bool SkBitmap::peekPixels(SkPixmap* pmap) const { 1291 if (fPixels) { 1292 if (pmap) { 1293 pmap->reset(fInfo, fPixels, fRowBytes, fColorTable); 1294 } 1295 return true; 1296 } 1297 return false; 1298} 1299 1300/////////////////////////////////////////////////////////////////////////////// 1301 1302#ifdef SK_DEBUG 1303void SkImageInfo::validate() const { 1304 SkASSERT(fWidth >= 0); 1305 SkASSERT(fHeight >= 0); 1306 SkASSERT(SkColorTypeIsValid(fColorType)); 1307 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); 1308} 1309#endif 1310