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