18432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold/*
28432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * Copyright 2010, The Android Open Source Project
38432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold *
48432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * Licensed under the Apache License, Version 2.0 (the "License");
58432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * you may not use this file except in compliance with the License.
68432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * You may obtain a copy of the License at
78432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold *
88432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold *     http://www.apache.org/licenses/LICENSE-2.0
98432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold *
108432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * Unless required by applicable law or agreed to in writing, software
118432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * distributed under the License is distributed on an "AS IS" BASIS,
128432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * See the License for the specific language governing permissions and
148432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold * limitations under the License.
158432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold */
168432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
178432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkImageDecoder.h"
188432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkImageEncoder.h"
198432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkColorPriv.h"
208432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkScaledBitmapSampler.h"
218432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkStream.h"
228432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkTemplates.h"
238432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkUtils.h"
24943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin#include "SkTScopedPtr.h"
258432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
268432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold// A WebP decoder only, on top of (subset of) libwebp
278432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold// For more information on WebP image format, and libwebp library, see:
288432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//   http://code.google.com/speed/webp/
298432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//   http://www.webmproject.org/code/#libwebp_webp_image_decoder_library
308432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//   http://review.webmproject.org/gitweb?p=libwebp.git
318432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
328432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include <stdio.h>
338432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldextern "C" {
348c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora// If moving libwebp out of skia source tree, path for webp headers must be
358c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora// updated accordingly. Here, we enforce using local copy in webp sub-directory.
368432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "webp/decode.h"
37a059123d8eb75302b13a7fd831478413d124d618Vikas Arora#include "webp/encode.h"
388432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold}
398432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
408432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#ifdef ANDROID
418432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include <cutils/properties.h>
428432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
438432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold// Key to lookup the size of memory buffer set in system property
448432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldstatic const char KEY_MEM_CAP[] = "ro.media.dec.webp.memcap";
458432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#endif
468432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
478432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold// this enables timing code to report milliseconds for a decode
488432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//#define TIME_DECODE
498432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
508432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//////////////////////////////////////////////////////////////////////////
518432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//////////////////////////////////////////////////////////////////////////
528432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
538432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold// Define VP8 I/O on top of Skia stream
548432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
558432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//////////////////////////////////////////////////////////////////////////
568432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//////////////////////////////////////////////////////////////////////////
578432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
5822c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arorastatic const size_t WEBP_VP8_HEADER_SIZE = 64;
5982ed38078af4a2b643415a76e84f88754f804709Vikas Arorastatic const size_t WEBP_IDECODE_BUFFER_SZ = (1 << 16);
608432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
6182ed38078af4a2b643415a76e84f88754f804709Vikas Arora// Parse headers of RIFF container, and check for valid Webp (VP8) content.
6222c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arorastatic bool webp_parse_header(SkStream* stream, int* width, int* height,
6322c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora                              int* alpha) {
6482ed38078af4a2b643415a76e84f88754f804709Vikas Arora    unsigned char buffer[WEBP_VP8_HEADER_SIZE];
6522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    const uint32_t contentSize = stream->getLength();
6682ed38078af4a2b643415a76e84f88754f804709Vikas Arora    const size_t len = stream->read(buffer, WEBP_VP8_HEADER_SIZE);
6722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    const uint32_t read_bytes = (contentSize < WEBP_VP8_HEADER_SIZE) ?
6822c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora        contentSize : WEBP_VP8_HEADER_SIZE;
6922c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    if (len != read_bytes) {
7082ed38078af4a2b643415a76e84f88754f804709Vikas Arora        return false; // can't read enough
718432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
728432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
7322c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    WebPBitstreamFeatures features;
7422c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    VP8StatusCode status = WebPGetFeatures(buffer, read_bytes, &features);
7522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    if (status != VP8_STATUS_OK) {
7682ed38078af4a2b643415a76e84f88754f804709Vikas Arora        return false; // Invalid WebP file.
778432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
7822c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    *width = features.width;
7922c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    *height = features.height;
8022c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    *alpha = features.has_alpha;
818432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
8282ed38078af4a2b643415a76e84f88754f804709Vikas Arora    // sanity check for image size that's about to be decoded.
8382ed38078af4a2b643415a76e84f88754f804709Vikas Arora    {
8482ed38078af4a2b643415a76e84f88754f804709Vikas Arora        Sk64 size;
8582ed38078af4a2b643415a76e84f88754f804709Vikas Arora        size.setMul(*width, *height);
8682ed38078af4a2b643415a76e84f88754f804709Vikas Arora        if (size.isNeg() || !size.is32()) {
8782ed38078af4a2b643415a76e84f88754f804709Vikas Arora            return false;
8882ed38078af4a2b643415a76e84f88754f804709Vikas Arora        }
8982ed38078af4a2b643415a76e84f88754f804709Vikas Arora        // now check that if we are 4-bytes per pixel, we also don't overflow
9082ed38078af4a2b643415a76e84f88754f804709Vikas Arora        if (size.get32() > (0x7FFFFFFF >> 2)) {
9182ed38078af4a2b643415a76e84f88754f804709Vikas Arora            return false;
9282ed38078af4a2b643415a76e84f88754f804709Vikas Arora        }
938432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
9482ed38078af4a2b643415a76e84f88754f804709Vikas Arora    return true;
958432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold}
968432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
978432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldclass SkWEBPImageDecoder: public SkImageDecoder {
988432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldpublic:
998432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    virtual Format getFormat() const {
1008432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        return kWEBP_Format;
1018432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
1028432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
1038432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldprotected:
1048c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height);
1058c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect rect);
1068432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
10782ed38078af4a2b643415a76e84f88754f804709Vikas Arora
10882ed38078af4a2b643415a76e84f88754f804709Vikas Aroraprivate:
10982ed38078af4a2b643415a76e84f88754f804709Vikas Arora    bool setDecodeConfig(SkBitmap* decodedBitmap, int width, int height);
1108c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    SkStream *inputStream;
1118c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    int origWidth;
1128c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    int origHeight;
11322c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    int hasAlpha;
1148432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold};
1158432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
1168432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold//////////////////////////////////////////////////////////////////////////
1178432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
1188432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkTime.h"
1198432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
1208432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldclass AutoTimeMillis {
1218432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldpublic:
1228432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    AutoTimeMillis(const char label[]) :
1238432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        fLabel(label) {
1248432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        if (!fLabel) {
1258432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold            fLabel = "";
1268432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        }
1278432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        fNow = SkTime::GetMSecs();
1288432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
1298432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    ~AutoTimeMillis() {
1308432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        SkDebugf("---- Time (ms): %s %d\n", fLabel, SkTime::GetMSecs() - fNow);
1318432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
1328432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldprivate:
1338432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    const char* fLabel;
1348432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    SkMSec fNow;
1358432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold};
1368432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
1378432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold///////////////////////////////////////////////////////////////////////////////
1388432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
1398432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold// This guy exists just to aid in debugging, as it allows debuggers to just
1408432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold// set a break-point in one place to see all error exists.
1418432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldstatic bool return_false(const SkBitmap& bm, const char msg[]) {
1428432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#if 0
1438432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    SkDebugf("libwebp error %s [%d %d]", msg, bm.width(), bm.height());
1448432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#endif
1458432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    return false; // must always return false
1468432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold}
1478432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
148772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arorastatic WEBP_CSP_MODE webp_decode_mode(SkBitmap* decodedBitmap, int hasAlpha) {
14913f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora    WEBP_CSP_MODE mode = MODE_LAST;
15013f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora    SkBitmap::Config config = decodedBitmap->config();
151772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    // For images that have alpha, choose appropriate color mode (MODE_rgbA,
152772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    // MODE_rgbA_4444) that pre-multiplies RGB pixel values with transparency
153772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    // factor (alpha).
15413f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora    if (config == SkBitmap::kARGB_8888_Config) {
155772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora      mode = hasAlpha ? MODE_rgbA : MODE_RGBA;
15613f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora    } else if (config == SkBitmap::kARGB_4444_Config) {
157772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora      mode = hasAlpha ? MODE_rgbA_4444 : MODE_RGBA_4444;
15813f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora    } else if (config == SkBitmap::kRGB_565_Config) {
15913f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora      mode = MODE_RGB_565;
160c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora    }
161772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    SkASSERT(mode != MODE_LAST);
1628c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    return mode;
1638c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora}
16413f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora
1658c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora// Incremental WebP image decoding. Reads input buffer of 64K size iteratively
1668c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora// and decodes this block to appropriate color-space as per config object.
1678c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arorastatic bool webp_idecode(SkStream* stream, WebPDecoderConfig& config) {
168943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    WebPIDecoder* idec = WebPIDecode(NULL, 0, &config);
16913f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora    if (idec == NULL) {
1708c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        WebPFreeDecBuffer(&config.output);
1718432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        return false;
1728432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
1738432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
1748c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    stream->rewind();
1758c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    const uint32_t contentSize = stream->getLength();
17622c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    const uint32_t read_buffer_size = (contentSize < WEBP_IDECODE_BUFFER_SZ) ?
17722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora        contentSize : WEBP_IDECODE_BUFFER_SZ;
17882ed38078af4a2b643415a76e84f88754f804709Vikas Arora    SkAutoMalloc srcStorage(read_buffer_size);
17982ed38078af4a2b643415a76e84f88754f804709Vikas Arora    unsigned char* input = (uint8_t*)srcStorage.get();
18082ed38078af4a2b643415a76e84f88754f804709Vikas Arora    if (input == NULL) {
18182ed38078af4a2b643415a76e84f88754f804709Vikas Arora        WebPIDelete(idec);
1828c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        WebPFreeDecBuffer(&config.output);
1838432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        return false;
1848432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
18582ed38078af4a2b643415a76e84f88754f804709Vikas Arora
1860d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora    bool success = true;
1870d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora    VP8StatusCode status = VP8_STATUS_SUSPENDED;
1880d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora    do {
1890d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora        const uint32_t bytes_to_read = WEBP_IDECODE_BUFFER_SZ;
19082ed38078af4a2b643415a76e84f88754f804709Vikas Arora        const size_t bytes_read = stream->read(input, bytes_to_read);
19182ed38078af4a2b643415a76e84f88754f804709Vikas Arora        if (bytes_read == 0) {
1920d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora            success = false;
19382ed38078af4a2b643415a76e84f88754f804709Vikas Arora            break;
19482ed38078af4a2b643415a76e84f88754f804709Vikas Arora        }
19582ed38078af4a2b643415a76e84f88754f804709Vikas Arora
1960d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora        status = WebPIAppend(idec, input, bytes_read);
1970d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora        if (VP8_STATUS_OK != status && VP8_STATUS_SUSPENDED != status) {
1980d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora            success = false;
19982ed38078af4a2b643415a76e84f88754f804709Vikas Arora            break;
20082ed38078af4a2b643415a76e84f88754f804709Vikas Arora        }
2010d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora    } while (VP8_STATUS_OK != status);
20282ed38078af4a2b643415a76e84f88754f804709Vikas Arora    srcStorage.free();
20382ed38078af4a2b643415a76e84f88754f804709Vikas Arora    WebPIDelete(idec);
2048c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    WebPFreeDecBuffer(&config.output);
20582ed38078af4a2b643415a76e84f88754f804709Vikas Arora
2060d4a859c834194fba1e003c2aa22dc75036444d6Vikas Arora    return success;
20782ed38078af4a2b643415a76e84f88754f804709Vikas Arora}
2088432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
20922c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arorastatic bool webp_get_config_resize(WebPDecoderConfig& config,
21022c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora                                   SkBitmap* decodedBitmap,
211772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora                                   int width, int height, int hasAlpha) {
212772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap, hasAlpha);
2138c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    if (mode == MODE_LAST) {
2148c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        return false;
2158c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    }
2168c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
2178c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    if (WebPInitDecoderConfig(&config) == 0) {
2188c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        return false;
2198c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    }
2208c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
2218c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    config.output.colorspace = mode;
2228c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    config.output.u.RGBA.rgba = (uint8_t*)decodedBitmap->getPixels();
2238c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    config.output.u.RGBA.stride = decodedBitmap->rowBytes();
2248c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    config.output.u.RGBA.size = decodedBitmap->getSize();
2258c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    config.output.is_external_memory = 1;
2268c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
22722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    if (width != decodedBitmap->width() ||
22822c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora        height != decodedBitmap->height()) {
2298c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        config.options.use_scaling = 1;
2308c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        config.options.scaled_width = decodedBitmap->width();
2318c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        config.options.scaled_height = decodedBitmap->height();
2328c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    }
2338c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
2348c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    return true;
2358c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora}
2368c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
23722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arorastatic bool webp_get_config_resize_crop(WebPDecoderConfig& config,
23822c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora                                        SkBitmap* decodedBitmap,
239772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora                                        SkIRect region, int hasAlpha) {
2408c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
241772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    if (!webp_get_config_resize(
242772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora        config, decodedBitmap, region.width(), region.height(), hasAlpha)) {
243772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora      return false;
244772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    }
2458c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
24622c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    config.options.use_cropping = 1;
24722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    config.options.crop_left = region.fLeft;
24822c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    config.options.crop_top = region.fTop;
24922c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    config.options.crop_width = region.width();
25022c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    config.options.crop_height = region.height();
2518c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
2528c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    return true;
2538c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora}
2548c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
25582ed38078af4a2b643415a76e84f88754f804709Vikas Arorabool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap,
256c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora                                         int width, int height) {
25782ed38078af4a2b643415a76e84f88754f804709Vikas Arora    SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, hasAlpha);
2588432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
2598c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    // YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats.
2608432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    if (hasAlpha) {
2618432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        if (config != SkBitmap::kARGB_4444_Config) {
2628432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold            config = SkBitmap::kARGB_8888_Config;
2638432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        }
2648432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    } else {
26582ed38078af4a2b643415a76e84f88754f804709Vikas Arora        if (config != SkBitmap::kRGB_565_Config &&
26682ed38078af4a2b643415a76e84f88754f804709Vikas Arora            config != SkBitmap::kARGB_4444_Config) {
2678432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold            config = SkBitmap::kARGB_8888_Config;
2688432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        }
2698432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
2708432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
271c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora    if (!this->chooseFromOneChoice(config, width, height)) {
2728432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        return false;
2738432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
2748432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
275c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora    decodedBitmap->setConfig(config, width, height, 0);
2768432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
27722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    decodedBitmap->setIsOpaque(!hasAlpha);
2788432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
27982ed38078af4a2b643415a76e84f88754f804709Vikas Arora    return true;
28082ed38078af4a2b643415a76e84f88754f804709Vikas Arora}
2818432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
2828c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arorabool SkWEBPImageDecoder::onBuildTileIndex(SkStream* stream,
2838c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora                                          int *width, int *height) {
28422c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    int origWidth, origHeight, hasAlpha;
28522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
2868c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        return false;
2878c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    }
2888c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
2898c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    stream->rewind();
2908c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    *width = origWidth;
2918c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    *height = origHeight;
2928c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
2938c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    this->inputStream = stream;
2948c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    this->origWidth = origWidth;
2958c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    this->origHeight = origHeight;
29622c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    this->hasAlpha = hasAlpha;
2978c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
2988c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    return true;
2998c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora}
3008c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
30122c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arorastatic bool isConfigCompatible(SkBitmap* bitmap) {
302943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    SkBitmap::Config config = bitmap->config();
303943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    return config == SkBitmap::kARGB_4444_Config ||
304943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin           config == SkBitmap::kRGB_565_Config ||
305943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin           config == SkBitmap::kARGB_8888_Config;
306943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin}
307943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin
3088c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arorabool SkWEBPImageDecoder::onDecodeRegion(SkBitmap* decodedBitmap,
3098c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora                                        SkIRect region) {
310943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    SkIRect rect = SkIRect::MakeWH(origWidth, origHeight);
3118c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
312943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    if (!rect.intersect(region)) {
313943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        // If the requested region is entirely outsides the image, just
314943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        // returns false
3158c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        return false;
3168c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    }
3178c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
318943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    const int sampleSize = this->getSampleSize();
319943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    SkScaledBitmapSampler sampler(rect.width(), rect.height(), sampleSize);
320943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    const int width = sampler.scaledWidth();
321943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    const int height = sampler.scaledHeight();
322943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin
323943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    // The image can be decoded directly to decodedBitmap if
324943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    //   1. the region is within the image range
325943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    //   2. bitmap's config is compatible
326943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    //   3. bitmap's size is same as the required region (after sampled)
327943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    bool directDecode = (rect == region) &&
328943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin                        (decodedBitmap->isNull() ||
32922c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora                         (isConfigCompatible(decodedBitmap) &&
330943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin                         (decodedBitmap->width() == width) &&
33122c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora                         (decodedBitmap->height() == height)));
332943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    SkTScopedPtr<SkBitmap> adb;
333943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    SkBitmap *bitmap = decodedBitmap;
334943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin
335943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    if (!directDecode) {
336943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        // allocates a temp bitmap
337943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        bitmap = new SkBitmap;
338943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        adb.reset(bitmap);
3398c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    }
3408c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
341943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    if (bitmap->isNull()) {
342943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        if (!setDecodeConfig(bitmap, width, height)) {
343943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin            return false;
344943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        }
345943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        // alloc from native heap if it is a temp bitmap. (prevent GC)
346943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        bool allocResult = (bitmap == decodedBitmap)
347943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin                               ? allocPixelRef(bitmap, NULL)
348943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin                               : bitmap->allocPixels();
349943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        if (!allocResult) {
350943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin            return return_false(*decodedBitmap, "allocPixelRef");
351943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        }
352943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    } else {
353943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        // This is also called in setDecodeConfig in above block.
354943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        // i.e., when bitmap->isNull() is true.
355943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        if (!chooseFromOneChoice(bitmap->config(), width, height)) {
356943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin            return false;
357943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        }
358943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    }
3598c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
360943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    SkAutoLockPixels alp(*bitmap);
3618c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    WebPDecoderConfig config;
362772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    if (!webp_get_config_resize_crop(config, bitmap, rect, hasAlpha)) {
3638c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora        return false;
3648c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    }
3658c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
3668c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    // Decode the WebP image data stream using WebP incremental decoding for
3678c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    // the specified cropped image-region.
368943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    if (!webp_idecode(this->inputStream, config)) {
369943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        return false;
370943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    }
371943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin
372943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    if (!directDecode) {
373943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin        cropBitmap(decodedBitmap, bitmap, sampleSize, region.x(), region.y(),
374943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin                  region.width(), region.height(), rect.x(), rect.y());
375943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    }
376943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin    return true;
3778c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora}
3788c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
37982ed38078af4a2b643415a76e84f88754f804709Vikas Arorabool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
38082ed38078af4a2b643415a76e84f88754f804709Vikas Arora                                  Mode mode) {
38182ed38078af4a2b643415a76e84f88754f804709Vikas Arora#ifdef TIME_DECODE
38282ed38078af4a2b643415a76e84f88754f804709Vikas Arora    AutoTimeMillis atm("WEBP Decode");
3838432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#endif
38482ed38078af4a2b643415a76e84f88754f804709Vikas Arora
38522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    int origWidth, origHeight, hasAlpha;
38622c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
3878432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        return false;
3888432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
38922c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    this->hasAlpha = hasAlpha;
3908432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
391c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora    const int sampleSize = this->getSampleSize();
392c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora    SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
393c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora
39482ed38078af4a2b643415a76e84f88754f804709Vikas Arora    // If only bounds are requested, done
39582ed38078af4a2b643415a76e84f88754f804709Vikas Arora    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
396c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase        if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(),
397c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase                             sampler.scaledHeight())) {
398c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase            return false;
399c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase        }
40082ed38078af4a2b643415a76e84f88754f804709Vikas Arora        return true;
40182ed38078af4a2b643415a76e84f88754f804709Vikas Arora    }
402c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase#ifdef SK_BUILD_FOR_ANDROID
403c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase    // No Bitmap reuse supported for this format
404c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase    if (!decodedBitmap->isNull()) {
405c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase        return false;
406c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase    }
407c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase#endif
408c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase    if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(),
409c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase                         sampler.scaledHeight())) {
410c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase        return false;
411c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase    }
4128432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
41382ed38078af4a2b643415a76e84f88754f804709Vikas Arora    if (!this->allocPixelRef(decodedBitmap, NULL)) {
41482ed38078af4a2b643415a76e84f88754f804709Vikas Arora        return return_false(*decodedBitmap, "allocPixelRef");
4158432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
4168432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
4178c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    SkAutoLockPixels alp(*decodedBitmap);
4188c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora
4198c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    WebPDecoderConfig config;
420772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora    if (!webp_get_config_resize(config, decodedBitmap, origWidth, origHeight,
421772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora                                hasAlpha)) {
4228432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold        return false;
4238432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
4248432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
4258c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    // Decode the WebP image data stream using WebP incremental decoding.
4268c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora    return webp_idecode(stream, config);
4278432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold}
4288432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
4298432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold///////////////////////////////////////////////////////////////////////////////
4308432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
431a059123d8eb75302b13a7fd831478413d124d618Vikas Aroratypedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width,
432a059123d8eb75302b13a7fd831478413d124d618Vikas Arora                                 const SkPMColor* SK_RESTRICT ctable);
433a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
434a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
435a059123d8eb75302b13a7fd831478413d124d618Vikas Arora                             const SkPMColor*) {
436a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  const uint32_t* SK_RESTRICT src = (const uint32_t*)in;
437a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  for (int i = 0; i < width; ++i) {
438a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      const uint32_t c = *src++;
439a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[0] = SkGetPackedR32(c);
440a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[1] = SkGetPackedG32(c);
441a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[2] = SkGetPackedB32(c);
442a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb += 3;
443a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  }
444a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}
445a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
446a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
447a059123d8eb75302b13a7fd831478413d124d618Vikas Arora                           const SkPMColor*) {
448a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  const uint16_t* SK_RESTRICT src = (const uint16_t*)in;
449a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  for (int i = 0; i < width; ++i) {
450a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      const uint16_t c = *src++;
451a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[0] = SkPacked16ToR32(c);
452a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[1] = SkPacked16ToG32(c);
453a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[2] = SkPacked16ToB32(c);
454a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb += 3;
455a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  }
456a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}
457a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
458a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
459a059123d8eb75302b13a7fd831478413d124d618Vikas Arora                             const SkPMColor*) {
460a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in;
461a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  for (int i = 0; i < width; ++i) {
462a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      const SkPMColor16 c = *src++;
463a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[0] = SkPacked4444ToR32(c);
464a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[1] = SkPacked4444ToG32(c);
465a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[2] = SkPacked4444ToB32(c);
466a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb += 3;
467a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  }
468a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}
469a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
470a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
471a059123d8eb75302b13a7fd831478413d124d618Vikas Arora                          const SkPMColor* SK_RESTRICT ctable) {
472a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  const uint8_t* SK_RESTRICT src = (const uint8_t*)in;
473a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  for (int i = 0; i < width; ++i) {
474a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      const uint32_t c = ctable[*src++];
475a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[0] = SkGetPackedR32(c);
476a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[1] = SkGetPackedG32(c);
477a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb[2] = SkGetPackedB32(c);
478a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      rgb += 3;
479a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  }
480a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}
481a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
482a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic ScanlineImporter ChooseImporter(const SkBitmap::Config& config) {
483a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    switch (config) {
484a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        case SkBitmap::kARGB_8888_Config:
485a059123d8eb75302b13a7fd831478413d124d618Vikas Arora            return ARGB_8888_To_RGB;
486a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        case SkBitmap::kRGB_565_Config:
487a059123d8eb75302b13a7fd831478413d124d618Vikas Arora            return RGB_565_To_RGB;
488a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        case SkBitmap::kARGB_4444_Config:
489a059123d8eb75302b13a7fd831478413d124d618Vikas Arora            return ARGB_4444_To_RGB;
490a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        case SkBitmap::kIndex8_Config:
491a059123d8eb75302b13a7fd831478413d124d618Vikas Arora            return Index8_To_RGB;
492a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        default:
493a059123d8eb75302b13a7fd831478413d124d618Vikas Arora            return NULL;
494a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    }
495a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}
496a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
497a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic int StreamWriter(const uint8_t* data, size_t data_size,
498a059123d8eb75302b13a7fd831478413d124d618Vikas Arora                        const WebPPicture* const picture) {
499a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  SkWStream* const stream = (SkWStream*)picture->custom_ptr;
500a059123d8eb75302b13a7fd831478413d124d618Vikas Arora  return stream->write(data, data_size) ? 1 : 0;
501a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}
502a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
503a059123d8eb75302b13a7fd831478413d124d618Vikas Aroraclass SkWEBPImageEncoder : public SkImageEncoder {
504a059123d8eb75302b13a7fd831478413d124d618Vikas Aroraprotected:
505a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
506a059123d8eb75302b13a7fd831478413d124d618Vikas Arora};
507a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
508a059123d8eb75302b13a7fd831478413d124d618Vikas Arorabool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm,
509a059123d8eb75302b13a7fd831478413d124d618Vikas Arora                                  int quality) {
510a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    const SkBitmap::Config config = bm.getConfig();
511a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    const ScanlineImporter scanline_import = ChooseImporter(config);
512a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    if (NULL == scanline_import) {
513a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        return false;
514a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    }
515a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
516a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    SkAutoLockPixels alp(bm);
517a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    SkAutoLockColors ctLocker;
518a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    if (NULL == bm.getPixels()) {
519a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        return false;
520a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    }
521a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
522a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    WebPConfig webp_config;
523a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, quality)) {
524a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        return false;
525a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    }
526a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
527a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    WebPPicture pic;
528a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    WebPPictureInit(&pic);
529a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    pic.width = bm.width();
530a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    pic.height = bm.height();
531a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    pic.writer = StreamWriter;
532a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    pic.custom_ptr = (void*)stream;
533a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
534a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    const SkPMColor* colors = ctLocker.lockColors(bm);
535a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    const uint8_t* src = (uint8_t*)bm.getPixels();
536a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    const int rgb_stride = pic.width * 3;
537a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
538a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    // Import (for each scanline) the bit-map image (in appropriate color-space)
539a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    // to RGB color space.
540a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    uint8_t* rgb = new uint8_t[rgb_stride * pic.height];
541a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    for (int y = 0; y < pic.height; ++y) {
542a059123d8eb75302b13a7fd831478413d124d618Vikas Arora        scanline_import(src + y * bm.rowBytes(), rgb + y * rgb_stride,
543a059123d8eb75302b13a7fd831478413d124d618Vikas Arora                        pic.width, colors);
544a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    }
545a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
546a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    bool ok = WebPPictureImportRGB(&pic, rgb, rgb_stride);
547a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    delete[] rgb;
548a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
549a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    ok = ok && WebPEncode(&webp_config, &pic);
550a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    WebPPictureFree(&pic);
551a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
552a059123d8eb75302b13a7fd831478413d124d618Vikas Arora    return ok;
553a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}
554a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
555a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
556a059123d8eb75302b13a7fd831478413d124d618Vikas Arora///////////////////////////////////////////////////////////////////////////////
5576699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste QueruDEFINE_DECODER_CREATOR(WEBPImageDecoder);
5586699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste QueruDEFINE_ENCODER_CREATOR(WEBPImageEncoder);
5596699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
560a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
5618432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkTRegistry.h"
5628432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
5636699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Querustatic SkImageDecoder* sk_libwebp_dfactory(SkStream* stream) {
56422c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    int width, height, hasAlpha;
56522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora    if (!webp_parse_header(stream, &width, &height, &hasAlpha)) {
566772042aa3d99e2cfd8077981236cc2bec4d8078fVikas Arora        return NULL;
5678432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    }
5688432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
5698432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    // Magic matches, call decoder
5708432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold    return SkNEW(SkWEBPImageDecoder);
5718432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold}
5728432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold
5736699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Querustatic SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) {
574a059123d8eb75302b13a7fd831478413d124d618Vikas Arora      return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NULL;
575a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}
576a059123d8eb75302b13a7fd831478413d124d618Vikas Arora
577a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libwebp_dfactory);
578a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libwebp_efactory);
579