diff options
author | Matt Sarett <msarett@google.com> | 2017-04-05 16:52:00 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-04-05 21:33:14 +0000 |
commit | 0c9d0b4e03b6c10778329e995b5dfdcb97954b28 (patch) | |
tree | 43391c6ceaa97fe9574530642b943d6ee20418c0 | |
parent | 7125ac603613d156d83a528f27b03e04282a1e37 (diff) |
Add support for writing ICC profiles to webp encoder
Bug: skia:
Change-Id: If0a8f84ed88da96924370b841f2283c0ff8e32ab
Reviewed-on: https://skia-review.googlesource.com/10212
Commit-Queue: Matt Sarett <msarett@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
-rw-r--r-- | src/images/SkWEBPImageEncoder.cpp | 56 | ||||
-rw-r--r-- | tests/CodecTest.cpp | 4 | ||||
-rw-r--r-- | third_party/libwebp/BUILD.gn | 4 |
3 files changed, 53 insertions, 11 deletions
diff --git a/src/images/SkWEBPImageEncoder.cpp b/src/images/SkWEBPImageEncoder.cpp index 28dff0569c..728dbc712a 100644 --- a/src/images/SkWEBPImageEncoder.cpp +++ b/src/images/SkWEBPImageEncoder.cpp @@ -26,7 +26,7 @@ #include "SkUnPreMultiply.h" #include "SkUtils.h" -// A WebP decoder only, on top of (subset of) libwebp +// A WebP encoder only, on top of (subset of) libwebp // For more information on WebP image format, and libwebp library, see: // http://code.google.com/speed/webp/ // http://www.webmproject.org/code/#libwebp_webp_image_decoder_library @@ -37,6 +37,7 @@ extern "C" { // If moving libwebp out of skia source tree, path for webp headers must be // updated accordingly. Here, we enforce using local copy in webp sub-directory. #include "webp/encode.h" +#include "webp/mux.h" } static transform_scanline_proc choose_proc(const SkImageInfo& info) { @@ -174,10 +175,17 @@ static bool do_encode(SkWStream* stream, const SkPixmap& srcPixmap, const SkEnco WebPPicture pic; WebPPictureInit(&pic); + SkAutoTCallVProc<WebPPicture, WebPPictureFree> autoPic(&pic); pic.width = pixmap.width(); pic.height = pixmap.height(); pic.writer = stream_writer; - pic.custom_ptr = (void*)stream; + + // If there is no need to embed an ICC profile, we write directly to the input stream. + // Otherwise, we will first encode to |tmp| and use a mux to add the ICC chunk. libwebp + // forces us to have an encoded image before we can add a profile. + sk_sp<SkData> icc = pixmap.colorSpace() ? icc_from_color_space(*pixmap.colorSpace()) : nullptr; + SkDynamicMemoryWStream tmp; + pic.custom_ptr = icc ? (void*)&tmp : (void*)stream; const uint8_t* src = (uint8_t*)pixmap.addr(); const int rgbStride = pic.width * bpp; @@ -190,21 +198,47 @@ static bool do_encode(SkWStream* stream, const SkPixmap& srcPixmap, const SkEnco proc((char*) &rgb[y * rgbStride], (const char*) &src[y * rowBytes], pic.width, bpp, colors); } - bool ok; - if (bpp == 3) { - ok = SkToBool(WebPPictureImportRGB(&pic, &rgb[0], rgbStride)); - } else { + auto importProc = WebPPictureImportRGB; + if (3 != bpp) { if (pixmap.isOpaque()) { - ok = SkToBool(WebPPictureImportRGBX(&pic, &rgb[0], rgbStride)); + importProc = WebPPictureImportRGBX; } else { - ok = SkToBool(WebPPictureImportRGBA(&pic, &rgb[0], rgbStride)); + importProc = WebPPictureImportRGBA; } } - ok = ok && WebPEncode(&webp_config, &pic); - WebPPictureFree(&pic); + if (!importProc(&pic, &rgb[0], rgbStride)) { + return false; + } + + if (!WebPEncode(&webp_config, &pic)) { + return false; + } + + if (icc) { + sk_sp<SkData> encodedData = tmp.detachAsData(); + WebPData encoded = { encodedData->bytes(), encodedData->size() }; + WebPData iccChunk = { icc->bytes(), icc->size() }; + + SkAutoTCallVProc<WebPMux, WebPMuxDelete> mux(WebPMuxNew()); + if (WEBP_MUX_OK != WebPMuxSetImage(mux, &encoded, 0)) { + return false; + } + + if (WEBP_MUX_OK != WebPMuxSetChunk(mux, "ICCP", &iccChunk, 0)) { + return false; + } + + WebPData assembled; + if (WEBP_MUX_OK != WebPMuxAssemble(mux, &assembled)) { + return false; + } + + stream->write(assembled.bytes, assembled.size); + WebPDataClear(&assembled); + } - return ok; + return true; } bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& src, int quality) { diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp index f3a393d7ac..3897878879 100644 --- a/tests/CodecTest.cpp +++ b/tests/CodecTest.cpp @@ -1538,6 +1538,9 @@ static void encode_format(SkDynamicMemoryWStream* stream, const SkPixmap& pixmap case SkEncodedImageFormat::kJPEG: SkEncodeImageAsJPEG(stream, pixmap, opts); break; + case SkEncodedImageFormat::kWEBP: + SkEncodeImageAsWEBP(stream, pixmap, opts); + break; default: SkASSERT(false); break; @@ -1586,4 +1589,5 @@ static void test_encode_icc(skiatest::Reporter* r, SkEncodedImageFormat format) DEF_TEST(Codec_EncodeICC, r) { test_encode_icc(r, SkEncodedImageFormat::kPNG); test_encode_icc(r, SkEncodedImageFormat::kJPEG); + test_encode_icc(r, SkEncodedImageFormat::kWEBP); } diff --git a/third_party/libwebp/BUILD.gn b/third_party/libwebp/BUILD.gn index 3e9bd06020..7fec982e35 100644 --- a/third_party/libwebp/BUILD.gn +++ b/third_party/libwebp/BUILD.gn @@ -128,6 +128,10 @@ if (skia_use_system_libwebp) { "../externals/libwebp/src/enc/tree_enc.c", "../externals/libwebp/src/enc/vp8l_enc.c", "../externals/libwebp/src/enc/webp_enc.c", + "../externals/libwebp/src/mux/anim_encode.c", + "../externals/libwebp/src/mux/muxedit.c", + "../externals/libwebp/src/mux/muxinternal.c", + "../externals/libwebp/src/mux/muxread.c", "../externals/libwebp/src/utils/bit_reader_utils.c", "../externals/libwebp/src/utils/bit_writer_utils.c", "../externals/libwebp/src/utils/color_cache_utils.c", |