Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / images / SkWebpEncoder.cpp
1 /*
2  * Copyright 2010 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "src/images/SkImageEncoderPriv.h"
9
10 #ifdef SK_ENCODE_WEBP
11
12 #include "include/core/SkBitmap.h"
13 #include "include/core/SkStream.h"
14 #include "include/core/SkUnPreMultiply.h"
15 #include "include/encode/SkWebpEncoder.h"
16 #include "include/private/SkColorData.h"
17 #include "include/private/SkImageInfoPriv.h"
18 #include "include/private/SkTemplates.h"
19 #include "src/images/SkImageEncoderFns.h"
20 #include "src/utils/SkUTF.h"
21
22 // A WebP encoder only, on top of (subset of) libwebp
23 // For more information on WebP image format, and libwebp library, see:
24 //   http://code.google.com/speed/webp/
25 //   http://www.webmproject.org/code/#libwebp_webp_image_decoder_library
26 //   http://review.webmproject.org/gitweb?p=libwebp.git
27
28 #include <stdio.h>
29 extern "C" {
30 // If moving libwebp out of skia source tree, path for webp headers must be
31 // updated accordingly. Here, we enforce using local copy in webp sub-directory.
32 #include "webp/encode.h"
33 #include "webp/mux.h"
34 }
35
36 static int stream_writer(const uint8_t* data, size_t data_size,
37                          const WebPPicture* const picture) {
38   SkWStream* const stream = (SkWStream*)picture->custom_ptr;
39   return stream->write(data, data_size) ? 1 : 0;
40 }
41
42 using WebPPictureImportProc = int (*) (WebPPicture* picture, const uint8_t* pixels, int stride);
43
44 bool SkWebpEncoder::Encode(SkWStream* stream, const SkPixmap& pixmap, const Options& opts) {
45     if (!SkPixmapIsValid(pixmap)) {
46         return false;
47     }
48
49     if (SkColorTypeIsAlphaOnly(pixmap.colorType())) {
50         // Maintain the existing behavior of not supporting encoding alpha-only images.
51         // TODO: Support encoding alpha only to an image with alpha but no color?
52         return false;
53     }
54
55     if (nullptr == pixmap.addr()) {
56         return false;
57     }
58
59     WebPConfig webp_config;
60     if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, opts.fQuality)) {
61         return false;
62     }
63
64     WebPPicture pic;
65     WebPPictureInit(&pic);
66     SkAutoTCallVProc<WebPPicture, WebPPictureFree> autoPic(&pic);
67     pic.width = pixmap.width();
68     pic.height = pixmap.height();
69     pic.writer = stream_writer;
70
71     // Set compression, method, and pixel format.
72     // libwebp recommends using BGRA for lossless and YUV for lossy.
73     // The choices of |webp_config.method| currently just match Chrome's defaults.  We
74     // could potentially expose this decision to the client.
75     if (Compression::kLossy == opts.fCompression) {
76         webp_config.lossless = 0;
77 #ifndef SK_WEBP_ENCODER_USE_DEFAULT_METHOD
78         webp_config.method = 3;
79 #endif
80         pic.use_argb = 0;
81     } else {
82         webp_config.lossless = 1;
83         webp_config.method = 0;
84         pic.use_argb = 1;
85     }
86
87     // If there is no need to embed an ICC profile, we write directly to the input stream.
88     // Otherwise, we will first encode to |tmp| and use a mux to add the ICC chunk.  libwebp
89     // forces us to have an encoded image before we can add a profile.
90     sk_sp<SkData> icc = icc_from_color_space(pixmap.info());
91     SkDynamicMemoryWStream tmp;
92     pic.custom_ptr = icc ? (void*)&tmp : (void*)stream;
93
94     {
95         const SkColorType ct = pixmap.colorType();
96         const bool premul = pixmap.alphaType() == kPremul_SkAlphaType;
97
98         SkBitmap tmpBm;
99         WebPPictureImportProc importProc = nullptr;
100         const SkPixmap* src = &pixmap;
101         if      (           ct ==  kRGB_888x_SkColorType) { importProc = WebPPictureImportRGBX; }
102         else if (!premul && ct == kRGBA_8888_SkColorType) { importProc = WebPPictureImportRGBA; }
103 #ifdef WebPPictureImportBGRA
104         else if (!premul && ct == kBGRA_8888_SkColorType) { importProc = WebPPictureImportBGRA; }
105 #endif
106         else {
107             importProc = WebPPictureImportRGBA;
108             auto info = pixmap.info().makeColorType(kRGBA_8888_SkColorType)
109                                      .makeAlphaType(kUnpremul_SkAlphaType);
110             if (!tmpBm.tryAllocPixels(info)
111                     || !pixmap.readPixels(tmpBm.info(), tmpBm.getPixels(), tmpBm.rowBytes())) {
112                 return false;
113             }
114             src = &tmpBm.pixmap();
115         }
116
117         if (!importProc(&pic, reinterpret_cast<const uint8_t*>(src->addr()), src->rowBytes())) {
118             return false;
119         }
120     }
121
122     if (!WebPEncode(&webp_config, &pic)) {
123         return false;
124     }
125
126     if (icc) {
127         sk_sp<SkData> encodedData = tmp.detachAsData();
128         WebPData encoded = { encodedData->bytes(), encodedData->size() };
129         WebPData iccChunk = { icc->bytes(), icc->size() };
130
131         SkAutoTCallVProc<WebPMux, WebPMuxDelete> mux(WebPMuxNew());
132         if (WEBP_MUX_OK != WebPMuxSetImage(mux, &encoded, 0)) {
133             return false;
134         }
135
136         if (WEBP_MUX_OK != WebPMuxSetChunk(mux, "ICCP", &iccChunk, 0)) {
137             return false;
138         }
139
140         WebPData assembled;
141         if (WEBP_MUX_OK != WebPMuxAssemble(mux, &assembled)) {
142             return false;
143         }
144
145         stream->write(assembled.bytes, assembled.size);
146         WebPDataClear(&assembled);
147     }
148
149     return true;
150 }
151
152 #endif