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