OLD | NEW |
---|---|
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 |
OLD | NEW |