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

Unified Diff: blimp/common/compositor/blimp_remote_image_serializer.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: 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_remote_image_serializer.cc
diff --git a/blimp/common/compositor/blimp_remote_image_serializer.cc b/blimp/common/compositor/blimp_remote_image_serializer.cc
index 562c70d2f75401953f4eb022c6c48e42f0b07b23..1db3a6ef1a745a8f849e91552ad7c3eb5c0ff3b4 100644
--- a/blimp/common/compositor/blimp_remote_image_serializer.cc
+++ b/blimp/common/compositor/blimp_remote_image_serializer.cc
@@ -4,18 +4,145 @@
#include "blimp/common/compositor/blimp_remote_image_serializer.h"
+#include <stddef.h>
+#include <vector>
+
+#include "third_party/libwebp/webp/encode.h"
+#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkPixelSerializer.h"
+namespace {
+// 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 < 10)
urvang 2016/02/10 23:54:42 Don't you need first 14 bytes? (8 + 6)
nyquist 2016/02/11 05:19:23 Done.
+ return false;
+ return !memcmp(cast_data, "RIFF", 4) && !memcmp(cast_data + 8, "WEBPVP", 6);
+ }
+
+ SkData* onEncode(const SkPixmap& pixmap) override {
+ auto pixel_chars = static_cast<const unsigned char*>(pixmap.addr());
+ WebPConfig config;
+ if (!WebPConfigInit(&config))
+ return nullptr;
+ WebPPicture picture;
+ if (!WebPPictureInit(&picture))
+ return nullptr;
+
+ 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();
+
+ const bool has_alpha = pixmap.alphaType() != kOpaque_SkAlphaType;
+ const bool premultiplied =
+ has_alpha && pixmap.alphaType() == kPremul_SkAlphaType;
+ if (premultiplied &&
+ !PlatformPremultipliedImportPicture(pixel_chars, &picture))
+ return nullptr;
+ if (!premultiplied && !ImportPictureRGBA<false>(pixel_chars, &picture))
+ return nullptr;
+
+ const int quality = 50;
+ std::vector<unsigned char> data;
+ picture.custom_ptr = &data;
+ picture.writer = &WebPImageEncoder::WriteOutput;
+ config.quality = quality;
+ config.method = 3;
+
+ bool success = WebPEncode(&config, &picture) != 0;
urvang 2016/02/10 23:54:42 "!= 0" isn't really needed
nyquist 2016/02/11 05:19:23 Done.
+ WebPPictureFree(&picture);
+ if (!success)
+ return nullptr;
+ return SkData::NewWithCopy(&data.front(), data.size());
+ }
+
+ private:
+ 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;
+ }
+
+ typedef int (*WebPImporter)(WebPPicture* const,
+ const uint8_t* const data,
+ int row_stride);
+
+ bool RgbPictureImport(const unsigned char* pixels,
urvang 2016/02/10 23:54:42 These parts were taken from an OLD version of http
nyquist 2016/02/11 05:19:23 So, I tried to change the code so that it assumed
+ bool premultiplied,
+ WebPImporter import_RGBA,
+ WebPImporter import_RGB,
+ WebPPicture* picture) {
+ if (premultiplied) {
+ return import_RGBA(picture, pixels,
+ static_cast<int>(picture->width * 4)) != 0;
+ }
+
+ // Write the RGB pixels to an rgb data buffer, alpha premultiplied,
+ // then import the rgb data.
+
+ size_t pixelCount = picture->height * picture->width;
+ std::vector<unsigned char> rgb(pixelCount * 3);
+
+ for (unsigned char* data = rgb.data(); pixelCount-- > 0; pixels += 4) {
+ unsigned char alpha = pixels[3];
+ if (alpha != 255) {
+ *data++ = SkMulDiv255Round(pixels[0], alpha);
+ *data++ = SkMulDiv255Round(pixels[1], alpha);
+ *data++ = SkMulDiv255Round(pixels[2], alpha);
+ } else {
+ *data++ = pixels[0];
+ *data++ = pixels[1];
+ *data++ = pixels[2];
+ }
+ }
+
+ return import_RGB(picture, rgb.data(), picture->width * 3) != 0;
+ }
+
+ template <bool Premultiplied>
+ bool ImportPictureBGRA(const unsigned char* pixels, WebPPicture* picture) {
+ return RgbPictureImport(pixels, Premultiplied, &WebPPictureImportBGRA,
+ &WebPPictureImportBGR, picture);
+ }
+
+ template <bool Premultiplied>
+ bool ImportPictureRGBA(const unsigned char* pixels, WebPPicture* picture) {
+ return RgbPictureImport(pixels, Premultiplied, &WebPPictureImportRGBA,
+ &WebPPictureImportRGB, picture);
+ }
+
+ bool PlatformPremultipliedImportPicture(const unsigned char* pixels,
+ WebPPicture* picture) {
+ if (SK_B32_SHIFT) // Android
+ return ImportPictureRGBA<true>(pixels, picture);
+
+ return ImportPictureBGRA<true>(pixels, picture);
+ }
+};
+
+} // namespace
+
namespace blimp {
-BlimpRemoteImageSerializer::BlimpRemoteImageSerializer() {}
+BlimpRemoteImageSerializer::BlimpRemoteImageSerializer()
+ : pixel_serializer_(make_scoped_ptr(new WebPImageEncoder)) {}
BlimpRemoteImageSerializer::~BlimpRemoteImageSerializer() {}
SkPixelSerializer* BlimpRemoteImageSerializer::GetPixelSerializer() {
- // TODO(nyquist): Add an image encoder. Make sure it does not serialize images
- // more than once. crbug.com/548434.
- return nullptr;
+ return pixel_serializer_.get();
}
} // namespace blimp

Powered by Google App Engine
This is Rietveld 408576698