bool SkImageGenerator::tryGenerateBitmap(SkBitmap* bitmap, const SkImageInfo* infoPtr) { const SkImageInfo info = infoPtr ? *infoPtr : this->getInfo(); const size_t rowBytes = info.minRowBytes(); const size_t pixelSize = info.getSafeSize(rowBytes); if (0 == pixelSize) { return false; } SkAutoFree pixelStorage(sk_malloc_flags(pixelSize, 0)); void* pixels = pixelStorage.get(); if (!pixels) { return false; } SkPMColor ctStorage[256]; int ctCount = 0; if (!this->getPixels(info, pixels, rowBytes, ctStorage, &ctCount)) { return false; } SkAutoTUnref<SkColorTable> ctable; if (ctCount > 0) { SkASSERT(kIndex_8_SkColorType == info.colorType()); ctable.reset(new SkColorTable(ctStorage, ctCount)); } else { SkASSERT(kIndex_8_SkColorType != info.colorType()); } return bitmap->installPixels(info, pixelStorage.detach(), rowBytes, ctable, release_malloc_proc, nullptr); }
size_t SkAutoPixmapStorage::AllocSize(const SkImageInfo& info, size_t* rowBytes) { size_t rb = info.minRowBytes(); if (rowBytes) { *rowBytes = rb; } return info.getSafeSize(rb); }
bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount) { if (kUnknown_SkColorType == info.colorType()) { return false; } if (NULL == pixels) { return false; } if (rowBytes < info.minRowBytes()) { return false; } if (kIndex_8_SkColorType == info.colorType()) { if (NULL == ctable || NULL == ctableCount) { return false; } } else { if (ctableCount) { *ctableCount = 0; } ctableCount = NULL; ctable = NULL; } bool success = this->onGetPixels(info, pixels, rowBytes, ctable, ctableCount); if (success && ctableCount) { SkASSERT(*ctableCount >= 0 && *ctableCount <= 256); } return success; }
virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { if (position.size().width() == fWidth && position.size().height() == fHeight) { return; // We don't care about the position, only the size. } fWidth = position.size().width(); fHeight = position.size().height(); fDeviceContext = pp::Graphics2D(this, pp::Size(fWidth, fHeight), false); if (!BindGraphics(fDeviceContext)) { SkDebugf("Couldn't bind the device context\n"); return; } fImage = pp::ImageData(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, pp::Size(fWidth, fHeight), false); const SkImageInfo info = SkImageInfo::MakeN32Premul(fWidth, fHeight); fBitmap.installPixels(info, fImage.data(), info.minRowBytes()); if (fCanvas) { delete fCanvas; } fCanvas = new SkCanvas(fBitmap); fCanvas->clear(SK_ColorWHITE); if (!fFlushLoopRunning) { Paint(); } }
sk_sp<SkImage> SkImageMakeRasterCopyAndAssignColorSpace(const SkImage* src, SkColorSpace* colorSpace) { // Read the pixels out of the source image, with no conversion SkImageInfo info = as_IB(src)->onImageInfo(); if (kUnknown_SkColorType == info.colorType()) { SkDEBUGFAIL("Unexpected color type"); return nullptr; } size_t rowBytes = info.minRowBytes(); size_t size = info.computeByteSize(rowBytes); if (SkImageInfo::ByteSizeOverflowed(size)) { return nullptr; } auto data = SkData::MakeUninitialized(size); if (!data) { return nullptr; } SkPixmap pm(info, data->writable_data(), rowBytes); if (!src->readPixels(pm, 0, 0, SkImage::kDisallow_CachingHint)) { return nullptr; } // Wrap them in a new image with a different color space return SkImage::MakeRasterData(info.makeColorSpace(sk_ref_sp(colorSpace)), data, rowBytes); }
TEST_F(DeferredImageDecoderTest, frameOpacity) { std::unique_ptr<ImageDecoder> actualDecoder = ImageDecoder::create(*m_data, ImageDecoder::AlphaPremultiplied, ImageDecoder::GammaAndColorProfileApplied); std::unique_ptr<DeferredImageDecoder> decoder = DeferredImageDecoder::createForTesting(std::move(actualDecoder)); decoder->setData(*m_data, true); SkImageInfo pixInfo = SkImageInfo::MakeN32Premul(1, 1); size_t rowBytes = pixInfo.minRowBytes(); size_t size = pixInfo.getSafeSize(rowBytes); SkAutoMalloc storage(size); SkPixmap pixmap(pixInfo, storage.get(), rowBytes); // Before decoding, the frame is not known to be opaque. RefPtr<SkImage> frame = decoder->createFrameAtIndex(0); ASSERT_TRUE(frame); EXPECT_FALSE(frame->isOpaque()); // Force a lazy decode by reading pixels. EXPECT_TRUE(frame->readPixels(pixmap, 0, 0)); // After decoding, the frame is known to be opaque. frame = decoder->createFrameAtIndex(0); ASSERT_TRUE(frame); EXPECT_TRUE(frame->isOpaque()); // Re-generating the opaque-marked frame should not fail. EXPECT_TRUE(frame->readPixels(pixmap, 0, 0)); }
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& options) override { REPORTER_ASSERT(fReporter, pixels != nullptr); REPORTER_ASSERT(fReporter, rowBytes >= info.minRowBytes()); if (fType != kSucceedGetPixels_TestType) { return false; } if (info.colorType() != kN32_SkColorType && info.colorType() != getInfo().colorType()) { return false; } char* bytePtr = static_cast<char*>(pixels); switch (info.colorType()) { case kN32_SkColorType: for (int y = 0; y < info.height(); ++y) { sk_memset32((uint32_t*)bytePtr, TestImageGenerator::PMColor(), info.width()); bytePtr += rowBytes; } break; case kRGB_565_SkColorType: for (int y = 0; y < info.height(); ++y) { sk_memset16((uint16_t*)bytePtr, SkPixel32ToPixel16(TestImageGenerator::PMColor()), info.width()); bytePtr += rowBytes; } break; default: return false; } return true; }
TEST_F(DeferredImageDecoderTest, frameOpacity) { std::unique_ptr<DeferredImageDecoder> decoder = DeferredImageDecoder::create( m_data, true, ImageDecoder::AlphaPremultiplied, ColorBehavior::transformToTargetForTesting()); SkImageInfo pixInfo = SkImageInfo::MakeN32Premul(1, 1); size_t rowBytes = pixInfo.minRowBytes(); size_t size = pixInfo.getSafeSize(rowBytes); Vector<char> storage(size); SkPixmap pixmap(pixInfo, storage.data(), rowBytes); // Before decoding, the frame is not known to be opaque. sk_sp<SkImage> frame = decoder->createFrameAtIndex(0); ASSERT_TRUE(frame); EXPECT_FALSE(frame->isOpaque()); // Force a lazy decode by reading pixels. EXPECT_TRUE(frame->readPixels(pixmap, 0, 0)); // After decoding, the frame is known to be opaque. frame = decoder->createFrameAtIndex(0); ASSERT_TRUE(frame); EXPECT_TRUE(frame->isOpaque()); // Re-generating the opaque-marked frame should not fail. EXPECT_TRUE(frame->readPixels(pixmap, 0, 0)); }
SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const AndroidOptions* options) { if (!pixels) { return SkCodec::kInvalidParameters; } if (rowBytes < info.minRowBytes()) { return SkCodec::kInvalidParameters; } AndroidOptions defaultOptions; if (!options) { options = &defaultOptions; } else if (options->fSubset) { if (!is_valid_subset(*options->fSubset, fInfo.dimensions())) { return SkCodec::kInvalidParameters; } if (SkIRect::MakeSize(fInfo.dimensions()) == *options->fSubset) { // The caller wants the whole thing, rather than a subset. Modify // the AndroidOptions passed to onGetAndroidPixels to not specify // a subset. defaultOptions = *options; defaultOptions.fSubset = nullptr; options = &defaultOptions; } } return this->onGetAndroidPixels(info, pixels, rowBytes, *options); }
bool SkPixmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB, int x, int y) const { if (kUnknown_SkColorType == requestedDstInfo.colorType()) { return false; } if (nullptr == dstPixels || dstRB < requestedDstInfo.minRowBytes()) { return false; } if (0 == requestedDstInfo.width() || 0 == requestedDstInfo.height()) { return false; } SkIRect srcR = SkIRect::MakeXYWH(x, y, requestedDstInfo.width(), requestedDstInfo.height()); if (!srcR.intersect(0, 0, this->width(), this->height())) { return false; } // the intersect may have shrunk info's logical size const SkImageInfo dstInfo = requestedDstInfo.makeWH(srcR.width(), srcR.height()); // if x or y are negative, then we have to adjust pixels if (x > 0) { x = 0; } if (y > 0) { y = 0; } // here x,y are either 0 or negative dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel()); const SkImageInfo srcInfo = this->info().makeWH(dstInfo.width(), dstInfo.height()); const void* srcPixels = this->addr(srcR.x(), srcR.y()); return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, this->rowBytes(), this->ctable()); }
static SkImage* create_rasterproc_image(RasterDataHolder* dataHolder) { SkASSERT(dataHolder); SkImageInfo info; SkAutoTUnref<SkData> data(create_image_data(&info)); dataHolder->fData.reset(SkRef(data.get())); return SkImage::NewFromRaster(info, data->data(), info.minRowBytes(), RasterDataHolder::Release, dataHolder); }
static void test_allocpixels(skiatest::Reporter* reporter) { const int width = 10; const int height = 10; const SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); const size_t explicitRowBytes = info.minRowBytes() + 24; SkBitmap bm; bm.setInfo(info); REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); bm.allocPixels(); REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); bm.reset(); bm.allocPixels(info); REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); bm.setInfo(info, explicitRowBytes); REPORTER_ASSERT(reporter, explicitRowBytes == bm.rowBytes()); bm.allocPixels(); REPORTER_ASSERT(reporter, explicitRowBytes == bm.rowBytes()); bm.reset(); bm.allocPixels(info, explicitRowBytes); REPORTER_ASSERT(reporter, explicitRowBytes == bm.rowBytes()); bm.reset(); bm.setInfo(info, 0); REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); bm.reset(); bm.allocPixels(info, 0); REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); bm.reset(); bool success = bm.setInfo(info, info.minRowBytes() - 1); // invalid for 32bit REPORTER_ASSERT(reporter, !success); REPORTER_ASSERT(reporter, bm.isNull()); }
static SkImage* create_codec_image() { SkImageInfo info; SkAutoTUnref<SkData> data(create_image_data(&info)); SkBitmap bitmap; bitmap.installPixels(info, data->writable_data(), info.minRowBytes()); SkAutoTUnref<SkData> src( SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100)); return SkImage::NewFromEncoded(src); }
SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& requestInfo, void* requestPixels, size_t requestRowBytes, const AndroidOptions* options) { if (!requestPixels) { return SkCodec::kInvalidParameters; } if (requestRowBytes < requestInfo.minRowBytes()) { return SkCodec::kInvalidParameters; } SkImageInfo adjustedInfo = fInfo; if (ExifOrientationBehavior::kRespect == fOrientationBehavior && SkPixmapPriv::ShouldSwapWidthHeight(fCodec->getOrigin())) { adjustedInfo = SkPixmapPriv::SwapWidthHeight(adjustedInfo); } AndroidOptions defaultOptions; if (!options) { options = &defaultOptions; } else if (options->fSubset) { if (!is_valid_subset(*options->fSubset, adjustedInfo.dimensions())) { return SkCodec::kInvalidParameters; } if (SkIRect::MakeSize(adjustedInfo.dimensions()) == *options->fSubset) { // The caller wants the whole thing, rather than a subset. Modify // the AndroidOptions passed to onGetAndroidPixels to not specify // a subset. defaultOptions = *options; defaultOptions.fSubset = nullptr; options = &defaultOptions; } } if (ExifOrientationBehavior::kIgnore == fOrientationBehavior) { return this->onGetAndroidPixels(requestInfo, requestPixels, requestRowBytes, *options); } SkCodec::Result result; auto decode = [this, options, &result](const SkPixmap& pm) { result = this->onGetAndroidPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), *options); return acceptable_result(result); }; SkPixmap dst(requestInfo, requestPixels, requestRowBytes); if (SkPixmapPriv::Orient(dst, fCodec->getOrigin(), decode)) { return result; } // Orient returned false. If onGetAndroidPixels succeeded, then Orient failed internally. if (acceptable_result(result)) { return SkCodec::kInternalError; } return result; }
// https://code.google.com/p/chromium/issues/detail?id=446164 static void test_bigalloc(skiatest::Reporter* reporter) { const int width = 0x40000001; const int height = 0x00000096; const SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); SkBitmap bm; REPORTER_ASSERT(reporter, !bm.tryAllocPixels(info)); sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, info.minRowBytes()); REPORTER_ASSERT(reporter, !pr); }
ImagePattern::ImagePattern(PassRefPtr<Image> image, RepeatMode repeatMode) : Pattern(repeatMode) , m_tileImage(image->imageForCurrentFrame()) { if (m_tileImage) { // TODO(fmalita): mechanism to extract the actual SkImageInfo from an SkImage? const SkImageInfo info = SkImageInfo::MakeN32Premul(m_tileImage->width(), m_tileImage->height()); adjustExternalMemoryAllocated(info.getSafeSize(info.minRowBytes())); } }
bool DecodingImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { if (NULL == pixels) { return false; } if (fInfo != info) { // The caller has specified a different info. This is an // error for this kind of SkImageGenerator. Use the Options // to change the settings. return false; } if (info.minRowBytes() > rowBytes) { // The caller has specified a bad rowBytes. return false; } SkAssertResult(fStream->rewind()); SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream)); if (NULL == decoder.get()) { return false; } decoder->setDitherImage(fDitherImage); decoder->setSampleSize(fSampleSize); decoder->setRequireUnpremultipliedColors( info.fAlphaType == kUnpremul_SkAlphaType); SkBitmap bitmap; TargetAllocator allocator(fInfo, pixels, rowBytes); decoder->setAllocator(&allocator); // TODO: need to be able to pass colortype directly to decoder SkBitmap::Config legacyConfig = SkColorTypeToBitmapConfig(info.colorType()); bool success = decoder->decode(fStream, &bitmap, legacyConfig, SkImageDecoder::kDecodePixels_Mode); decoder->setAllocator(NULL); if (!success) { return false; } if (allocator.isReady()) { // Did not use pixels! SkBitmap bm; SkASSERT(bitmap.canCopyTo(info.colorType())); bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator); if (!copySuccess || allocator.isReady()) { SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed."); // Earlier we checked canCopyto(); we expect consistency. return false; } SkASSERT(check_alpha(info.alphaType(), bm.alphaType())); } else { SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType())); } return true; }
DEF_TEST(ImageDataRef, reporter) { SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); size_t rowBytes = info.minRowBytes(); size_t size = info.getSafeSize(rowBytes); SkData* data = SkData::NewUninitialized(size); REPORTER_ASSERT(reporter, data->unique()); SkImage* image = SkImage::NewRasterData(info, data, rowBytes); REPORTER_ASSERT(reporter, !data->unique()); image->unref(); REPORTER_ASSERT(reporter, data->unique()); data->unref(); }
sk_sp<SkImage> SkImage::makeRasterImage() const { SkPixmap pm; if (this->peekPixels(&pm)) { return sk_ref_sp(const_cast<SkImage*>(this)); } const SkImageInfo info = as_IB(this)->onImageInfo(); const size_t rowBytes = info.minRowBytes(); size_t size = info.computeByteSize(rowBytes); if (SkImageInfo::ByteSizeOverflowed(size)) { return nullptr; } sk_sp<SkData> data = SkData::MakeUninitialized(size); pm = { info.makeColorSpace(nullptr), data->writable_data(), info.minRowBytes() }; if (!this->readPixels(pm, 0, 0)) { return nullptr; } return SkImage::MakeRasterData(info, std::move(data), rowBytes); }
bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) { #ifdef SK_DEBUG SkASSERT(info.width() > 0 && info.height() > 0); SkASSERT(dstP); SkASSERT(rowBytes >= info.minRowBytes()); SkASSERT(x >= 0 && y >= 0); const SkImageInfo& srcInfo = this->imageInfo(); SkASSERT(x + info.width() <= srcInfo.width()); SkASSERT(y + info.height() <= srcInfo.height()); #endif return this->onReadPixels(info, dstP, rowBytes, x, y); }
// TODO(ccameron): ImagePattern should not draw to a globally set color space. // https://crbug.com/672306 ImagePattern::ImagePattern(PassRefPtr<Image> image, RepeatMode repeatMode) : Pattern(repeatMode), m_tileImage(image->imageForCurrentFrame( ColorBehavior::transformToGlobalTarget())) { m_previousLocalMatrix.setIdentity(); if (m_tileImage) { // TODO(fmalita): mechanism to extract the actual SkImageInfo from an // SkImage? const SkImageInfo info = SkImageInfo::MakeN32Premul( m_tileImage->width() + (isRepeatX() ? 0 : 2), m_tileImage->height() + (isRepeatY() ? 0 : 2)); adjustExternalMemoryAllocated(info.getSafeSize(info.minRowBytes())); } }
bool SkBaseDevice::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y) { #ifdef SK_DEBUG SkASSERT(info.width() > 0 && info.height() > 0); SkASSERT(pixels); SkASSERT(rowBytes >= info.minRowBytes()); SkASSERT(x >= 0 && y >= 0); const SkImageInfo& dstInfo = this->imageInfo(); SkASSERT(x + info.width() <= dstInfo.width()); SkASSERT(y + info.height() <= dstInfo.height()); #endif return this->onWritePixels(info, pixels, rowBytes, x, y); }
void draw(SkCanvas* canvas) { std::vector<uint32_t> srcPixels; constexpr int width = 256; constexpr int height = 256; srcPixels.resize(width * height); SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(width, height); SkPixmap pixmap(imageInfo, &srcPixels.front(), imageInfo.minRowBytes()); pixmap.erase(SK_ColorTRANSPARENT); pixmap.erase(SK_ColorRED, { 24, 24, 192, 192 } ); pixmap.erase(SK_ColorTRANSPARENT, { 48, 48, 168, 168 } ); SkBitmap bitmap; bitmap.installPixels(pixmap); canvas->drawBitmap(bitmap, 0, 0); canvas->drawBitmap(bitmap, 48, 48); }
void draw(SkCanvas* canvas) { canvas->scale(16, 16); SkBitmap bitmap; SkImageInfo imageInfo = SkImageInfo::Make(2, 2, kRGB_565_SkColorType, kOpaque_SkAlphaType); bitmap.allocPixels(imageInfo); SkCanvas offscreen(bitmap); offscreen.clear(SK_ColorGREEN); canvas->drawBitmap(bitmap, 0, 0); auto pack565 = [](unsigned r, unsigned g, unsigned b) -> uint16_t { return (b << 0) | (g << 5) | (r << 11); }; uint16_t red565[] = { pack565(0x1F, 0x00, 0x00), pack565(0x17, 0x00, 0x00), pack565(0x0F, 0x00, 0x00), pack565(0x07, 0x00, 0x00) }; uint16_t blue565[] = { pack565(0x00, 0x00, 0x1F), pack565(0x00, 0x00, 0x17), pack565(0x00, 0x00, 0x0F), pack565(0x00, 0x00, 0x07) }; SkPixmap redPixmap(imageInfo, &red565, imageInfo.minRowBytes()); if (bitmap.writePixels(redPixmap, 0, 0)) { canvas->drawBitmap(bitmap, 2, 2); } SkPixmap bluePixmap(imageInfo, &blue565, imageInfo.minRowBytes()); if (bitmap.writePixels(bluePixmap, 0, 0)) { canvas->drawBitmap(bitmap, 4, 4); } }
SkSpecialSurface_Raster(const SkImageInfo& info, sk_sp<SkPixelRef> pr, const SkIRect& subset, const SkSurfaceProps* props) : INHERITED(subset, props) { SkASSERT(info.width() == pr->width() && info.height() == pr->height()); fBitmap.setInfo(info, info.minRowBytes()); fBitmap.setPixelRef(std::move(pr), 0, 0); fCanvas.reset(new SkCanvas(fBitmap, this->props())); fCanvas->clipRect(SkRect::Make(subset)); #ifdef SK_IS_BOT fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness #endif }
void draw(SkCanvas* canvas) { SkRandom random; SkBitmap bitmap; const int width = 8; const int height = 8; uint32_t pixels[width * height]; for (unsigned x = 0; x < width * height; ++x) { pixels[x] = random.nextU(); } SkImageInfo info = SkImageInfo::MakeN32(width, height, kUnpremul_SkAlphaType); if (bitmap.installPixels(info, pixels, info.minRowBytes())) { canvas->scale(32, 32); canvas->drawBitmap(bitmap, 0, 0); } }
static void test_peek(skiatest::Reporter* reporter, SkImage* image, bool expectPeekSuccess) { SkImageInfo info; size_t rowBytes; const void* addr = image->peekPixels(&info, &rowBytes); bool success = SkToBool(addr); REPORTER_ASSERT(reporter, expectPeekSuccess == success); if (success) { REPORTER_ASSERT(reporter, 20 == info.width()); REPORTER_ASSERT(reporter, 20 == info.height()); REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType()); REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() || kOpaque_SkAlphaType == info.alphaType()); REPORTER_ASSERT(reporter, info.minRowBytes() <= rowBytes); REPORTER_ASSERT(reporter, SkPreMultiplyColor(SK_ColorWHITE) == *(const SkPMColor*)addr); } }
sk_sp<SkImage> SkImage::makeNonTextureImage() const { if (!this->isTextureBacked()) { return sk_ref_sp(const_cast<SkImage*>(this)); } SkImageInfo info = as_IB(this)->onImageInfo(); size_t rowBytes = info.minRowBytes(); size_t size = info.getSafeSize(rowBytes); auto data = SkData::MakeUninitialized(size); if (!data) { return nullptr; } SkPixmap pm(info, data->writable_data(), rowBytes); if (!this->readPixels(pm, 0, 0, kDisallow_CachingHint)) { return nullptr; } return MakeRasterData(info, data, rowBytes); }
SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options* options, SkPMColor ctable[], int* ctableCount) { if (kUnknown_SkColorType == info.colorType()) { return kInvalidConversion; } if (NULL == pixels) { return kInvalidParameters; } if (rowBytes < info.minRowBytes()) { return kInvalidParameters; } if (kIndex_8_SkColorType == info.colorType()) { if (NULL == ctable || NULL == ctableCount) { return kInvalidParameters; } } else { if (ctableCount) { *ctableCount = 0; } ctableCount = NULL; ctable = NULL; } { SkAlphaType canonical; if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &canonical) || canonical != info.alphaType()) { return kInvalidConversion; } } // Default options. Options optsStorage; if (NULL == options) { options = &optsStorage; } const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ctable, ctableCount); if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { SkASSERT(*ctableCount >= 0 && *ctableCount <= 256); } return result; }
sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable, sk_sp<SkData> data) { SkASSERT(data != nullptr); if (!is_valid(info, ctable.get())) { return nullptr; } if ((rowBytes < info.minRowBytes()) || (data->size() < info.getSafeSize(rowBytes))) { return nullptr; } // must get this address before we call release void* pixels = const_cast<void*>(data->data()); SkPixelRef* pr = new SkMallocPixelRef(info, pixels, rowBytes, std::move(ctable), sk_data_releaseproc, data.release()); pr->setImmutable(); // since we were created with (immutable) data return sk_sp<SkPixelRef>(pr); }