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

Side by Side 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: address minor last comments 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
« no previous file with comments | « blimp/common/DEPS ('k') | blimp/common/compositor/webp_decoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_image_serialization_processor.h" 5 #include "blimp/common/compositor/blimp_image_serialization_processor.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "blimp/common/compositor/webp_decoder.h"
12 #include "third_party/libwebp/webp/encode.h"
13 #include "third_party/skia/include/core/SkData.h"
11 #include "third_party/skia/include/core/SkPicture.h" 14 #include "third_party/skia/include/core/SkPicture.h"
12 #include "third_party/skia/include/core/SkPixelSerializer.h" 15 #include "third_party/skia/include/core/SkPixelSerializer.h"
16 #include "third_party/skia/include/core/SkUnPreMultiply.h"
13 17
14 namespace { 18 namespace {
15 bool NoopDecoder(const void* input, size_t input_size, SkBitmap* bitmap) { 19 // TODO(nyquist): Make sure encoder does not serialize images more than once.
16 // TODO(nyquist): Add an image decoder. 20 // See crbug.com/548434.
17 return false; 21 class WebPImageEncoder : public SkPixelSerializer {
18 } 22 public:
23 WebPImageEncoder() {}
24 ~WebPImageEncoder() override{};
25
26 bool onUseEncodedData(const void* data, size_t len) override {
27 const unsigned char* cast_data = static_cast<const unsigned char*>(data);
28 if (len < 14)
29 return false;
30 return !memcmp(cast_data, "RIFF", 4) && !memcmp(cast_data + 8, "WEBPVP", 6);
31 }
32
33 SkData* onEncode(const SkPixmap& pixmap) override {
34 // Initialize an empty WebPConfig.
35 WebPConfig config;
36 if (!WebPConfigInit(&config))
37 return nullptr;
38
39 // Initialize an empty WebPPicture.
40 WebPPicture picture;
41 if (!WebPPictureInit(&picture))
42 return nullptr;
43
44 // Ensure width and height are valid dimensions.
45 if (!pixmap.width() || pixmap.width() > WEBP_MAX_DIMENSION)
46 return nullptr;
47 picture.width = pixmap.width();
48 if (!pixmap.height() || pixmap.height() > WEBP_MAX_DIMENSION)
49 return nullptr;
50 picture.height = pixmap.height();
51
52 // Import picture from raw pixels.
53 DCHECK(pixmap.alphaType() == kPremul_SkAlphaType);
54 auto pixel_chars = static_cast<const unsigned char*>(pixmap.addr());
55 if (!PlatformPictureImport(pixel_chars, &picture))
56 return nullptr;
57
58 // Create a buffer for where to store the output data.
59 std::vector<unsigned char> data;
60 picture.custom_ptr = &data;
61
62 // Use our own WebPWriterFunction implementation.
63 picture.writer = &WebPImageEncoder::WriteOutput;
64
65 // Setup the configuration for the output WebP picture. This is currently
66 // the same as the default configuration for WebP, but since any change in
67 // the WebP defaults would invalidate all caches they are hard coded.
68 config.quality = 75.0; // between 0 (smallest file) and 100 (biggest).
69 config.method = 4; // quality/speed trade-off (0=fast, 6=slower-better).
70
71 // Encode the picture using the given configuration.
72 bool success = WebPEncode(&config, &picture);
73
74 // Release the memory allocated by WebPPictureImport*(). This does not free
75 // the memory used by the picture object itself.
76 WebPPictureFree(&picture);
77
78 if (!success)
79 return nullptr;
80
81 // Copy WebP data into SkData. |data| is allocated only on the stack, so
82 // it is automatically deleted after this.
83 return SkData::NewWithCopy(&data.front(), data.size());
84 }
85
86 private:
87 // WebPWriterFunction implementation.
88 static int WriteOutput(const uint8_t* data,
89 size_t size,
90 const WebPPicture* const picture) {
91 std::vector<unsigned char>* dest =
92 static_cast<std::vector<unsigned char>*>(picture->custom_ptr);
93 dest->insert(dest->end(), data, data + size);
94 return 1;
95 }
96
97 // For each pixel, un-premultiplies the alpha-channel for each of the RGB
98 // channels. As an example, for a channel value that before multiplication was
99 // 255, and after applying an alpha of 128, the premultiplied pixel would be
100 // 128. The un-premultiply step uses the alpha-channel to get back to 255. The
101 // alpha channel is kept unchanged.
102 void UnPremultiply(const unsigned char* in_pixels,
103 unsigned char* out_pixels,
104 size_t pixel_count) {
105 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
106 for (; pixel_count-- > 0; in_pixels += 4) {
107 unsigned char alpha = in_pixels[3];
108 if (alpha == 255) { // Full opacity, just blindly copy.
109 *out_pixels++ = in_pixels[0];
110 *out_pixels++ = in_pixels[1];
111 *out_pixels++ = in_pixels[2];
112 *out_pixels++ = alpha;
113 } else {
114 SkUnPreMultiply::Scale scale = table[alpha];
115 *out_pixels++ = SkUnPreMultiply::ApplyScale(scale, in_pixels[0]);
116 *out_pixels++ = SkUnPreMultiply::ApplyScale(scale, in_pixels[1]);
117 *out_pixels++ = SkUnPreMultiply::ApplyScale(scale, in_pixels[2]);
118 *out_pixels++ = alpha;
119 }
120 }
121 }
122
123 bool PlatformPictureImport(const unsigned char* pixels,
124 WebPPicture* picture) {
125 // Need to unpremultiply each pixel, each pixel using 4 bytes (RGBA).
126 size_t pixel_count = picture->height * picture->width;
127 std::vector<unsigned char> unpremul_pixels(pixel_count * 4);
128 UnPremultiply(pixels, unpremul_pixels.data(), pixel_count);
129
130 // Each pixel uses 4 bytes (RGBA) which affects the stride per row.
131 int row_stride = picture->width * 4;
132
133 if (SK_B32_SHIFT) // Android
134 return WebPPictureImportRGBA(picture, unpremul_pixels.data(), row_stride);
135 return WebPPictureImportBGRA(picture, unpremul_pixels.data(), row_stride);
136 }
137 };
19 138
20 } // namespace 139 } // namespace
21 140
22 namespace blimp { 141 namespace blimp {
23 142
24 BlimpImageSerializationProcessor::BlimpImageSerializationProcessor(Mode mode) { 143 BlimpImageSerializationProcessor::BlimpImageSerializationProcessor(Mode mode) {
25 switch (mode) { 144 switch (mode) {
26 case Mode::SERIALIZATION: 145 case Mode::SERIALIZATION:
27 pixel_serializer_ = nullptr; 146 pixel_serializer_.reset(new WebPImageEncoder);
28 pixel_deserializer_ = nullptr; 147 pixel_deserializer_ = nullptr;
29 break; 148 break;
30 case Mode::DESERIALIZATION: 149 case Mode::DESERIALIZATION:
31 pixel_serializer_ = nullptr; 150 pixel_serializer_ = nullptr;
32 pixel_deserializer_ = &NoopDecoder; 151 pixel_deserializer_ = &WebPDecoder;
33 break; 152 break;
34 default: 153 default:
35 NOTREACHED() << "Unknown serialization mode"; 154 NOTREACHED() << "Unknown serialization mode";
36 } 155 }
37 } 156 }
38 157
39 BlimpImageSerializationProcessor::~BlimpImageSerializationProcessor() {} 158 BlimpImageSerializationProcessor::~BlimpImageSerializationProcessor() {}
40 159
41 SkPixelSerializer* BlimpImageSerializationProcessor::GetPixelSerializer() { 160 SkPixelSerializer* BlimpImageSerializationProcessor::GetPixelSerializer() {
42 return pixel_serializer_.get(); 161 return pixel_serializer_.get();
43 } 162 }
44 163
45 SkPicture::InstallPixelRefProc 164 SkPicture::InstallPixelRefProc
46 BlimpImageSerializationProcessor::GetPixelDeserializer() { 165 BlimpImageSerializationProcessor::GetPixelDeserializer() {
47 return pixel_deserializer_; 166 return pixel_deserializer_;
48 } 167 }
49 168
50 } // namespace blimp 169 } // namespace blimp
OLDNEW
« 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