Chromium Code Reviews| 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 |