Add image->bitmap

BUG=skia:

patch from issue 1212163012 at patchset 1 (http://crrev.com/1212163012#ps1)

Review URL: https://codereview.chromium.org/1208993017
This commit is contained in:
reed 2015-07-08 12:46:22 -07:00 committed by Commit bot
parent 37fffc6e8f
commit 3c06511e91
5 changed files with 87 additions and 0 deletions

View File

@ -264,6 +264,24 @@ public:
SkImage* newImage(int newWidth, int newHeight, const SkIRect* subset = NULL,
SkFilterQuality = kNone_SkFilterQuality) const;
// Helper functions to convert to SkBitmap
enum LegacyBitmapMode {
kRO_LegacyBitmapMode,
kRW_LegacyBitmapMode,
};
/**
* Attempt to create a bitmap with the same pixels as the image. The result will always be
* a raster-backed bitmap (texture-backed bitmaps are DEPRECATED, and not supported here).
*
* If the mode is kRO (read-only), the resulting bitmap will be marked as immutable.
*
* On succcess, returns true. On failure, returns false and the bitmap parameter will be reset
* to empty.
*/
bool asLegacyBitmap(SkBitmap*, LegacyBitmapMode) const;
protected:
SkImage(int width, int height) :
fWidth(width),

View File

@ -257,6 +257,29 @@ SkImage* SkImage::NewFromBitmap(const SkBitmap& bm) {
return SkNewImageFromRasterBitmap(bm, false, NULL);
}
bool SkImage::asLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) const {
return as_IB(this)->onAsLegacyBitmap(bitmap, mode);
}
bool SkImage_Base::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) const {
// As the base-class, all we can do is make a copy (regardless of mode).
// Subclasses that want to be more optimal should override.
SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
if (!bitmap->tryAllocPixels(info)) {
return false;
}
if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
bitmap->reset();
return false;
}
if (kRO_LegacyBitmapMode == mode) {
bitmap->setImmutable();
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////
#if !SK_SUPPORT_GPU

View File

@ -61,6 +61,8 @@ public:
SkFilterQuality) const;
virtual SkData* onRefEncoded() const { return NULL; }
virtual bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const;
private:
const SkSurfaceProps fProps;

View File

@ -79,6 +79,7 @@ public:
const SkMatrix* localMatrix) const override;
bool isOpaque() const override;
bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const override;
SkImage_Raster(const SkBitmap& bm, const SkSurfaceProps* props)
: INHERITED(bm.width(), bm.height(), props)
@ -262,3 +263,17 @@ bool SkImage_Raster::isOpaque() const {
return fBitmap.isOpaque();
}
bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) const {
if (kRO_LegacyBitmapMode == mode) {
// When we're a snapshot from a surface, our bitmap may not be marked immutable
// even though logically always we are, but in that case we can't physically share our
// pixelref since the caller might call setImmutable() themselves
// (thus changing our state).
if (fBitmap.isImmutable()) {
bitmap->setInfo(fBitmap.info());
bitmap->setPixelRef(fBitmap.pixelRef(), fBitmap.pixelRefOrigin());
return true;
}
}
return this->INHERITED::onAsLegacyBitmap(bitmap, mode);
}

View File

@ -407,6 +407,33 @@ static void test_image_readpixels(skiatest::Reporter* reporter, SkImage* image,
REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected));
}
static void test_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image) {
const SkImage::LegacyBitmapMode modes[] = {
SkImage::kRO_LegacyBitmapMode,
SkImage::kRW_LegacyBitmapMode,
};
for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
SkBitmap bitmap;
REPORTER_ASSERT(reporter, image->asLegacyBitmap(&bitmap, modes[i]));
REPORTER_ASSERT(reporter, image->width() == bitmap.width());
REPORTER_ASSERT(reporter, image->height() == bitmap.height());
REPORTER_ASSERT(reporter, image->isOpaque() == bitmap.isOpaque());
bitmap.lockPixels();
REPORTER_ASSERT(reporter, bitmap.getPixels());
const SkImageInfo info = SkImageInfo::MakeN32(1, 1, bitmap.alphaType());
SkPMColor imageColor;
REPORTER_ASSERT(reporter, image->readPixels(info, &imageColor, sizeof(SkPMColor), 0, 0));
REPORTER_ASSERT(reporter, imageColor == *bitmap.getAddr32(0, 0));
if (SkImage::kRO_LegacyBitmapMode == modes[i]) {
REPORTER_ASSERT(reporter, bitmap.isImmutable());
}
}
}
static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* factory) {
static const struct {
ImageType fType;
@ -450,6 +477,8 @@ static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto
REPORTER_ASSERT(reporter, NULL == releaseCtx.fData); // we ignored the context
}
test_legacy_bitmap(reporter, image);
const void* addr = image->peekPixels(&info, &rowBytes);
bool success = SkToBool(addr);
REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success);