diff options
author | reed <reed@google.com> | 2016-08-11 03:55:15 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-08-11 03:55:15 -0700 |
commit | a9ca05ca5e604b9ee18e9cce19b059085ca0e22c (patch) | |
tree | b8b28257068935dc55c956c41ff2e3d899e031c7 /src/core/SkReadBuffer.cpp | |
parent | 286a8657da0364006e95cb0988477cc3a5f0e112 (diff) |
Deserialize pictures with custom image-deserializer
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2187613002
Review-Url: https://codereview.chromium.org/2187613002
Diffstat (limited to 'src/core/SkReadBuffer.cpp')
-rw-r--r-- | src/core/SkReadBuffer.cpp | 122 |
1 files changed, 51 insertions, 71 deletions
diff --git a/src/core/SkReadBuffer.cpp b/src/core/SkReadBuffer.cpp index 54f684acaa..5356d4a6b1 100644 --- a/src/core/SkReadBuffer.cpp +++ b/src/core/SkReadBuffer.cpp @@ -8,11 +8,32 @@ #include "SkBitmap.h" #include "SkErrorInternals.h" #include "SkImage.h" +#include "SkImageDeserializer.h" #include "SkImageGenerator.h" #include "SkReadBuffer.h" #include "SkStream.h" #include "SkTypeface.h" +namespace { + + // This generator intentionally should always fail on all attempts to get its pixels, + // simulating a bad or empty codec stream. + class EmptyImageGenerator final : public SkImageGenerator { + public: + EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { } + + private: + typedef SkImageGenerator INHERITED; + }; + + static sk_sp<SkImage> MakeEmptyImage(int width, int height) { + return SkImage::MakeFromGenerator( + new EmptyImageGenerator(SkImageInfo::MakeN32Premul(width, height))); + } + +} // anonymous namespace + + static uint32_t default_flags() { uint32_t flags = 0; flags |= SkReadBuffer::kScalarIsFloat_Flag; @@ -22,6 +43,9 @@ static uint32_t default_flags() { return flags; } +// This has an empty constructor and destructor, and is thread-safe, so we can use a singleton. +static SkImageDeserializer gDefaultImageDeserializer; + SkReadBuffer::SkReadBuffer() { fFlags = default_flags(); fVersion = 0; @@ -32,7 +56,7 @@ SkReadBuffer::SkReadBuffer() { fFactoryArray = nullptr; fFactoryCount = 0; - fBitmapDecoder = nullptr; + fImageDeserializer = &gDefaultImageDeserializer; #ifdef DEBUG_NON_DETERMINISTIC_ASSERT fDecodedBitmapIndex = -1; #endif // DEBUG_NON_DETERMINISTIC_ASSERT @@ -49,7 +73,7 @@ SkReadBuffer::SkReadBuffer(const void* data, size_t size) { fFactoryArray = nullptr; fFactoryCount = 0; - fBitmapDecoder = nullptr; + fImageDeserializer = &gDefaultImageDeserializer; #ifdef DEBUG_NON_DETERMINISTIC_ASSERT fDecodedBitmapIndex = -1; #endif // DEBUG_NON_DETERMINISTIC_ASSERT @@ -68,7 +92,7 @@ SkReadBuffer::SkReadBuffer(SkStream* stream) { fFactoryArray = nullptr; fFactoryCount = 0; - fBitmapDecoder = nullptr; + fImageDeserializer = &gDefaultImageDeserializer; #ifdef DEBUG_NON_DETERMINISTIC_ASSERT fDecodedBitmapIndex = -1; #endif // DEBUG_NON_DETERMINISTIC_ASSERT @@ -78,6 +102,10 @@ SkReadBuffer::~SkReadBuffer() { sk_free(fMemoryPtr); } +void SkReadBuffer::setImageDeserializer(SkImageDeserializer* deserializer) { + fImageDeserializer = deserializer ? deserializer : &gDefaultImageDeserializer; +} + bool SkReadBuffer::readBool() { return fReader.readBool(); } @@ -179,7 +207,7 @@ uint32_t SkReadBuffer::getArrayCount() { return *(uint32_t*)fReader.peek(); } -bool SkReadBuffer::readBitmap(SkBitmap* bitmap) { +sk_sp<SkImage> SkReadBuffer::readBitmapAsImage() { const int width = this->readInt(); const int height = this->readInt(); @@ -203,39 +231,12 @@ bool SkReadBuffer::readBitmap(SkBitmap* bitmap) { const void* data = this->skip(length); const int32_t xOffset = this->readInt(); const int32_t yOffset = this->readInt(); - if (fBitmapDecoder != nullptr && fBitmapDecoder(data, length, bitmap)) { - if (bitmap->width() == width && bitmap->height() == height) { -#ifdef DEBUG_NON_DETERMINISTIC_ASSERT - if (0 != xOffset || 0 != yOffset) { - SkDebugf("SkReadBuffer::readBitmap: heights match," - " but offset is not zero. \nInfo about the bitmap:" - "\n\tIndex: %d\n\tDimensions: [%d %d]\n\tEncoded" - " data size: %d\n\tOffset: (%d, %d)\n", - fDecodedBitmapIndex, width, height, length, xOffset, - yOffset); - } -#endif // DEBUG_NON_DETERMINISTIC_ASSERT - // If the width and height match, there should be no offset. - SkASSERT(0 == xOffset && 0 == yOffset); - return true; - } - - // This case can only be reached if extractSubset was called, so - // the recorded width and height must be smaller than or equal to - // the encoded width and height. - // FIXME (scroggo): This assert assumes that our decoder and the - // sources encoder agree on the width and height which may not - // always be the case. Removing until it can be investigated - // further. - //SkASSERT(width <= bitmap->width() && height <= bitmap->height()); - - SkBitmap subsetBm; - SkIRect subset = SkIRect::MakeXYWH(xOffset, yOffset, width, height); - if (bitmap->extractSubset(&subsetBm, subset)) { - bitmap->swap(subsetBm); - return true; - } + SkIRect subset = SkIRect::MakeXYWH(xOffset, yOffset, width, height); + sk_sp<SkImage> image = fImageDeserializer->makeFromMemory(data, length, &subset); + if (image) { + return image; } + // This bitmap was encoded when written, but we are unable to decode, possibly due to // not having a decoder. SkErrorInternals::SetError(kParseError_SkError, @@ -243,32 +244,20 @@ bool SkReadBuffer::readBitmap(SkBitmap* bitmap) { // Even though we weren't able to decode the pixels, the readbuffer should still be // intact, so we return true with an empty bitmap, so we don't force an abort of the // larger deserialize. - bitmap->setInfo(SkImageInfo::MakeUnknown(width, height)); - return true; - } else if (SkBitmap::ReadRawPixels(this, bitmap)) { - return true; + return MakeEmptyImage(width, height); + } else { + SkBitmap bitmap; + if (SkBitmap::ReadRawPixels(this, &bitmap)) { + bitmap.setImmutable(); + return SkImage::MakeFromBitmap(bitmap); + } } } // Could not read the SkBitmap. Use a placeholder bitmap. - bitmap->setInfo(SkImageInfo::MakeUnknown(width, height)); - return false; + return nullptr; } -namespace { - -// This generator intentionally should always fail on all attempts to get its pixels, -// simulating a bad or empty codec stream. -class EmptyImageGenerator final : public SkImageGenerator { -public: - EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { } - -private: - typedef SkImageGenerator INHERITED; -}; - -} // anonymous namespace - -SkImage* SkReadBuffer::readImage() { +sk_sp<SkImage> SkReadBuffer::readImage() { int width = this->read32(); int height = this->read32(); if (width <= 0 || height <= 0) { // SkImage never has a zero dimension @@ -276,25 +265,20 @@ SkImage* SkReadBuffer::readImage() { return nullptr; } - auto placeholder = [=] { - return SkImage::MakeFromGenerator( - new EmptyImageGenerator(SkImageInfo::MakeN32Premul(width, height))).release(); - }; - uint32_t encoded_size = this->getArrayCount(); if (encoded_size == 0) { // The image could not be encoded at serialization time - return an empty placeholder. (void)this->readUInt(); // Swallow that encoded_size == 0 sentinel. - return placeholder(); + return MakeEmptyImage(width, height); } if (encoded_size == 1) { // We had to encode the image as raw pixels via SkBitmap. (void)this->readUInt(); // Swallow that encoded_size == 1 sentinel. SkBitmap bm; if (SkBitmap::ReadRawPixels(this, &bm)) { - return SkImage::MakeFromBitmap(bm).release(); + return SkImage::MakeFromBitmap(bm); } - return placeholder(); + return MakeEmptyImage(width, height); } // The SkImage encoded itself. @@ -308,13 +292,9 @@ SkImage* SkReadBuffer::readImage() { } const SkIRect subset = SkIRect::MakeXYWH(originX, originY, width, height); - SkImage* image = SkImage::MakeFromEncoded(std::move(encoded), &subset).release(); - if (image) { - return image; - } - return SkImage::MakeFromGenerator( - new EmptyImageGenerator(SkImageInfo::MakeN32Premul(width, height))).release(); + sk_sp<SkImage> image = fImageDeserializer->makeFromData(encoded.get(), &subset); + return image ? image : MakeEmptyImage(width, height); } SkTypeface* SkReadBuffer::readTypeface() { |