Add a SkPixelSerializer SkImage encode variant
R=reed@google.com BUG=skia:4285 Review URL: https://codereview.chromium.org/1310633006
This commit is contained in:
parent
1a9cafff04
commit
2be7125f32
@ -21,6 +21,7 @@ class SkColorTable;
|
|||||||
class SkImageGenerator;
|
class SkImageGenerator;
|
||||||
class SkPaint;
|
class SkPaint;
|
||||||
class SkPicture;
|
class SkPicture;
|
||||||
|
class SkPixelSerializer;
|
||||||
class SkString;
|
class SkString;
|
||||||
class SkSurface;
|
class SkSurface;
|
||||||
class SkSurfaceProps;
|
class SkSurfaceProps;
|
||||||
@ -234,12 +235,27 @@ public:
|
|||||||
*
|
*
|
||||||
* If the image type cannot be encoded, or the requested encoder type is
|
* If the image type cannot be encoded, or the requested encoder type is
|
||||||
* not supported, this will return NULL.
|
* 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(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
|
* If the image already has its contents in encoded form (e.g. PNG or JPEG), return a ref
|
||||||
|
@ -218,28 +218,13 @@ void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
|
|||||||
SkBitmap::WriteRawPixels(this, 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) {
|
void SkWriteBuffer::writeImage(const SkImage* image) {
|
||||||
this->writeInt(image->width());
|
this->writeInt(image->width());
|
||||||
this->writeInt(image->height());
|
this->writeInt(image->height());
|
||||||
|
|
||||||
SkAutoTUnref<SkData> encoded(image->refEncoded());
|
SkAutoTUnref<SkData> encoded(image->encode(this->getPixelSerializer()));
|
||||||
if (encoded && try_write_encoded(this, encoded)) {
|
if (encoded) {
|
||||||
return;
|
write_encoded_bitmap(this, encoded, SkIPoint::Make(0, 0));
|
||||||
}
|
|
||||||
|
|
||||||
encoded.reset(image->encode(SkImageEncoder::kPNG_Type, 100));
|
|
||||||
if (encoded && try_write_encoded(this, encoded)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "SkImage_Base.h"
|
#include "SkImage_Base.h"
|
||||||
#include "SkNextID.h"
|
#include "SkNextID.h"
|
||||||
#include "SkPixelRef.h"
|
#include "SkPixelRef.h"
|
||||||
|
#include "SkPixelSerializer.h"
|
||||||
#include "SkReadPixelsRec.h"
|
#include "SkReadPixelsRec.h"
|
||||||
#include "SkString.h"
|
#include "SkString.h"
|
||||||
#include "SkSurface.h"
|
#include "SkSurface.h"
|
||||||
@ -71,6 +72,40 @@ SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
|
|||||||
return nullptr;
|
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 {
|
SkData* SkImage::refEncoded() const {
|
||||||
return as_IB(this)->onRefEncoded();
|
return as_IB(this)->onRefEncoded();
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "SkDevice.h"
|
#include "SkDevice.h"
|
||||||
#include "SkImageEncoder.h"
|
#include "SkImageEncoder.h"
|
||||||
#include "SkImage_Base.h"
|
#include "SkImage_Base.h"
|
||||||
|
#include "SkPixelSerializer.h"
|
||||||
#include "SkRRect.h"
|
#include "SkRRect.h"
|
||||||
#include "SkSurface.h"
|
#include "SkSurface.h"
|
||||||
#include "SkUtils.h"
|
#include "SkUtils.h"
|
||||||
@ -104,6 +105,36 @@ DEF_GPUTEST(Image_Encode_Gpu, reporter, factory) {
|
|||||||
}
|
}
|
||||||
#endif
|
#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) {
|
DEF_TEST(Image_NewRasterCopy, reporter) {
|
||||||
const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0);
|
const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0);
|
||||||
const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
|
const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user