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 "SkColorTable.h" 12#include "SkConvertPixels.h" 13#include "SkData.h" 14#include "SkFilterQuality.h" 15#include "SkHalf.h" 16#include "SkImageInfoPriv.h" 17#include "SkMallocPixelRef.h" 18#include "SkMask.h" 19#include "SkMath.h" 20#include "SkPixelRef.h" 21#include "SkReadBuffer.h" 22#include "SkRect.h" 23#include "SkScalar.h" 24#include "SkTemplates.h" 25#include "SkUnPreMultiply.h" 26#include "SkWriteBuffer.h" 27#include "SkWritePixelsRec.h" 28 29#include <string.h> 30 31static bool reset_return_false(SkBitmap* bm) { 32 bm->reset(); 33 return false; 34} 35 36SkBitmap::SkBitmap() 37 : fPixels (nullptr) 38 , fPixelRefOrigin{0, 0} 39 , fRowBytes (0) 40 , fFlags (0) {} 41 42SkBitmap::SkBitmap(const SkBitmap& src) 43 : fPixelRef (src.fPixelRef) 44 , fPixels (src.fPixels) 45 , fPixelRefOrigin(src.fPixelRefOrigin) 46 , fInfo (src.fInfo) 47 , fRowBytes (src.fRowBytes) 48 , fFlags (src.fFlags) 49{ 50 SkDEBUGCODE(src.validate();) 51 SkDEBUGCODE(this->validate();) 52} 53 54SkBitmap::SkBitmap(SkBitmap&& other) 55 : fPixelRef (std::move(other.fPixelRef)) 56 , fPixels (other.fPixels) 57 , fPixelRefOrigin (other.fPixelRefOrigin) 58 , fInfo (std::move(other.fInfo)) 59 , fRowBytes (other.fRowBytes) 60 , fFlags (other.fFlags) 61{ 62 SkASSERT(!other.fPixelRef); 63 other.fInfo.reset(); 64 other.fPixels = nullptr; 65 other.fPixelRefOrigin = SkIPoint{0, 0}; 66 other.fRowBytes = 0; 67 other.fFlags = 0; 68} 69 70SkBitmap::~SkBitmap() {} 71 72SkBitmap& SkBitmap::operator=(const SkBitmap& src) { 73 if (this != &src) { 74 fPixelRef = src.fPixelRef; 75 fPixels = src.fPixels; 76 fPixelRefOrigin = src.fPixelRefOrigin; 77 fInfo = src.fInfo; 78 fRowBytes = src.fRowBytes; 79 fFlags = src.fFlags; 80 } 81 SkDEBUGCODE(this->validate();) 82 return *this; 83} 84 85SkBitmap& SkBitmap::operator=(SkBitmap&& other) { 86 if (this != &other) { 87 fPixelRef = std::move(other.fPixelRef); 88 fInfo = std::move(other.fInfo); 89 fPixels = other.fPixels; 90 fPixelRefOrigin = other.fPixelRefOrigin; 91 fRowBytes = other.fRowBytes; 92 fFlags = other.fFlags; 93 SkASSERT(!other.fPixelRef); 94 other.fInfo.reset(); 95 other.fPixels = nullptr; 96 other.fPixelRefOrigin = SkIPoint{0, 0}; 97 other.fRowBytes = 0; 98 other.fFlags = 0; 99 } 100 return *this; 101} 102 103void SkBitmap::swap(SkBitmap& other) { 104 SkTSwap(*this, other); 105 SkDEBUGCODE(this->validate();) 106} 107 108void SkBitmap::reset() { 109 this->freePixels(); 110 this->fInfo.reset(); 111 sk_bzero(this, sizeof(*this)); 112} 113 114void SkBitmap::getBounds(SkRect* bounds) const { 115 SkASSERT(bounds); 116 bounds->set(0, 0, 117 SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height())); 118} 119 120void SkBitmap::getBounds(SkIRect* bounds) const { 121 SkASSERT(bounds); 122 bounds->set(0, 0, fInfo.width(), fInfo.height()); 123} 124 125/////////////////////////////////////////////////////////////////////////////// 126 127bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) { 128 SkAlphaType newAT = info.alphaType(); 129 if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) { 130 return reset_return_false(this); 131 } 132 // don't look at info.alphaType(), since newAT is the real value... 133 134 // require that rowBytes fit in 31bits 135 int64_t mrb = info.minRowBytes64(); 136 if ((int32_t)mrb != mrb) { 137 return reset_return_false(this); 138 } 139 if ((int64_t)rowBytes != (int32_t)rowBytes) { 140 return reset_return_false(this); 141 } 142 143 if (info.width() < 0 || info.height() < 0) { 144 return reset_return_false(this); 145 } 146 147 if (kUnknown_SkColorType == info.colorType()) { 148 rowBytes = 0; 149 } else if (0 == rowBytes) { 150 rowBytes = (size_t)mrb; 151 } else if (!info.validRowBytes(rowBytes)) { 152 return reset_return_false(this); 153 } 154 155 this->freePixels(); 156 157 fInfo = info.makeAlphaType(newAT); 158 fRowBytes = SkToU32(rowBytes); 159 SkDEBUGCODE(this->validate();) 160 return true; 161} 162 163bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) { 164 if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) { 165 return false; 166 } 167 if (fInfo.alphaType() != newAlphaType) { 168 fInfo = fInfo.makeAlphaType(newAlphaType); 169 } 170 SkDEBUGCODE(this->validate();) 171 return true; 172} 173 174void SkBitmap::updatePixelsFromRef() { 175 void* p = nullptr; 176 if (fPixelRef) { 177 // wish we could assert that a pixelref *always* has pixels 178 p = fPixelRef->pixels(); 179 if (p) { 180 SkASSERT(fRowBytes == fPixelRef->rowBytes()); 181 p = (char*)p 182 + fPixelRefOrigin.fY * fRowBytes 183 + fPixelRefOrigin.fX * fInfo.bytesPerPixel(); 184 } 185 } 186 fPixels = p; 187} 188 189void SkBitmap::setPixelRef(sk_sp<SkPixelRef> pr, int dx, int dy) { 190#ifdef SK_DEBUG 191 if (pr) { 192 if (kUnknown_SkColorType != fInfo.colorType()) { 193 SkASSERT(fInfo.width() + dx <= pr->width()); 194 SkASSERT(fInfo.height() + dy <= pr->height()); 195 } 196 } 197#endif 198 199 fPixelRef = std::move(pr); 200 if (fPixelRef) { 201 fPixelRefOrigin.set(SkTPin(dx, 0, fPixelRef->width()), SkTPin(dy, 0, fPixelRef->height())); 202 this->updatePixelsFromRef(); 203 } else { 204 // ignore dx,dy if there is no pixelref 205 fPixelRefOrigin.setZero(); 206 fPixels = nullptr; 207 } 208 209 SkDEBUGCODE(this->validate();) 210} 211 212void SkBitmap::setPixels(void* p) { 213 if (nullptr == p) { 214 this->setPixelRef(nullptr, 0, 0); 215 return; 216 } 217 218 if (kUnknown_SkColorType == fInfo.colorType()) { 219 this->setPixelRef(nullptr, 0, 0); 220 return; 221 } 222 223 this->setPixelRef(SkMallocPixelRef::MakeDirect(fInfo, p, fRowBytes), 0, 0); 224 if (!fPixelRef) { 225 return; 226 } 227 SkDEBUGCODE(this->validate();) 228} 229 230bool SkBitmap::tryAllocPixels(Allocator* allocator) { 231 HeapAllocator stdalloc; 232 233 if (nullptr == allocator) { 234 allocator = &stdalloc; 235 } 236#ifdef SK_SUPPORT_LEGACY_COLORTABLE 237 return allocator->allocPixelRef(this, nullptr); 238#else 239 return allocator->allocPixelRef(this); 240#endif 241} 242 243/////////////////////////////////////////////////////////////////////////////// 244 245bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) { 246 if (!this->setInfo(requestedInfo, rowBytes)) { 247 return reset_return_false(this); 248 } 249 250 // setInfo may have corrected info (e.g. 565 is always opaque). 251 const SkImageInfo& correctedInfo = this->info(); 252 // setInfo may have computed a valid rowbytes if 0 were passed in 253 rowBytes = this->rowBytes(); 254 255 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(correctedInfo, rowBytes); 256 if (!pr) { 257 return reset_return_false(this); 258 } 259 this->setPixelRef(std::move(pr), 0, 0); 260 if (nullptr == this->getPixels()) { 261 return reset_return_false(this); 262 } 263 SkDEBUGCODE(this->validate();) 264 return true; 265} 266 267bool SkBitmap::tryAllocPixelsFlags(const SkImageInfo& requestedInfo, uint32_t allocFlags) { 268 if (!this->setInfo(requestedInfo)) { 269 return reset_return_false(this); 270 } 271 272 // setInfo may have corrected info (e.g. 565 is always opaque). 273 const SkImageInfo& correctedInfo = this->info(); 274 275 sk_sp<SkPixelRef> pr = (allocFlags & kZeroPixels_AllocFlag) ? 276 SkMallocPixelRef::MakeZeroed(correctedInfo, correctedInfo.minRowBytes()) : 277 SkMallocPixelRef::MakeAllocate(correctedInfo, correctedInfo.minRowBytes()); 278 if (!pr) { 279 return reset_return_false(this); 280 } 281 this->setPixelRef(std::move(pr), 0, 0); 282 if (nullptr == this->getPixels()) { 283 return reset_return_false(this); 284 } 285 SkDEBUGCODE(this->validate();) 286 return true; 287} 288 289static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) { 290 if (proc) { 291 proc(pixels, ctx); 292 } 293} 294 295bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb, 296 void (*releaseProc)(void* addr, void* context), void* context) { 297 if (!this->setInfo(requestedInfo, rb)) { 298 invoke_release_proc(releaseProc, pixels, context); 299 this->reset(); 300 return false; 301 } 302 if (nullptr == pixels) { 303 invoke_release_proc(releaseProc, pixels, context); 304 return true; // we behaved as if they called setInfo() 305 } 306 307 // setInfo may have corrected info (e.g. 565 is always opaque). 308 const SkImageInfo& correctedInfo = this->info(); 309 310 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeWithProc(correctedInfo, rb, pixels, 311 releaseProc, context); 312 if (!pr) { 313 this->reset(); 314 return false; 315 } 316 317 this->setPixelRef(std::move(pr), 0, 0); 318 SkDEBUGCODE(this->validate();) 319 return true; 320} 321 322bool SkBitmap::installPixels(const SkPixmap& pixmap) { 323 return this->installPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(), 324 nullptr, nullptr); 325} 326 327bool SkBitmap::installMaskPixels(const SkMask& mask) { 328 if (SkMask::kA8_Format != mask.fFormat) { 329 this->reset(); 330 return false; 331 } 332 return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), 333 mask.fBounds.height()), 334 mask.fImage, mask.fRowBytes); 335} 336 337/////////////////////////////////////////////////////////////////////////////// 338 339void SkBitmap::freePixels() { 340 fPixelRef = nullptr; 341 fPixelRefOrigin.setZero(); 342 fPixels = nullptr; 343} 344 345uint32_t SkBitmap::getGenerationID() const { 346 return fPixelRef ? fPixelRef->getGenerationID() : 0; 347} 348 349void SkBitmap::notifyPixelsChanged() const { 350 SkASSERT(!this->isImmutable()); 351 if (fPixelRef) { 352 fPixelRef->notifyPixelsChanged(); 353 } 354} 355 356/////////////////////////////////////////////////////////////////////////////// 357 358/** We explicitly use the same allocator for our pixels that SkMask does, 359 so that we can freely assign memory allocated by one class to the other. 360 */ 361bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst 362#ifdef SK_SUPPORT_LEGACY_COLORTABLE 363 , SkColorTable* 364#endif 365 ) { 366 const SkImageInfo info = dst->info(); 367 if (kUnknown_SkColorType == info.colorType()) { 368// SkDebugf("unsupported config for info %d\n", dst->config()); 369 return false; 370 } 371 372 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, dst->rowBytes()); 373 if (!pr) { 374 return false; 375 } 376 377 dst->setPixelRef(std::move(pr), 0, 0); 378 SkDEBUGCODE(dst->validate();) 379 return true; 380} 381 382/////////////////////////////////////////////////////////////////////////////// 383 384bool SkBitmap::isImmutable() const { 385 return fPixelRef ? fPixelRef->isImmutable() : false; 386} 387 388void SkBitmap::setImmutable() { 389 if (fPixelRef) { 390 fPixelRef->setImmutable(); 391 } 392} 393 394bool SkBitmap::isVolatile() const { 395 return (fFlags & kImageIsVolatile_Flag) != 0; 396} 397 398void SkBitmap::setIsVolatile(bool isVolatile) { 399 if (isVolatile) { 400 fFlags |= kImageIsVolatile_Flag; 401 } else { 402 fFlags &= ~kImageIsVolatile_Flag; 403 } 404} 405 406void* SkBitmap::getAddr(int x, int y) const { 407 SkASSERT((unsigned)x < (unsigned)this->width()); 408 SkASSERT((unsigned)y < (unsigned)this->height()); 409 410 char* base = (char*)this->getPixels(); 411 if (base) { 412 base += y * this->rowBytes(); 413 switch (this->colorType()) { 414 case kRGBA_F16_SkColorType: 415 base += x << 3; 416 break; 417 case kRGBA_8888_SkColorType: 418 case kBGRA_8888_SkColorType: 419 base += x << 2; 420 break; 421 case kARGB_4444_SkColorType: 422 case kRGB_565_SkColorType: 423 base += x << 1; 424 break; 425 case kAlpha_8_SkColorType: 426 case kGray_8_SkColorType: 427 base += x; 428 break; 429 default: 430 SkDEBUGFAIL("Can't return addr for config"); 431 base = nullptr; 432 break; 433 } 434 } 435 return base; 436} 437 438/////////////////////////////////////////////////////////////////////////////// 439/////////////////////////////////////////////////////////////////////////////// 440 441void SkBitmap::erase(SkColor c, const SkIRect& area) const { 442 SkDEBUGCODE(this->validate();) 443 444 switch (fInfo.colorType()) { 445 case kUnknown_SkColorType: 446 // TODO: can we ASSERT that we never get here? 447 return; // can't erase. Should we bzero so the memory is not uninitialized? 448 default: 449 break; 450 } 451 452 SkPixmap result; 453 if (!this->peekPixels(&result)) { 454 return; 455 } 456 457 if (result.erase(c, area)) { 458 this->notifyPixelsChanged(); 459 } 460} 461 462void SkBitmap::eraseColor(SkColor c) const { 463 this->erase(c, SkIRect::MakeWH(this->width(), this->height())); 464} 465 466////////////////////////////////////////////////////////////////////////////////////// 467////////////////////////////////////////////////////////////////////////////////////// 468 469bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { 470 SkDEBUGCODE(this->validate();) 471 472 if (nullptr == result || !fPixelRef) { 473 return false; // no src pixels 474 } 475 476 SkIRect srcRect, r; 477 srcRect.set(0, 0, this->width(), this->height()); 478 if (!r.intersect(srcRect, subset)) { 479 return false; // r is empty (i.e. no intersection) 480 } 481 482 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 483 // exited above. 484 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 485 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 486 487 SkBitmap dst; 488 dst.setInfo(this->info().makeWH(r.width(), r.height()), this->rowBytes()); 489 dst.setIsVolatile(this->isVolatile()); 490 491 if (fPixelRef) { 492 SkIPoint origin = fPixelRefOrigin; 493 origin.fX += r.fLeft; 494 origin.fY += r.fTop; 495 // share the pixelref with a custom offset 496 dst.setPixelRef(fPixelRef, origin.x(), origin.y()); 497 } 498 SkDEBUGCODE(dst.validate();) 499 500 // we know we're good, so commit to result 501 result->swap(dst); 502 return true; 503} 504 505/////////////////////////////////////////////////////////////////////////////// 506 507bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB, 508 int x, int y, SkTransferFunctionBehavior behavior) const { 509 SkPixmap src; 510 if (!this->peekPixels(&src)) { 511 return false; 512 } 513 return src.readPixels(requestedDstInfo, dstPixels, dstRB, x, y, behavior); 514} 515 516bool SkBitmap::readPixels(const SkPixmap& dst, int srcX, int srcY) const { 517 return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY); 518} 519 520bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY, 521 SkTransferFunctionBehavior behavior) { 522 if (!SkImageInfoValidConversion(fInfo, src.info())) { 523 return false; 524 } 525 526 SkWritePixelsRec rec(src.info(), src.addr(), src.rowBytes(), dstX, dstY); 527 if (!rec.trim(fInfo.width(), fInfo.height())) { 528 return false; 529 } 530 531 void* dstPixels = this->getAddr(rec.fX, rec.fY); 532 const SkImageInfo dstInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height()); 533 SkConvertPixels(dstInfo, dstPixels, this->rowBytes(), rec.fInfo, rec.fPixels, rec.fRowBytes, 534 nullptr, behavior); 535 return true; 536} 537 538/////////////////////////////////////////////////////////////////////////////// 539 540static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) { 541 SkASSERT(alpha != nullptr); 542 SkASSERT(alphaRowBytes >= src.width()); 543 544 SkPixmap pmap; 545 if (!src.peekPixels(&pmap)) { 546 for (int y = 0; y < src.height(); ++y) { 547 memset(alpha, 0, src.width()); 548 alpha += alphaRowBytes; 549 } 550 return false; 551 } 552 SkConvertPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes, 553 pmap.info(), pmap.addr(), pmap.rowBytes(), nullptr, 554 SkTransferFunctionBehavior::kRespect); 555 return true; 556} 557 558#include "SkPaint.h" 559#include "SkMaskFilter.h" 560#include "SkMatrix.h" 561 562bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, 563 Allocator *allocator, SkIPoint* offset) const { 564 SkDEBUGCODE(this->validate();) 565 566 SkBitmap tmpBitmap; 567 SkMatrix identity; 568 SkMask srcM, dstM; 569 570 srcM.fBounds.set(0, 0, this->width(), this->height()); 571 srcM.fRowBytes = SkAlign4(this->width()); 572 srcM.fFormat = SkMask::kA8_Format; 573 574 SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr; 575 576 // compute our (larger?) dst bounds if we have a filter 577 if (filter) { 578 identity.reset(); 579 if (!filter->filterMask(&dstM, srcM, identity, nullptr)) { 580 goto NO_FILTER_CASE; 581 } 582 dstM.fRowBytes = SkAlign4(dstM.fBounds.width()); 583 } else { 584 NO_FILTER_CASE: 585 tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes); 586 if (!tmpBitmap.tryAllocPixels(allocator)) { 587 // Allocation of pixels for alpha bitmap failed. 588 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 589 tmpBitmap.width(), tmpBitmap.height()); 590 return false; 591 } 592 GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes); 593 if (offset) { 594 offset->set(0, 0); 595 } 596 tmpBitmap.swap(*dst); 597 return true; 598 } 599 srcM.fImage = SkMask::AllocImage(srcM.computeImageSize()); 600 SkAutoMaskFreeImage srcCleanup(srcM.fImage); 601 602 GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes); 603 if (!filter->filterMask(&dstM, srcM, identity, nullptr)) { 604 goto NO_FILTER_CASE; 605 } 606 SkAutoMaskFreeImage dstCleanup(dstM.fImage); 607 608 tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()), 609 dstM.fRowBytes); 610 if (!tmpBitmap.tryAllocPixels(allocator)) { 611 // Allocation of pixels for alpha bitmap failed. 612 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 613 tmpBitmap.width(), tmpBitmap.height()); 614 return false; 615 } 616 memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize()); 617 if (offset) { 618 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); 619 } 620 SkDEBUGCODE(tmpBitmap.validate();) 621 622 tmpBitmap.swap(*dst); 623 return true; 624} 625 626/////////////////////////////////////////////////////////////////////////////// 627 628static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) { 629 const SkImageInfo& info = pmap.info(); 630 const size_t snugRB = info.width() * info.bytesPerPixel(); 631 const char* src = (const char*)pmap.addr(); 632 const size_t ramRB = pmap.rowBytes(); 633 634 buffer->write32(SkToU32(snugRB)); 635 info.flatten(*buffer); 636 637 const size_t size = snugRB * info.height(); 638 SkAutoTMalloc<char> storage(size); 639 char* dst = storage.get(); 640 for (int y = 0; y < info.height(); ++y) { 641 memcpy(dst, src, snugRB); 642 dst += snugRB; 643 src += ramRB; 644 } 645 buffer->writeByteArray(storage.get(), size); 646 // no colortable 647 buffer->writeBool(false); 648} 649 650void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) { 651 const SkImageInfo info = bitmap.info(); 652 if (0 == info.width() || 0 == info.height() || bitmap.isNull()) { 653 buffer->writeUInt(0); // instead of snugRB, signaling no pixels 654 return; 655 } 656 657 SkPixmap result; 658 if (!bitmap.peekPixels(&result)) { 659 buffer->writeUInt(0); // instead of snugRB, signaling no pixels 660 return; 661 } 662 663 write_raw_pixels(buffer, result); 664} 665 666bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) { 667 const size_t snugRB = buffer->readUInt(); 668 if (0 == snugRB) { // no pixels 669 return false; 670 } 671 672 SkImageInfo info; 673 info.unflatten(*buffer); 674 675 if (info.width() < 0 || info.height() < 0) { 676 return false; 677 } 678 679 // If there was an error reading "info" or if it is bogus, 680 // don't use it to compute minRowBytes() 681 if (!buffer->validate(SkColorTypeValidateAlphaType(info.colorType(), 682 info.alphaType()))) { 683 return false; 684 } 685 686 const size_t ramRB = info.minRowBytes(); 687 const int height = SkMax32(info.height(), 0); 688 const uint64_t snugSize = sk_64_mul(snugRB, height); 689 const uint64_t ramSize = sk_64_mul(ramRB, height); 690 static const uint64_t max_size_t = (size_t)(-1); 691 if (!buffer->validate((snugSize <= ramSize) && (ramSize <= max_size_t))) { 692 return false; 693 } 694 695 sk_sp<SkData> data(SkData::MakeUninitialized(SkToSizeT(ramSize))); 696 unsigned char* dst = (unsigned char*)data->writable_data(); 697 buffer->readByteArray(dst, SkToSizeT(snugSize)); 698 699 if (snugSize != ramSize) { 700 const unsigned char* srcRow = dst + snugRB * (height - 1); 701 unsigned char* dstRow = dst + ramRB * (height - 1); 702 for (int y = height - 1; y >= 1; --y) { 703 memmove(dstRow, srcRow, snugRB); 704 srcRow -= snugRB; 705 dstRow -= ramRB; 706 } 707 SkASSERT(srcRow == dstRow); // first row does not need to be moved 708 } 709 710 if (buffer->readBool()) { 711 sk_sp<SkColorTable> ctable = SkColorTable::Create(*buffer); 712 if (!ctable) { 713 return false; 714 } 715 716 if (info.isEmpty()) { 717 // require an empty ctable 718 if (ctable->count() != 0) { 719 buffer->validate(false); 720 return false; 721 } 722 } else { 723 // require a non-empty ctable 724 if (ctable->count() == 0) { 725 buffer->validate(false); 726 return false; 727 } 728 unsigned char maxIndex = ctable->count() - 1; 729 for (uint64_t i = 0; i < ramSize; ++i) { 730 dst[i] = SkTMin(dst[i], maxIndex); 731 } 732 } 733 } 734 735 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeWithData(info, info.minRowBytes(), 736 std::move(data)); 737 if (!pr) { 738 return false; 739 } 740 bitmap->setInfo(info); 741 bitmap->setPixelRef(std::move(pr), 0, 0); 742 return true; 743} 744 745enum { 746 SERIALIZE_PIXELTYPE_NONE, 747 SERIALIZE_PIXELTYPE_REF_DATA 748}; 749 750/////////////////////////////////////////////////////////////////////////////// 751 752#ifdef SK_DEBUG 753void SkBitmap::validate() const { 754 fInfo.validate(); 755 756 // ImageInfo may not require this, but Bitmap ensures that opaque-only 757 // colorTypes report opaque for their alphatype 758 if (kRGB_565_SkColorType == fInfo.colorType()) { 759 SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType()); 760 } 761 762 SkASSERT(fInfo.validRowBytes(fRowBytes)); 763 uint8_t allFlags = kImageIsVolatile_Flag; 764#ifdef SK_BUILD_FOR_ANDROID 765 allFlags |= kHasHardwareMipMap_Flag; 766#endif 767 SkASSERT((~allFlags & fFlags) == 0); 768 769 if (fPixelRef && fPixelRef->pixels()) { 770 SkASSERT(fPixels); 771 } else { 772 SkASSERT(!fPixels); 773 } 774 775 if (fPixels) { 776 SkASSERT(fPixelRef); 777 SkASSERT(fPixelRef->rowBytes() == fRowBytes); 778 SkASSERT(fPixelRefOrigin.fX >= 0); 779 SkASSERT(fPixelRefOrigin.fY >= 0); 780 SkASSERT(fPixelRef->width() >= (int)this->width() + fPixelRefOrigin.fX); 781 SkASSERT(fPixelRef->height() >= (int)this->height() + fPixelRefOrigin.fY); 782 SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes()); 783 } 784} 785#endif 786 787#ifndef SK_IGNORE_TO_STRING 788#include "SkString.h" 789void SkBitmap::toString(SkString* str) const { 790 791 static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = { 792 "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8", 793 }; 794 795 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), 796 gColorTypeNames[this->colorType()]); 797 798 str->append(" ("); 799 if (this->isOpaque()) { 800 str->append("opaque"); 801 } else { 802 str->append("transparent"); 803 } 804 if (this->isImmutable()) { 805 str->append(", immutable"); 806 } else { 807 str->append(", not-immutable"); 808 } 809 str->append(")"); 810 811 str->appendf(" pixelref:%p", this->pixelRef()); 812 str->append(")"); 813} 814#endif 815 816/////////////////////////////////////////////////////////////////////////////// 817 818bool SkBitmap::peekPixels(SkPixmap* pmap) const { 819 if (fPixels) { 820 if (pmap) { 821 pmap->reset(fInfo, fPixels, fRowBytes); 822 } 823 return true; 824 } 825 return false; 826} 827 828/////////////////////////////////////////////////////////////////////////////// 829 830#ifdef SK_DEBUG 831void SkImageInfo::validate() const { 832 SkASSERT(fWidth >= 0); 833 SkASSERT(fHeight >= 0); 834 SkASSERT(SkColorTypeIsValid(fColorType)); 835 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); 836} 837#endif 838