diff options
author | Mike Reed <reed@google.com> | 2018-05-29 15:41:27 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-29 20:42:17 +0000 |
commit | f2c736400f03f8fe7fe356962c979f23df4d5f6b (patch) | |
tree | 809d21837d0701569cccd0e21f23e2ac5574007a | |
parent | 4f078f7cfac6580dce6e213c022708922739ac6d (diff) |
support image-subsets in serialization
A follow-on API change *could* be to extend the SerialProcs to pass subset information
up to the client, in case they want to handle the subsetting step themselves.
Bug: skia:7983
Change-Id: I36d3f1ce439886384495485c3be3c591d611a135
Reviewed-on: https://skia-review.googlesource.com/130543
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Reed <reed@google.com>
-rw-r--r-- | gm/image.cpp | 33 | ||||
-rw-r--r-- | include/core/SkPicture.h | 3 | ||||
-rw-r--r-- | src/core/SkImagePriv.h | 6 | ||||
-rw-r--r-- | src/core/SkReadBuffer.cpp | 23 | ||||
-rw-r--r-- | src/core/SkReadBuffer.h | 1 | ||||
-rw-r--r-- | src/core/SkWriteBuffer.cpp | 10 | ||||
-rw-r--r-- | src/image/SkImage.cpp | 5 | ||||
-rw-r--r-- | src/image/SkImage_Base.h | 4 | ||||
-rw-r--r-- | src/image/SkImage_Lazy.cpp | 4 |
9 files changed, 84 insertions, 5 deletions
diff --git a/gm/image.cpp b/gm/image.cpp index fc91d6b7f1..2c1b8d8458 100644 --- a/gm/image.cpp +++ b/gm/image.cpp @@ -399,3 +399,36 @@ DEF_SIMPLE_GM(scalepixels_unpremul, canvas, 1080, 280) { canvas->translate(pm2.width() + 10.0f, 0); } } + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +static sk_sp<SkImage> make_lazy_image(SkSurface* surf) { + surf->getCanvas()->drawCircle(100, 100, 100, SkPaint()); + auto data = surf->makeImageSnapshot()->encodeToData(); + return SkImage::MakeFromEncoded(data); +} + +#include "SkWriteBuffer.h" +#include "SkReadBuffer.h" +static sk_sp<SkImage> serial_deserial(SkImage* img) { + SkBinaryWriteBuffer writer; + writer.writeImage(img); + size_t length = writer.bytesWritten(); + auto data = SkData::MakeUninitialized(length); + writer.writeToMemory(data->writable_data()); + + SkReadBuffer reader(data->data(), length); + return reader.readImage(); +} + +DEF_SIMPLE_GM(image_subset, canvas, 440, 220) { + SkImageInfo info = SkImageInfo::MakeN32Premul(200, 200, nullptr); + auto surf = sk_tool_utils::makeSurface(canvas, info, nullptr); + auto img = make_lazy_image(surf.get()); + + canvas->drawImage(img, 10, 10, nullptr); + auto sub = img->makeSubset({100, 100, 200, 200}); + canvas->drawImage(sub, 220, 10); + sub = serial_deserial(sub.get()); + canvas->drawImage(sub, 220+110, 10); +} diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index f0e9e0e731..3693a45d8a 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -169,10 +169,11 @@ private: // V60: Remove flags in picture header // V61: Change SkDrawPictureRec to take two colors rather than two alphas // V62: Don't negate size of custom encoded images (don't write origin x,y either) + // V63: Store image bounds (including origin) instead of just width/height to support subsets // Only SKPs within the min/current picture version range (inclusive) can be read. static const uint32_t MIN_PICTURE_VERSION = 56; // august 2017 - static const uint32_t CURRENT_PICTURE_VERSION = 62; + static const uint32_t CURRENT_PICTURE_VERSION = 63; static_assert(MIN_PICTURE_VERSION <= 62, "Remove kFontAxes_bad from SkFontDescriptor.cpp"); diff --git a/src/core/SkImagePriv.h b/src/core/SkImagePriv.h index 7848bf4035..9172dd4c2c 100644 --- a/src/core/SkImagePriv.h +++ b/src/core/SkImagePriv.h @@ -77,6 +77,12 @@ bool SkImage_pinAsTexture(const SkImage*, GrContext*); void SkImage_unpinAsTexture(const SkImage*, GrContext*); /** + * Returns the bounds of the image relative to its encoded buffer. For all non-lazy images, + * this returns (0,0,width,height). For a lazy-image, it may return a subset of that rect. + */ +SkIRect SkImage_getSubset(const SkImage*); + +/** * Returns a new image containing the same pixel values as the source, but with a different color * space assigned. This performs no color space conversion. Primarily used in tests, to visualize * the results of rendering in wide or narrow gamuts. diff --git a/src/core/SkReadBuffer.cpp b/src/core/SkReadBuffer.cpp index 0c2edf622d..3491428658 100644 --- a/src/core/SkReadBuffer.cpp +++ b/src/core/SkReadBuffer.cpp @@ -282,14 +282,28 @@ uint32_t SkReadBuffer::getArrayCount() { return fError ? 0 : *(uint32_t*)fReader.peek(); } +/* Format: + * (subset) width, height + * (subset) origin x, y + * size (31bits) + * data [ encoded, with raw width/height ] + */ sk_sp<SkImage> SkReadBuffer::readImage() { if (fInflator) { SkImage* img = fInflator->getImage(this->read32()); return img ? sk_ref_sp(img) : nullptr; } - int width = this->read32(); - int height = this->read32(); + SkIRect bounds; + if (this->isVersionLT(kStoreImageBounds_Version)) { + bounds.fLeft = bounds.fTop = 0; + bounds.fRight = this->read32(); + bounds.fBottom = this->read32(); + } else { + this->readIRect(&bounds); + } + const int width = bounds.width(); + const int height = bounds.height(); if (width <= 0 || height <= 0) { // SkImage never has a zero dimension this->validate(false); return nullptr; @@ -338,6 +352,11 @@ sk_sp<SkImage> SkReadBuffer::readImage() { if (!image) { image = SkImage::MakeFromEncoded(std::move(data)); } + if (image) { + if (bounds.x() || bounds.y() || width < image->width() || height < image->height()) { + image = image->makeSubset(bounds); + } + } // Question: are we correct to return an "empty" image instead of nullptr, if the decoder // failed for some reason? return image ? image : MakeEmptyImage(width, height); diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h index 48a7aedf89..5f459cecef 100644 --- a/src/core/SkReadBuffer.h +++ b/src/core/SkReadBuffer.h @@ -78,6 +78,7 @@ public: kRemoveHeaderFlags_Version = 60, kTwoColorDrawShadow_Version = 61, kDontNegateImageSize_Version = 62, + kStoreImageBounds_Version = 63, }; /** diff --git a/src/core/SkWriteBuffer.cpp b/src/core/SkWriteBuffer.cpp index cb752c491f..b793dbf2dc 100644 --- a/src/core/SkWriteBuffer.cpp +++ b/src/core/SkWriteBuffer.cpp @@ -9,6 +9,7 @@ #include "SkBitmap.h" #include "SkData.h" #include "SkDeduper.h" +#include "SkImagePriv.h" #include "SkPaintPriv.h" #include "SkPixelRef.h" #include "SkPtrRecorder.h" @@ -133,14 +134,19 @@ bool SkBinaryWriteBuffer::writeToStream(SkWStream* stream) { return fWriter.writeToStream(stream); } +/* Format: + * (subset) bounds + * size (31bits) + * data [ encoded, with raw width/height ] + */ void SkBinaryWriteBuffer::writeImage(const SkImage* image) { if (fDeduper) { this->write32(fDeduper->findOrDefineImage(const_cast<SkImage*>(image))); return; } - this->writeInt(image->width()); - this->writeInt(image->height()); + const SkIRect bounds = SkImage_getSubset(image); + this->writeIRect(bounds); sk_sp<SkData> data; if (fProcs.fImageProc) { diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp index 72285bd698..cc4419a904 100644 --- a/src/image/SkImage.cpp +++ b/src/image/SkImage.cpp @@ -411,6 +411,11 @@ void SkImage_unpinAsTexture(const SkImage* image, GrContext* ctx) { as_IB(image)->onUnpinAsTexture(ctx); } +SkIRect SkImage_getSubset(const SkImage* image) { + SkASSERT(image); + return as_IB(image)->onGetSubset(); +} + /////////////////////////////////////////////////////////////////////////////////////////////////// sk_sp<SkImage> SkImageMakeRasterCopyAndAssignColorSpace(const SkImage* src, diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h index 2049fb3561..0d54a39471 100644 --- a/src/image/SkImage_Base.h +++ b/src/image/SkImage_Base.h @@ -38,6 +38,10 @@ public: virtual SkColorType onColorType() const = 0; virtual SkAlphaType onAlphaType() const = 0; + virtual SkIRect onGetSubset() const { + return { 0, 0, this->width(), this->height() }; + } + virtual bool onPeekPixels(SkPixmap*) const { return false; } virtual const SkBitmap* onPeekBitmap() const { return nullptr; } diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp index 82d573d708..7914f58d3c 100644 --- a/src/image/SkImage_Lazy.cpp +++ b/src/image/SkImage_Lazy.cpp @@ -77,6 +77,10 @@ public: return fInfo.alphaType(); } + SkIRect onGetSubset() const override { + return SkIRect::MakeXYWH(fOrigin.fX, fOrigin.fY, fInfo.width(), fInfo.height()); + } + bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY, CachingHint) const override; #if SK_SUPPORT_GPU |