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

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: merged origin/master 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
« no previous file with comments | « blimp/common/DEPS ('k') | blimp/common/compositor/webp_decoder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..ca436ed8cdd6300f344dd9e804bf7d34bd33e687 100644
--- a/blimp/common/compositor/blimp_image_serialization_processor.cc
+++ b/blimp/common/compositor/blimp_image_serialization_processor.cc
@@ -8,14 +8,133 @@
#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. This is currently
+ // the same as the default configuration for WebP, but since any change in
+ // the WebP defaults would invalidate all caches they are hard coded.
+ config.quality = 75.0; // between 0 (smallest file) and 100 (biggest).
+ config.method = 4; // 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;
+ }
+
+ // For each pixel, un-premultiplies the alpha-channel for each of the RGB
+ // channels. As an example, for a channel value that before multiplication was
+ // 255, and after applying an alpha of 128, the premultiplied pixel would be
+ // 128. The un-premultiply step uses the alpha-channel to get back to 255. The
+ // alpha channel is kept the unchanged.
urvang 2016/02/17 18:48:34 s/the unchanged/unchanged/
nyquist 2016/02/17 22:39:00 Done.
+ 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, each pixel using 4 bytes (RGBA).
+ size_t pixel_count = picture->height * picture->width;
+ std::vector<unsigned char> unpremul_pixels(pixel_count * 4);
+ UnPremultiply(pixels, unpremul_pixels.data(), pixel_count);
+
+ // Each pixel uses 4 bytes (RGBA) which affects the stride per row.
+ int row_stride = picture->width * 4;
+
+ if (SK_B32_SHIFT) // Android
+ return WebPPictureImportRGBA(picture, unpremul_pixels.data(), row_stride);
+ return WebPPictureImportBGRA(picture, unpremul_pixels.data(), row_stride);
+ }
+};
} // namespace
@@ -24,12 +143,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";
« no previous file with comments | « blimp/common/DEPS ('k') | blimp/common/compositor/webp_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698