1a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org/*
2a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * Copyright 2010, The Android Open Source Project
3a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org *
4a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * Licensed under the Apache License, Version 2.0 (the "License");
5a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * you may not use this file except in compliance with the License.
6a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * You may obtain a copy of the License at
7a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org *
8a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org *     http://www.apache.org/licenses/LICENSE-2.0
9a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org *
10a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * Unless required by applicable law or agreed to in writing, software
11a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * distributed under the License is distributed on an "AS IS" BASIS,
12a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * See the License for the specific language governing permissions and
14a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org * limitations under the License.
15a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org */
16a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
17a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkImageDecoder.h"
18a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkImageEncoder.h"
19a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkColorPriv.h"
20a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkScaledBitmapSampler.h"
21a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkStream.h"
22a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkTemplates.h"
23a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkUtils.h"
24a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
25a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// A WebP decoder only, on top of (subset of) libwebp
26a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// For more information on WebP image format, and libwebp library, see:
27a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//   http://code.google.com/speed/webp/
28a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//   http://www.webmproject.org/code/#libwebp_webp_image_decoder_library
29a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//   http://review.webmproject.org/gitweb?p=libwebp.git
30a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
31a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include <stdio.h>
32a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgextern "C" {
33a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// If moving libwebp out of skia source tree, path for webp headers must be
34a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// updated accordingly. Here, we enforce using local copy in webp sub-directory.
35a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "webp/decode.h"
36a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "webp/encode.h"
37a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
38a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
39a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// this enables timing code to report milliseconds for a decode
40a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//#define TIME_DECODE
41a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
42a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////
43a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////
44a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
45a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// Define VP8 I/O on top of Skia stream
46a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
47a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////
48a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////
49a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
50a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic const size_t WEBP_VP8_HEADER_SIZE = 64;
51a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic const size_t WEBP_IDECODE_BUFFER_SZ = (1 << 16);
52a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
53a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// Parse headers of RIFF container, and check for valid Webp (VP8) content.
54a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic bool webp_parse_header(SkStream* stream, int* width, int* height, int* alpha) {
55a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    unsigned char buffer[WEBP_VP8_HEADER_SIZE];
563c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com    size_t bytesToRead = WEBP_VP8_HEADER_SIZE;
573c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com    size_t totalBytesRead = 0;
583c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com    do {
593c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com        unsigned char* dst = buffer + totalBytesRead;
603c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com        const size_t bytesRead = stream->read(dst, bytesToRead);
613c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com        if (0 == bytesRead) {
623c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com            // Could not read any bytes. Check to see if we are at the end (exit
633c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com            // condition), and continue reading if not. Important for streams
643c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com            // that do not have all the data ready.
653c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com            continue;
663c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com        }
673c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com        bytesToRead -= bytesRead;
683c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com        totalBytesRead += bytesRead;
693c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com        SkASSERT(bytesToRead + totalBytesRead == WEBP_VP8_HEADER_SIZE);
703c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com    } while (!stream->isAtEnd() && bytesToRead > 0);
71a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
72a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPBitstreamFeatures features;
733c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com    VP8StatusCode status = WebPGetFeatures(buffer, totalBytesRead, &features);
74a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (VP8_STATUS_OK != status) {
75a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false; // Invalid WebP file.
76a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
77a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    *width = features.width;
78a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    *height = features.height;
79a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    *alpha = features.has_alpha;
80a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
81a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // sanity check for image size that's about to be decoded.
82a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    {
8357212f9469c8056bab3c85243dbb904e386eab95reed@google.com        int64_t size = sk_64_mul(*width, *height);
8457212f9469c8056bab3c85243dbb904e386eab95reed@google.com        if (!sk_64_isS32(size)) {
85a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            return false;
86a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
87a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        // now check that if we are 4-bytes per pixel, we also don't overflow
8857212f9469c8056bab3c85243dbb904e386eab95reed@google.com        if (sk_64_asS32(size) > (0x7FFFFFFF >> 2)) {
89a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            return false;
90a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
91a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
92a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return true;
93a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
94a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
95a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgclass SkWEBPImageDecoder: public SkImageDecoder {
96a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgpublic:
97a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkWEBPImageDecoder() {
98a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        fInputStream = NULL;
99a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        fOrigWidth = 0;
100a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        fOrigHeight = 0;
101a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        fHasAlpha = 0;
102a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
103a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    virtual ~SkWEBPImageDecoder() {
104a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        SkSafeUnref(fInputStream);
105a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
106a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
107a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    virtual Format getFormat() const SK_OVERRIDE {
108a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return kWEBP_Format;
109a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
110a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
111a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgprotected:
112b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com    virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
1137e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com    virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
114a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
115a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
116a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgprivate:
1172bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    /**
1182bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com     *  Called when determining the output config to request to webp.
1192bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com     *  If the image does not have alpha, there is no need to premultiply.
1202bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com     *  If the caller wants unpremultiplied colors, that is respected.
1212bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com     */
1222bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    bool shouldPremultiply() const {
1232bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return SkToBool(fHasAlpha) && !this->getRequireUnpremultipliedColors();
1242bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
1252bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
126a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    bool setDecodeConfig(SkBitmap* decodedBitmap, int width, int height);
1272bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
128a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkStream* fInputStream;
129a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    int fOrigWidth;
130a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    int fOrigHeight;
131a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    int fHasAlpha;
132a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
133a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    typedef SkImageDecoder INHERITED;
134a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org};
135a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
136a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////
137a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
138a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#ifdef TIME_DECODE
139a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
140a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkTime.h"
141a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
142a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgclass AutoTimeMillis {
143a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgpublic:
144a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    AutoTimeMillis(const char label[]) :
145a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        fLabel(label) {
146a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        if (NULL == fLabel) {
147a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            fLabel = "";
148a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
149a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        fNow = SkTime::GetMSecs();
150a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
151a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    ~AutoTimeMillis() {
152a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        SkDebugf("---- Time (ms): %s %d\n", fLabel, SkTime::GetMSecs() - fNow);
153a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
154a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgprivate:
155a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    const char* fLabel;
156a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkMSec fNow;
157a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org};
158a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
159a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#endif
160a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
161a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
162a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
163a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// This guy exists just to aid in debugging, as it allows debuggers to just
164a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// set a break-point in one place to see all error exists.
165a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic bool return_false(const SkBitmap& bm, const char msg[]) {
166a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkDEBUGF(("libwebp error %s [%d %d]", msg, bm.width(), bm.height()));
167a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return false; // must always return false
168a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
169a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
1702bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.comstatic WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, bool premultiply) {
171a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WEBP_CSP_MODE mode = MODE_LAST;
1720689d7b12e7c427a077b003d3d8ae759d86f798freed    const SkColorType ct = decodedBitmap->colorType();
1732bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
1740689d7b12e7c427a077b003d3d8ae759d86f798freed    if (ct == kN32_SkColorType) {
175dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
176dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com            mode = premultiply ? MODE_bgrA : MODE_BGRA;
177dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
178dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com            mode = premultiply ? MODE_rgbA : MODE_RGBA;
179dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        #else
180dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com            #error "Skia uses BGRA or RGBA byte order"
181dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        #endif
1820689d7b12e7c427a077b003d3d8ae759d86f798freed    } else if (ct == kARGB_4444_SkColorType) {
1832bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        mode = premultiply ? MODE_rgbA_4444 : MODE_RGBA_4444;
1840689d7b12e7c427a077b003d3d8ae759d86f798freed    } else if (ct == kRGB_565_SkColorType) {
1852bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        mode = MODE_RGB_565;
186a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
187a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkASSERT(MODE_LAST != mode);
188a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return mode;
189a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
190a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
191a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// Incremental WebP image decoding. Reads input buffer of 64K size iteratively
192a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org// and decodes this block to appropriate color-space as per config object.
193a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic bool webp_idecode(SkStream* stream, WebPDecoderConfig* config) {
194a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPIDecoder* idec = WebPIDecode(NULL, 0, config);
195a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (NULL == idec) {
196a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        WebPFreeDecBuffer(&config->output);
197a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
198a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
199a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
2004d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com    if (!stream->rewind()) {
2014d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com        SkDebugf("Failed to rewind webp stream!");
2024d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com        return false;
2034d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com    }
2043c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com    const size_t readBufferSize = stream->hasLength() ?
2053c8730a84e469cfc71866a2f8d6bfd1d2ea689e3scroggo@google.com            SkTMin(stream->getLength(), WEBP_IDECODE_BUFFER_SZ) : WEBP_IDECODE_BUFFER_SZ;
206a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkAutoMalloc srcStorage(readBufferSize);
207a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    unsigned char* input = (uint8_t*)srcStorage.get();
208a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (NULL == input) {
209a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        WebPIDelete(idec);
210a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        WebPFreeDecBuffer(&config->output);
211a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
212a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
213a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
21480e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com    bool success = true;
21580e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com    VP8StatusCode status = VP8_STATUS_SUSPENDED;
21680e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com    do {
21780e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com        const size_t bytesRead = stream->read(input, readBufferSize);
218a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        if (0 == bytesRead) {
21980e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com            success = false;
220a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            break;
221a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
222a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
22380e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com        status = WebPIAppend(idec, input, bytesRead);
22480e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com        if (VP8_STATUS_OK != status && VP8_STATUS_SUSPENDED != status) {
22580e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com            success = false;
226a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            break;
227a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
22880e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com    } while (VP8_STATUS_OK != status);
229a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    srcStorage.free();
230a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPIDelete(idec);
231a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPFreeDecBuffer(&config->output);
232a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
23380e18c93bbeefe54f8192a380586e6468f179917scroggo@google.com    return success;
234a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
235a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
236a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic bool webp_get_config_resize(WebPDecoderConfig* config,
237a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                                   SkBitmap* decodedBitmap,
2382bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                                   int width, int height, bool premultiply) {
2392bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap, premultiply);
240a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (MODE_LAST == mode) {
241a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
242a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
243a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
244a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (0 == WebPInitDecoderConfig(config)) {
245a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
246a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
247a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
248a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->output.colorspace = mode;
249a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->output.u.RGBA.rgba = (uint8_t*)decodedBitmap->getPixels();
2508b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    config->output.u.RGBA.stride = (int) decodedBitmap->rowBytes();
251a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->output.u.RGBA.size = decodedBitmap->getSize();
252a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->output.is_external_memory = 1;
253a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
254a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (width != decodedBitmap->width() || height != decodedBitmap->height()) {
255a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        config->options.use_scaling = 1;
256a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        config->options.scaled_width = decodedBitmap->width();
257a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        config->options.scaled_height = decodedBitmap->height();
258a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
259a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
260a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return true;
261a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
262a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
263a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic bool webp_get_config_resize_crop(WebPDecoderConfig* config,
264a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                                        SkBitmap* decodedBitmap,
2652bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                                        const SkIRect& region, bool premultiply) {
266a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
267a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!webp_get_config_resize(config, decodedBitmap, region.width(),
2682bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                                region.height(), premultiply)) {
269a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      return false;
270a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
271a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
272a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->options.use_cropping = 1;
273a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->options.crop_left = region.fLeft;
274a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->options.crop_top = region.fTop;
275a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->options.crop_width = region.width();
276a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    config->options.crop_height = region.height();
277a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
278a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return true;
279a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
280a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
2816c22573edb234ad14df947278cfed010669a39a7reedbool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap, int width, int height) {
2826c22573edb234ad14df947278cfed010669a39a7reed    SkColorType colorType = this->getPrefColorType(k32Bit_SrcDepth, SkToBool(fHasAlpha));
283a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
284a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats.
285a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (fHasAlpha) {
2866c22573edb234ad14df947278cfed010669a39a7reed        if (colorType != kARGB_4444_SkColorType) {
2876c22573edb234ad14df947278cfed010669a39a7reed            colorType = kN32_SkColorType;
288a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
289a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    } else {
2906c22573edb234ad14df947278cfed010669a39a7reed        if (colorType != kRGB_565_SkColorType && colorType != kARGB_4444_SkColorType) {
2916c22573edb234ad14df947278cfed010669a39a7reed            colorType = kN32_SkColorType;
292a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
293a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
294a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
2955926b86b90c68bffefbdc8639e41b5bc9102cec6reed#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
2966c22573edb234ad14df947278cfed010669a39a7reed    if (!this->chooseFromOneChoice(colorType, width, height)) {
297a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
298a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
2995926b86b90c68bffefbdc8639e41b5bc9102cec6reed#endif
300a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
3016c22573edb234ad14df947278cfed010669a39a7reed    SkAlphaType alphaType = kOpaque_SkAlphaType;
302915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (SkToBool(fHasAlpha)) {
303915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        if (this->getRequireUnpremultipliedColors()) {
3046c22573edb234ad14df947278cfed010669a39a7reed            alphaType = kUnpremul_SkAlphaType;
305915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        } else {
3066c22573edb234ad14df947278cfed010669a39a7reed            alphaType = kPremul_SkAlphaType;
307915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        }
308915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
3096c22573edb234ad14df947278cfed010669a39a7reed    return decodedBitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType));
310a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
311a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
312b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.combool SkWEBPImageDecoder::onBuildTileIndex(SkStreamRewindable* stream,
313a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                                          int *width, int *height) {
314a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    int origWidth, origHeight, hasAlpha;
315a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
316a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
317a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
318a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
3194d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com    if (!stream->rewind()) {
3204d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com        SkDebugf("Failed to rewind webp stream!");
3214d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com        return false;
3224d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com    }
3234d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com
324a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    *width = origWidth;
325a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    *height = origHeight;
326a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
327a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkRefCnt_SafeAssign(this->fInputStream, stream);
328a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    this->fOrigWidth = origWidth;
329a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    this->fOrigHeight = origHeight;
330a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    this->fHasAlpha = hasAlpha;
331a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
332a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return true;
333a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
334a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
335a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic bool is_config_compatible(const SkBitmap& bitmap) {
3360689d7b12e7c427a077b003d3d8ae759d86f798freed    const SkColorType ct = bitmap.colorType();
3370689d7b12e7c427a077b003d3d8ae759d86f798freed    return ct == kARGB_4444_SkColorType || ct == kRGB_565_SkColorType || ct == kN32_SkColorType;
338a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
339a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
3407e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.combool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap,
341a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                                        const SkIRect& region) {
342a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkIRect rect = SkIRect::MakeWH(fOrigWidth, fOrigHeight);
343a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
344a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!rect.intersect(region)) {
345a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        // If the requested region is entirely outsides the image, return false
346a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
347a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
348a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
349a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    const int sampleSize = this->getSampleSize();
350a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkScaledBitmapSampler sampler(rect.width(), rect.height(), sampleSize);
351a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    const int width = sampler.scaledWidth();
352a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    const int height = sampler.scaledHeight();
353a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
354a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // The image can be decoded directly to decodedBitmap if
355a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    //   1. the region is within the image range
356a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    //   2. bitmap's config is compatible
357a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    //   3. bitmap's size is same as the required region (after sampled)
358a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    bool directDecode = (rect == region) &&
359a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                        (decodedBitmap->isNull() ||
360a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                         (is_config_compatible(*decodedBitmap) &&
361a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                         (decodedBitmap->width() == width) &&
362a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                         (decodedBitmap->height() == height)));
363a9f142e9f0e96ba6766479545a66654d8b3ebdc4commit-bot@chromium.org
364a9f142e9f0e96ba6766479545a66654d8b3ebdc4commit-bot@chromium.org    SkBitmap tmpBitmap;
365a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkBitmap *bitmap = decodedBitmap;
366a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
367a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!directDecode) {
368a9f142e9f0e96ba6766479545a66654d8b3ebdc4commit-bot@chromium.org        bitmap = &tmpBitmap;
369a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
370a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
371a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (bitmap->isNull()) {
372a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        if (!setDecodeConfig(bitmap, width, height)) {
373a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            return false;
374a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
375a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        // alloc from native heap if it is a temp bitmap. (prevent GC)
376a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        bool allocResult = (bitmap == decodedBitmap)
377a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                               ? allocPixelRef(bitmap, NULL)
378848250415eddc54075f7eb8795e8db79e749c6abreed                               : bitmap->tryAllocPixels();
379a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        if (!allocResult) {
380a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            return return_false(*decodedBitmap, "allocPixelRef");
381a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
3825926b86b90c68bffefbdc8639e41b5bc9102cec6reed#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
383a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    } else {
384a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        // This is also called in setDecodeConfig in above block.
385a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        // i.e., when bitmap->isNull() is true.
3866c22573edb234ad14df947278cfed010669a39a7reed        if (!chooseFromOneChoice(bitmap->colorType(), width, height)) {
387a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            return false;
388a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        }
3895926b86b90c68bffefbdc8639e41b5bc9102cec6reed#endif
390a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
391a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
392a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkAutoLockPixels alp(*bitmap);
393a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPDecoderConfig config;
3942bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (!webp_get_config_resize_crop(&config, bitmap, rect,
3952bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                                     this->shouldPremultiply())) {
396a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
397a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
398a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
399a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // Decode the WebP image data stream using WebP incremental decoding for
400a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // the specified cropped image-region.
401a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!webp_idecode(this->fInputStream, &config)) {
402a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
403a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
404a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
405a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!directDecode) {
406a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        cropBitmap(decodedBitmap, bitmap, sampleSize, region.x(), region.y(),
407a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                   region.width(), region.height(), rect.x(), rect.y());
408a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
409a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return true;
410a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
411a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
412a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgbool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
413a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                                  Mode mode) {
414a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#ifdef TIME_DECODE
415a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    AutoTimeMillis atm("WEBP Decode");
416a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#endif
417a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
418a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    int origWidth, origHeight, hasAlpha;
419a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
420a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
421a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
422a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    this->fHasAlpha = hasAlpha;
423a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
424a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    const int sampleSize = this->getSampleSize();
425a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
426bc69ce982f8374742ca910587485f0d741350c2dscroggo@google.com    if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(),
427bc69ce982f8374742ca910587485f0d741350c2dscroggo@google.com                         sampler.scaledHeight())) {
428bc69ce982f8374742ca910587485f0d741350c2dscroggo@google.com        return false;
429bc69ce982f8374742ca910587485f0d741350c2dscroggo@google.com    }
430a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
431a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // If only bounds are requested, done
432a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
433a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return true;
434a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
435a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
436a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!this->allocPixelRef(decodedBitmap, NULL)) {
437a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return return_false(*decodedBitmap, "allocPixelRef");
438a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
439a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
440a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkAutoLockPixels alp(*decodedBitmap);
441a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
442a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPDecoderConfig config;
443a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!webp_get_config_resize(&config, decodedBitmap, origWidth, origHeight,
4442bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                                this->shouldPremultiply())) {
445a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
446a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
447a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
448a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // Decode the WebP image data stream using WebP incremental decoding.
449a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return webp_idecode(stream, &config);
450a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
451a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
452a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
453a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
4545007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org#include "SkUnPreMultiply.h"
4555007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org
456a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgtypedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width,
457a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                                 const SkPMColor* SK_RESTRICT ctable);
458a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
459a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
460a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                             const SkPMColor*) {
461a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  const uint32_t* SK_RESTRICT src = (const uint32_t*)in;
462a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  for (int i = 0; i < width; ++i) {
463a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      const uint32_t c = *src++;
464a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[0] = SkGetPackedR32(c);
465a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[1] = SkGetPackedG32(c);
466a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[2] = SkGetPackedB32(c);
467a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb += 3;
468a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  }
469a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
470a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
4715007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.orgstatic void ARGB_8888_To_RGBA(const uint8_t* in, uint8_t* rgb, int width,
4725007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                              const SkPMColor*) {
4735007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org  const uint32_t* SK_RESTRICT src = (const uint32_t*)in;
4745007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org  const SkUnPreMultiply::Scale* SK_RESTRICT table =
4755007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      SkUnPreMultiply::GetScaleTable();
4765007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org  for (int i = 0; i < width; ++i) {
4775007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      const uint32_t c = *src++;
4785007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      uint8_t a = SkGetPackedA32(c);
4795007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      uint8_t r = SkGetPackedR32(c);
4805007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      uint8_t g = SkGetPackedG32(c);
4815007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      uint8_t b = SkGetPackedB32(c);
4825007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      if (0 != a && 255 != a) {
4835007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        SkUnPreMultiply::Scale scale = table[a];
4845007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        r = SkUnPreMultiply::ApplyScale(scale, r);
4855007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        g = SkUnPreMultiply::ApplyScale(scale, g);
4865007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        b = SkUnPreMultiply::ApplyScale(scale, b);
4875007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      }
4885007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb[0] = r;
4895007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb[1] = g;
4905007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb[2] = b;
4915007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb[3] = a;
4925007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb += 4;
4935007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org  }
4945007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org}
4955007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org
496a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
497a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                           const SkPMColor*) {
498a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  const uint16_t* SK_RESTRICT src = (const uint16_t*)in;
499a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  for (int i = 0; i < width; ++i) {
500a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      const uint16_t c = *src++;
501a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[0] = SkPacked16ToR32(c);
502a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[1] = SkPacked16ToG32(c);
503a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[2] = SkPacked16ToB32(c);
504a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb += 3;
505a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  }
506a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
507a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
508a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
509a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                             const SkPMColor*) {
510a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in;
511a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  for (int i = 0; i < width; ++i) {
512a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      const SkPMColor16 c = *src++;
513a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[0] = SkPacked4444ToR32(c);
514a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[1] = SkPacked4444ToG32(c);
515a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[2] = SkPacked4444ToB32(c);
516a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb += 3;
517a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  }
518a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
519a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
5205007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.orgstatic void ARGB_4444_To_RGBA(const uint8_t* in, uint8_t* rgb, int width,
5215007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                              const SkPMColor*) {
5225007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org  const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in;
5235007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org  const SkUnPreMultiply::Scale* SK_RESTRICT table =
5245007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      SkUnPreMultiply::GetScaleTable();
5255007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org  for (int i = 0; i < width; ++i) {
5265007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      const SkPMColor16 c = *src++;
5275007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      uint8_t a = SkPacked4444ToA32(c);
5285007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      uint8_t r = SkPacked4444ToR32(c);
5295007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      uint8_t g = SkPacked4444ToG32(c);
5305007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      uint8_t b = SkPacked4444ToB32(c);
5315007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      if (0 != a && 255 != a) {
5325007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        SkUnPreMultiply::Scale scale = table[a];
5335007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        r = SkUnPreMultiply::ApplyScale(scale, r);
5345007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        g = SkUnPreMultiply::ApplyScale(scale, g);
5355007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        b = SkUnPreMultiply::ApplyScale(scale, b);
5365007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      }
5375007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb[0] = r;
5385007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb[1] = g;
5395007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb[2] = b;
5405007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb[3] = a;
5415007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org      rgb += 4;
5425007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org  }
5435007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org}
5445007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org
545a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
546a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                          const SkPMColor* SK_RESTRICT ctable) {
547a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  const uint8_t* SK_RESTRICT src = (const uint8_t*)in;
548a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  for (int i = 0; i < width; ++i) {
549a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      const uint32_t c = ctable[*src++];
550a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[0] = SkGetPackedR32(c);
551a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[1] = SkGetPackedG32(c);
552a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb[2] = SkGetPackedB32(c);
553a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      rgb += 3;
554a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  }
555a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
556a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
5570689d7b12e7c427a077b003d3d8ae759d86f798freedstatic ScanlineImporter ChooseImporter(SkColorType ct, bool  hasAlpha, int*  bpp) {
5580689d7b12e7c427a077b003d3d8ae759d86f798freed    switch (ct) {
5590689d7b12e7c427a077b003d3d8ae759d86f798freed        case kN32_SkColorType:
5605007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org            if (hasAlpha) {
5615007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                *bpp = 4;
5625007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                return ARGB_8888_To_RGBA;
5635007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org            } else {
5645007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                *bpp = 3;
5655007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                return ARGB_8888_To_RGB;
5665007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org            }
5670689d7b12e7c427a077b003d3d8ae759d86f798freed        case kARGB_4444_SkColorType:
5685007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org            if (hasAlpha) {
5695007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                *bpp = 4;
5705007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                return ARGB_4444_To_RGBA;
5715007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org            } else {
5725007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                *bpp = 3;
5735007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org                return ARGB_4444_To_RGB;
5745007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org            }
5750689d7b12e7c427a077b003d3d8ae759d86f798freed        case kRGB_565_SkColorType:
5765007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org            *bpp = 3;
577a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            return RGB_565_To_RGB;
5780689d7b12e7c427a077b003d3d8ae759d86f798freed        case kIndex_8_SkColorType:
5795007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org            *bpp = 3;
580a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            return Index8_To_RGB;
581a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        default:
582a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org            return NULL;
583a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
584a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
585a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
586a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic int stream_writer(const uint8_t* data, size_t data_size,
587a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                         const WebPPicture* const picture) {
588a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  SkWStream* const stream = (SkWStream*)picture->custom_ptr;
589a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org  return stream->write(data, data_size) ? 1 : 0;
590a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
591a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
592a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgclass SkWEBPImageEncoder : public SkImageEncoder {
593a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgprotected:
594a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK_OVERRIDE;
595a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
596a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgprivate:
597a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    typedef SkImageEncoder INHERITED;
598a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org};
599a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
600a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgbool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm,
601a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                                  int quality) {
6025007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    const bool hasAlpha = !bm.isOpaque();
6035007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    int bpp = -1;
6040689d7b12e7c427a077b003d3d8ae759d86f798freed    const ScanlineImporter scanline_import = ChooseImporter(bm.colorType(), hasAlpha, &bpp);
605a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (NULL == scanline_import) {
606a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
607a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
6085007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    if (-1 == bpp) {
6095007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        return false;
6105007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    }
611a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
612a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkAutoLockPixels alp(bm);
613a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    SkAutoLockColors ctLocker;
614a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (NULL == bm.getPixels()) {
615a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
616a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
617a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
618a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPConfig webp_config;
619bff83f61fa0dafafa4734e791c34551d4cb8b811commit-bot@chromium.org    if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, (float) quality)) {
620a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return false;
621a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
622a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
623a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPPicture pic;
624a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPPictureInit(&pic);
625a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    pic.width = bm.width();
626a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    pic.height = bm.height();
627a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    pic.writer = stream_writer;
628a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    pic.custom_ptr = (void*)stream;
629a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
630a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    const SkPMColor* colors = ctLocker.lockColors(bm);
631a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    const uint8_t* src = (uint8_t*)bm.getPixels();
6325007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    const int rgbStride = pic.width * bpp;
633a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
634a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // Import (for each scanline) the bit-map image (in appropriate color-space)
635a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // to RGB color space.
636a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    uint8_t* rgb = new uint8_t[rgbStride * pic.height];
637a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    for (int y = 0; y < pic.height; ++y) {
638a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        scanline_import(src + y * bm.rowBytes(), rgb + y * rgbStride,
639a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org                        pic.width, colors);
640a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
641a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
6425007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    bool ok;
6435007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    if (bpp == 3) {
6445007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride));
6455007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    } else {
6465007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org        ok = SkToBool(WebPPictureImportRGBA(&pic, rgb, rgbStride));
6475007aab81ad1394f4ab7833ea230f6462aa07e69commit-bot@chromium.org    }
648a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    delete[] rgb;
649a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
650a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    ok = ok && WebPEncode(&webp_config, &pic);
651a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    WebPPictureFree(&pic);
652a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
653a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return ok;
654a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
655a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
656a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
657a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
658a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgDEFINE_DECODER_CREATOR(WEBPImageDecoder);
659a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgDEFINE_ENCODER_CREATOR(WEBPImageEncoder);
660a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
661a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
662b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkImageDecoder* sk_libwebp_dfactory(SkStreamRewindable* stream) {
663a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    int width, height, hasAlpha;
664a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    if (!webp_parse_header(stream, &width, &height, &hasAlpha)) {
665a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org        return NULL;
666a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    }
667a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
668a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    // Magic matches, call decoder
669a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org    return SkNEW(SkWEBPImageDecoder);
670a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
671a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
672b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkImageDecoder::Format get_format_webp(SkStreamRewindable* stream) {
67339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    int width, height, hasAlpha;
67439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    if (webp_parse_header(stream, &width, &height, &hasAlpha)) {
67539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        return SkImageDecoder::kWEBP_Format;
67639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
67739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return SkImageDecoder::kUnknown_Format;
67839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
67939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
680a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgstatic SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) {
681a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org      return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NULL;
682a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org}
683a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org
684bd6343b1d60d2a85e930f33f4b06b4502b3e8caamtklein@google.comstatic SkImageDecoder_DecodeReg gDReg(sk_libwebp_dfactory);
685bd6343b1d60d2a85e930f33f4b06b4502b3e8caamtklein@google.comstatic SkImageDecoder_FormatReg gFormatReg(get_format_webp);
686bd6343b1d60d2a85e930f33f4b06b4502b3e8caamtklein@google.comstatic SkImageEncoder_EncodeReg gEReg(sk_libwebp_efactory);
687