Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2911)

Unified Diff: blimp/common/compositor/blimp_image_serialization_processor.cc

Issue 1680333004: Add support for encoding/decoding WebP images. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@serialize-deserialize-images-framework
Patch Set: Always assume alpha-channel in decoder Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: blimp/common/compositor/blimp_image_serialization_processor.cc
diff --git a/blimp/common/compositor/blimp_image_serialization_processor.cc b/blimp/common/compositor/blimp_image_serialization_processor.cc
index 36ea6af38275856c8d91fe02215e0c2b4c2b9db0..2b3fde63dff06615fab9846f51d988c8e2f9e137 100644
--- a/blimp/common/compositor/blimp_image_serialization_processor.cc
+++ b/blimp/common/compositor/blimp_image_serialization_processor.cc
@@ -8,14 +8,125 @@
#include <vector>
#include "base/logging.h"
+#include "blimp/common/compositor/webp_decoder.h"
+#include "third_party/libwebp/webp/encode.h"
+#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPixelSerializer.h"
+#include "third_party/skia/include/core/SkUnPreMultiply.h"
namespace {
-bool NoopDecoder(const void* input, size_t input_size, SkBitmap* bitmap) {
- // TODO(nyquist): Add an image decoder.
- return false;
-}
+// TODO(nyquist): Make sure encoder does not serialize images more than once.
+// See crbug.com/548434.
+class WebPImageEncoder : public SkPixelSerializer {
+ public:
+ WebPImageEncoder() {}
+ ~WebPImageEncoder() override{};
+
+ bool onUseEncodedData(const void* data, size_t len) override {
+ const unsigned char* cast_data = static_cast<const unsigned char*>(data);
+ if (len < 14)
+ return false;
+ return !memcmp(cast_data, "RIFF", 4) && !memcmp(cast_data + 8, "WEBPVP", 6);
+ }
+
+ SkData* onEncode(const SkPixmap& pixmap) override {
+ // Initialize an empty WebPConfig.
+ WebPConfig config;
+ if (!WebPConfigInit(&config))
+ return nullptr;
+
+ // Initialize an empty WebPPicture.
+ WebPPicture picture;
+ if (!WebPPictureInit(&picture))
+ return nullptr;
+
+ // Ensure width and height are valid dimensions.
+ if (!pixmap.width() || pixmap.width() > WEBP_MAX_DIMENSION)
+ return nullptr;
+ picture.width = pixmap.width();
+ if (!pixmap.height() || pixmap.height() > WEBP_MAX_DIMENSION)
+ return nullptr;
+ picture.height = pixmap.height();
+
+ // Import picture from raw pixels.
+ DCHECK(pixmap.alphaType() == kPremul_SkAlphaType);
+ auto pixel_chars = static_cast<const unsigned char*>(pixmap.addr());
+ if (!PlatformPictureImport(pixel_chars, &picture))
+ return nullptr;
+
+ // Create a buffer for where to store the output data.
+ std::vector<unsigned char> data;
+ picture.custom_ptr = &data;
+
+ // Use our own WebPWriterFunction implementation.
+ picture.writer = &WebPImageEncoder::WriteOutput;
+
+ // Setup the configuration for the output WebP picture.
+ config.quality = 100.0; // between 0 (smallest file) and 100 (biggest).
urvang 2016/02/17 01:49:08 You should stick to the default quality (=75) & me
nyquist 2016/02/17 16:56:44 OK. Kept at the defaults, but hard-coded them for
+ config.method = 6; // quality/speed trade-off (0=fast, 6=slower-better).
+
+ // Encode the picture using the given configuration.
+ bool success = WebPEncode(&config, &picture);
+
+ // Release the memory allocated by WebPPictureImport*(). This does not free
+ // the memory used by the picture object itself.
+ WebPPictureFree(&picture);
+
+ if (!success)
+ return nullptr;
+
+ // Copy WebP data into SkData. |data| is allocated only on the stack, so
+ // it is automatically deleted after this.
+ return SkData::NewWithCopy(&data.front(), data.size());
+ }
+
+ private:
+ // WebPWriterFunction implementation.
+ static int WriteOutput(const uint8_t* data,
+ size_t size,
+ const WebPPicture* const picture) {
+ std::vector<unsigned char>* dest =
+ static_cast<std::vector<unsigned char>*>(picture->custom_ptr);
+ dest->insert(dest->end(), data, data + size);
+ return 1;
+ }
+
+ void UnPremultiply(const unsigned char* in_pixels,
+ unsigned char* out_pixels,
+ size_t pixel_count) {
+ const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
+ for (; pixel_count-- > 0; in_pixels += 4) {
+ unsigned char alpha = in_pixels[3];
+ if (alpha == 255) { // Full opacity, just blindly copy.
+ *out_pixels++ = in_pixels[0];
+ *out_pixels++ = in_pixels[1];
+ *out_pixels++ = in_pixels[2];
+ *out_pixels++ = alpha;
+ } else {
+ SkUnPreMultiply::Scale scale = table[alpha];
+ *out_pixels++ = SkUnPreMultiply::ApplyScale(scale, in_pixels[0]);
+ *out_pixels++ = SkUnPreMultiply::ApplyScale(scale, in_pixels[1]);
+ *out_pixels++ = SkUnPreMultiply::ApplyScale(scale, in_pixels[2]);
+ *out_pixels++ = alpha;
+ }
+ }
+ }
+
+ bool PlatformPictureImport(const unsigned char* pixels,
+ WebPPicture* picture) {
+ // Need to unpremultiply each pixel.
+ size_t pixel_count = picture->height * picture->width;
+ std::vector<unsigned char> unpremul_pixels(pixel_count * 4);
+ UnPremultiply(pixels, unpremul_pixels.data(), pixel_count);
+
+ int row_stride = static_cast<int>(picture->width * 4);
urvang 2016/02/17 01:49:08 Isn't picture->width already an int?
nyquist 2016/02/17 16:56:44 Doh. My bad. Done.
+
+ if (SK_B32_SHIFT) // Android
+ return WebPPictureImportRGBA(picture, unpremul_pixels.data(), row_stride);
+ return WebPPictureImportBGRA(picture, unpremul_pixels.data(), row_stride);
+ }
+};
} // namespace
@@ -24,12 +135,12 @@ namespace blimp {
BlimpImageSerializationProcessor::BlimpImageSerializationProcessor(Mode mode) {
switch (mode) {
case Mode::SERIALIZATION:
- pixel_serializer_ = nullptr;
+ pixel_serializer_.reset(new WebPImageEncoder);
pixel_deserializer_ = nullptr;
break;
case Mode::DESERIALIZATION:
pixel_serializer_ = nullptr;
- pixel_deserializer_ = &NoopDecoder;
+ pixel_deserializer_ = &WebPDecoder;
break;
default:
NOTREACHED() << "Unknown serialization mode";

Powered by Google App Engine
This is Rietveld 408576698