aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2015-09-03 07:17:25 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-09-03 07:17:25 -0700
commit2be7125f3274a4b661f50e992fc0eb3c14c24f05 (patch)
treede15270f9114db847f7f8d317c050f5b83062b52
parent1a9cafff044e5a352c60065e44d64e9d0eb8f92a (diff)
Add a SkPixelSerializer SkImage encode variant
R=reed@google.com BUG=skia:4285 Review URL: https://codereview.chromium.org/1310633006
-rw-r--r--include/core/SkImage.h22
-rw-r--r--src/core/SkWriteBuffer.cpp21
-rw-r--r--src/image/SkImage.cpp35
-rw-r--r--tests/ImageTest.cpp31
4 files changed, 88 insertions, 21 deletions
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 2bcb90b5d3..b302792c58 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -21,6 +21,7 @@ class SkColorTable;
class SkImageGenerator;
class SkPaint;
class SkPicture;
+class SkPixelSerializer;
class SkString;
class SkSurface;
class SkSurfaceProps;
@@ -234,12 +235,27 @@ public:
*
* If the image type cannot be encoded, or the requested encoder type is
* not supported, this will return NULL.
+ *
+ * Note: this will attempt to encode the image's pixels in the specified format,
+ * even if the image returns a data from refEncoded(). That data will be ignored.
*/
SkData* encode(SkImageEncoder::Type, int quality) const;
- SkData* encode() const {
- return this->encode(SkImageEncoder::kPNG_Type, 100);
- }
+ /**
+ * Encode the image and return the result as a caller-managed SkData. This will
+ * attempt to reuse existing encoded data (as returned by refEncoded).
+ *
+ * We defer to the SkPixelSerializer both for vetting existing encoded data
+ * (useEncodedData) and for encoding the image (encodePixels) when no such data is
+ * present or is rejected by the serializer.
+ *
+ * If not specified, we use a default serializer which 1) always accepts existing data
+ * (in any format) and 2) encodes to PNG.
+ *
+ * If no compatible encoded data exists and encoding fails, this method will also
+ * fail (return NULL).
+ */
+ SkData* encode(SkPixelSerializer* = nullptr) const;
/**
* If the image already has its contents in encoded form (e.g. PNG or JPEG), return a ref
diff --git a/src/core/SkWriteBuffer.cpp b/src/core/SkWriteBuffer.cpp
index 7ddc77f93b..ac3d678dbc 100644
--- a/src/core/SkWriteBuffer.cpp
+++ b/src/core/SkWriteBuffer.cpp
@@ -218,31 +218,16 @@ void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
SkBitmap::WriteRawPixels(this, bitmap);
}
-static bool try_write_encoded(SkWriteBuffer* buffer, SkData* encoded) {
- SkPixelSerializer* ps = buffer->getPixelSerializer();
- // Assumes that if the client did not set a serializer, they are
- // happy to get the encoded data.
- if (!ps || ps->useEncodedData(encoded->data(), encoded->size())) {
- write_encoded_bitmap(buffer, encoded, SkIPoint::Make(0, 0));
- return true;
- }
- return false;
-}
-
void SkWriteBuffer::writeImage(const SkImage* image) {
this->writeInt(image->width());
this->writeInt(image->height());
- SkAutoTUnref<SkData> encoded(image->refEncoded());
- if (encoded && try_write_encoded(this, encoded)) {
+ SkAutoTUnref<SkData> encoded(image->encode(this->getPixelSerializer()));
+ if (encoded) {
+ write_encoded_bitmap(this, encoded, SkIPoint::Make(0, 0));
return;
}
- encoded.reset(image->encode(SkImageEncoder::kPNG_Type, 100));
- if (encoded && try_write_encoded(this, encoded)) {
- return;
- }
-
this->writeUInt(0); // signal no pixels (in place of the size of the encoded data)
}
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index c55d28a177..5a67c84caf 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -13,6 +13,7 @@
#include "SkImage_Base.h"
#include "SkNextID.h"
#include "SkPixelRef.h"
+#include "SkPixelSerializer.h"
#include "SkReadPixelsRec.h"
#include "SkString.h"
#include "SkSurface.h"
@@ -71,6 +72,40 @@ SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
return nullptr;
}
+namespace {
+
+class DefaultSerializer : public SkPixelSerializer {
+protected:
+ bool onUseEncodedData(const void *data, size_t len) override {
+ return true;
+ }
+
+ SkData* onEncodePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes) override {
+ return SkImageEncoder::EncodeData(info, pixels, rowBytes, SkImageEncoder::kPNG_Type, 100);
+ }
+};
+
+} // anonymous namespace
+
+SkData* SkImage::encode(SkPixelSerializer* serializer) const {
+ DefaultSerializer defaultSerializer;
+ SkPixelSerializer* effectiveSerializer = serializer ? serializer : &defaultSerializer;
+
+ SkAutoTUnref<SkData> encoded(this->refEncoded());
+ if (encoded && effectiveSerializer->useEncodedData(encoded->data(), encoded->size())) {
+ return encoded.detach();
+ }
+
+ SkBitmap bm;
+ SkAutoPixmapUnlock apu;
+ if (as_IB(this)->getROPixels(&bm) && bm.requestLock(&apu)) {
+ const SkPixmap& pmap = apu.pixmap();
+ return effectiveSerializer->encodePixels(pmap.info(), pmap.addr(), pmap.rowBytes());
+ }
+
+ return nullptr;
+}
+
SkData* SkImage::refEncoded() const {
return as_IB(this)->onRefEncoded();
}
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index bbf6682084..d271966979 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -10,6 +10,7 @@
#include "SkDevice.h"
#include "SkImageEncoder.h"
#include "SkImage_Base.h"
+#include "SkPixelSerializer.h"
#include "SkRRect.h"
#include "SkSurface.h"
#include "SkUtils.h"
@@ -104,6 +105,36 @@ DEF_GPUTEST(Image_Encode_Gpu, reporter, factory) {
}
#endif
+namespace {
+
+const char* kSerializedData = "serialized";
+
+class MockSerializer : public SkPixelSerializer {
+protected:
+ bool onUseEncodedData(const void*, size_t) override {
+ return false;
+ }
+
+ SkData* onEncodePixels(const SkImageInfo&, const void*, size_t) override {
+ return SkData::NewWithCString(kSerializedData);
+ }
+};
+
+} // anonymous namespace
+
+// Test that SkImage encoding observes custom pixel serializers.
+DEF_TEST(Image_Encode_Serializer, reporter) {
+ MockSerializer serializer;
+ const SkIRect ir = SkIRect::MakeXYWH(5, 5, 10, 10);
+ SkAutoTUnref<SkImage> image(make_image(nullptr, 20, 20, ir));
+ SkAutoTUnref<SkData> encoded(image->encode(&serializer));
+ SkAutoTUnref<SkData> reference(SkData::NewWithCString(kSerializedData));
+
+ REPORTER_ASSERT(reporter, encoded);
+ REPORTER_ASSERT(reporter, encoded->size() > 0);
+ REPORTER_ASSERT(reporter, encoded->equals(reference));
+}
+
DEF_TEST(Image_NewRasterCopy, reporter) {
const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0);
const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);