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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "blimp/common/compositor/blimp_remote_image_serializer.h" 5 #include "blimp/common/compositor/blimp_remote_image_serializer.h"
6 6
7 #include <stddef.h>
8 #include <vector>
9
10 #include "third_party/libwebp/webp/encode.h"
11 #include "third_party/skia/include/core/SkData.h"
7 #include "third_party/skia/include/core/SkPixelSerializer.h" 12 #include "third_party/skia/include/core/SkPixelSerializer.h"
8 13
14 namespace {
15 // TODO(nyquist): Make sure encoder does not serialize images more than once.
16 // See crbug.com/548434.
17 class WebPImageEncoder : public SkPixelSerializer {
18 public:
19 WebPImageEncoder() {}
20 ~WebPImageEncoder() override{};
21
22 bool onUseEncodedData(const void* data, size_t len) override {
23 const unsigned char* cast_data = static_cast<const unsigned char*>(data);
24 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.
25 return false;
26 return !memcmp(cast_data, "RIFF", 4) && !memcmp(cast_data + 8, "WEBPVP", 6);
27 }
28
29 SkData* onEncode(const SkPixmap& pixmap) override {
30 auto pixel_chars = static_cast<const unsigned char*>(pixmap.addr());
31 WebPConfig config;
32 if (!WebPConfigInit(&config))
33 return nullptr;
34 WebPPicture picture;
35 if (!WebPPictureInit(&picture))
36 return nullptr;
37
38 if (!pixmap.width() || pixmap.width() > WEBP_MAX_DIMENSION)
39 return nullptr;
40 picture.width = pixmap.width();
41 if (!pixmap.height() || pixmap.height() > WEBP_MAX_DIMENSION)
42 return nullptr;
43 picture.height = pixmap.height();
44
45 const bool has_alpha = pixmap.alphaType() != kOpaque_SkAlphaType;
46 const bool premultiplied =
47 has_alpha && pixmap.alphaType() == kPremul_SkAlphaType;
48 if (premultiplied &&
49 !PlatformPremultipliedImportPicture(pixel_chars, &picture))
50 return nullptr;
51 if (!premultiplied && !ImportPictureRGBA<false>(pixel_chars, &picture))
52 return nullptr;
53
54 const int quality = 50;
55 std::vector<unsigned char> data;
56 picture.custom_ptr = &data;
57 picture.writer = &WebPImageEncoder::WriteOutput;
58 config.quality = quality;
59 config.method = 3;
60
61 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.
62 WebPPictureFree(&picture);
63 if (!success)
64 return nullptr;
65 return SkData::NewWithCopy(&data.front(), data.size());
66 }
67
68 private:
69 static int WriteOutput(const uint8_t* data,
70 size_t size,
71 const WebPPicture* const picture) {
72 std::vector<unsigned char>* dest =
73 static_cast<std::vector<unsigned char>*>(picture->custom_ptr);
74 dest->insert(dest->end(), data, data + size);
75 return 1;
76 }
77
78 typedef int (*WebPImporter)(WebPPicture* const,
79 const uint8_t* const data,
80 int row_stride);
81
82 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
83 bool premultiplied,
84 WebPImporter import_RGBA,
85 WebPImporter import_RGB,
86 WebPPicture* picture) {
87 if (premultiplied) {
88 return import_RGBA(picture, pixels,
89 static_cast<int>(picture->width * 4)) != 0;
90 }
91
92 // Write the RGB pixels to an rgb data buffer, alpha premultiplied,
93 // then import the rgb data.
94
95 size_t pixelCount = picture->height * picture->width;
96 std::vector<unsigned char> rgb(pixelCount * 3);
97
98 for (unsigned char* data = rgb.data(); pixelCount-- > 0; pixels += 4) {
99 unsigned char alpha = pixels[3];
100 if (alpha != 255) {
101 *data++ = SkMulDiv255Round(pixels[0], alpha);
102 *data++ = SkMulDiv255Round(pixels[1], alpha);
103 *data++ = SkMulDiv255Round(pixels[2], alpha);
104 } else {
105 *data++ = pixels[0];
106 *data++ = pixels[1];
107 *data++ = pixels[2];
108 }
109 }
110
111 return import_RGB(picture, rgb.data(), picture->width * 3) != 0;
112 }
113
114 template <bool Premultiplied>
115 bool ImportPictureBGRA(const unsigned char* pixels, WebPPicture* picture) {
116 return RgbPictureImport(pixels, Premultiplied, &WebPPictureImportBGRA,
117 &WebPPictureImportBGR, picture);
118 }
119
120 template <bool Premultiplied>
121 bool ImportPictureRGBA(const unsigned char* pixels, WebPPicture* picture) {
122 return RgbPictureImport(pixels, Premultiplied, &WebPPictureImportRGBA,
123 &WebPPictureImportRGB, picture);
124 }
125
126 bool PlatformPremultipliedImportPicture(const unsigned char* pixels,
127 WebPPicture* picture) {
128 if (SK_B32_SHIFT) // Android
129 return ImportPictureRGBA<true>(pixels, picture);
130
131 return ImportPictureBGRA<true>(pixels, picture);
132 }
133 };
134
135 } // namespace
136
9 namespace blimp { 137 namespace blimp {
10 138
11 BlimpRemoteImageSerializer::BlimpRemoteImageSerializer() {} 139 BlimpRemoteImageSerializer::BlimpRemoteImageSerializer()
140 : pixel_serializer_(make_scoped_ptr(new WebPImageEncoder)) {}
12 141
13 BlimpRemoteImageSerializer::~BlimpRemoteImageSerializer() {} 142 BlimpRemoteImageSerializer::~BlimpRemoteImageSerializer() {}
14 143
15 SkPixelSerializer* BlimpRemoteImageSerializer::GetPixelSerializer() { 144 SkPixelSerializer* BlimpRemoteImageSerializer::GetPixelSerializer() {
16 // TODO(nyquist): Add an image encoder. Make sure it does not serialize images 145 return pixel_serializer_.get();
17 // more than once. crbug.com/548434.
18 return nullptr;
19 } 146 }
20 147
21 } // namespace blimp 148 } // namespace blimp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698