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 1484981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas 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(); 1514981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora // For images that have alpha, choose appropriate color mode (MODE_rgbA, 1524981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora // MODE_rgbA_4444) that pre-multiplies RGB pixel values with transparency 1534981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora // factor (alpha). 15413f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora if (config == SkBitmap::kARGB_8888_Config) { 1554981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora mode = hasAlpha ? MODE_rgbA : MODE_RGBA; 15613f6c47b625101944c936a20fb673cbe47b5c747Vikas Arora } else if (config == SkBitmap::kARGB_4444_Config) { 1574981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas 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 } 1614981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas 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 18682ed38078af4a2b643415a76e84f88754f804709Vikas Arora uint32_t bytes_remaining = contentSize; 18782ed38078af4a2b643415a76e84f88754f804709Vikas Arora while (bytes_remaining > 0) { 18882ed38078af4a2b643415a76e84f88754f804709Vikas Arora const uint32_t bytes_to_read = 18922c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora (bytes_remaining < WEBP_IDECODE_BUFFER_SZ) ? 19022c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora bytes_remaining : WEBP_IDECODE_BUFFER_SZ; 19182ed38078af4a2b643415a76e84f88754f804709Vikas Arora 19282ed38078af4a2b643415a76e84f88754f804709Vikas Arora const size_t bytes_read = stream->read(input, bytes_to_read); 19382ed38078af4a2b643415a76e84f88754f804709Vikas Arora if (bytes_read == 0) { 19482ed38078af4a2b643415a76e84f88754f804709Vikas Arora break; 19582ed38078af4a2b643415a76e84f88754f804709Vikas Arora } 19682ed38078af4a2b643415a76e84f88754f804709Vikas Arora 19782ed38078af4a2b643415a76e84f88754f804709Vikas Arora VP8StatusCode status = WebPIAppend(idec, input, bytes_read); 19882ed38078af4a2b643415a76e84f88754f804709Vikas Arora if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) { 19982ed38078af4a2b643415a76e84f88754f804709Vikas Arora bytes_remaining -= bytes_read; 20082ed38078af4a2b643415a76e84f88754f804709Vikas Arora } else { 20182ed38078af4a2b643415a76e84f88754f804709Vikas Arora break; 20282ed38078af4a2b643415a76e84f88754f804709Vikas Arora } 20382ed38078af4a2b643415a76e84f88754f804709Vikas Arora } 20482ed38078af4a2b643415a76e84f88754f804709Vikas Arora srcStorage.free(); 20582ed38078af4a2b643415a76e84f88754f804709Vikas Arora WebPIDelete(idec); 2068c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora WebPFreeDecBuffer(&config.output); 20782ed38078af4a2b643415a76e84f88754f804709Vikas Arora 20882ed38078af4a2b643415a76e84f88754f804709Vikas Arora if (bytes_remaining > 0) { 2098432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold return false; 21082ed38078af4a2b643415a76e84f88754f804709Vikas Arora } else { 21182ed38078af4a2b643415a76e84f88754f804709Vikas Arora return true; 2128432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 21382ed38078af4a2b643415a76e84f88754f804709Vikas Arora} 2148432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 21522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arorastatic bool webp_get_config_resize(WebPDecoderConfig& config, 21622c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora SkBitmap* decodedBitmap, 2174981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora int width, int height, int hasAlpha) { 2184981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap, hasAlpha); 2198c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora if (mode == MODE_LAST) { 2208c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return false; 2218c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora } 2228c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 2238c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora if (WebPInitDecoderConfig(&config) == 0) { 2248c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return false; 2258c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora } 2268c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 2278c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora config.output.colorspace = mode; 2288c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora config.output.u.RGBA.rgba = (uint8_t*)decodedBitmap->getPixels(); 2298c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora config.output.u.RGBA.stride = decodedBitmap->rowBytes(); 2308c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora config.output.u.RGBA.size = decodedBitmap->getSize(); 2318c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora config.output.is_external_memory = 1; 2328c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 23322c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora if (width != decodedBitmap->width() || 23422c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora height != decodedBitmap->height()) { 2358c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora config.options.use_scaling = 1; 2368c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora config.options.scaled_width = decodedBitmap->width(); 2378c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora config.options.scaled_height = decodedBitmap->height(); 2388c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora } 2398c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 2408c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return true; 2418c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora} 2428c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 24322c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arorastatic bool webp_get_config_resize_crop(WebPDecoderConfig& config, 24422c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora SkBitmap* decodedBitmap, 2454981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora SkIRect region, int hasAlpha) { 2468c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 2474981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora if (!webp_get_config_resize( 2484981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora config, decodedBitmap, region.width(), region.height(), hasAlpha)) { 2494981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora return false; 2504981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora } 2518c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 25222c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora config.options.use_cropping = 1; 25322c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora config.options.crop_left = region.fLeft; 25422c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora config.options.crop_top = region.fTop; 25522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora config.options.crop_width = region.width(); 25622c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora config.options.crop_height = region.height(); 2578c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 2588c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return true; 2598c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora} 2608c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 26182ed38078af4a2b643415a76e84f88754f804709Vikas Arorabool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap, 262c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora int width, int height) { 26382ed38078af4a2b643415a76e84f88754f804709Vikas Arora SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, hasAlpha); 2648432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 2658c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora // YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats. 2668432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold if (hasAlpha) { 2678432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold if (config != SkBitmap::kARGB_4444_Config) { 2688432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold config = SkBitmap::kARGB_8888_Config; 2698432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 2708432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } else { 27182ed38078af4a2b643415a76e84f88754f804709Vikas Arora if (config != SkBitmap::kRGB_565_Config && 27282ed38078af4a2b643415a76e84f88754f804709Vikas Arora config != SkBitmap::kARGB_4444_Config) { 2738432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold config = SkBitmap::kARGB_8888_Config; 2748432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 2758432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 2768432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 277c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora if (!this->chooseFromOneChoice(config, width, height)) { 2788432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold return false; 2798432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 2808432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 281c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora decodedBitmap->setConfig(config, width, height, 0); 2828432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 28322c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora decodedBitmap->setIsOpaque(!hasAlpha); 2848432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 28582ed38078af4a2b643415a76e84f88754f804709Vikas Arora return true; 28682ed38078af4a2b643415a76e84f88754f804709Vikas Arora} 2878432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 2888c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arorabool SkWEBPImageDecoder::onBuildTileIndex(SkStream* stream, 2898c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora int *width, int *height) { 29022c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora int origWidth, origHeight, hasAlpha; 29122c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) { 2928c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return false; 2938c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora } 2948c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 2958c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora stream->rewind(); 2968c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora *width = origWidth; 2978c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora *height = origHeight; 2988c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 2998c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora this->inputStream = stream; 3008c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora this->origWidth = origWidth; 3018c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora this->origHeight = origHeight; 30222c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora this->hasAlpha = hasAlpha; 3038c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 3048c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return true; 3058c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora} 3068c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 30722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arorastatic bool isConfigCompatible(SkBitmap* bitmap) { 308943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin SkBitmap::Config config = bitmap->config(); 309943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin return config == SkBitmap::kARGB_4444_Config || 310943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin config == SkBitmap::kRGB_565_Config || 311943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin config == SkBitmap::kARGB_8888_Config; 312943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin} 313943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin 3148c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arorabool SkWEBPImageDecoder::onDecodeRegion(SkBitmap* decodedBitmap, 3158c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora SkIRect region) { 316943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin SkIRect rect = SkIRect::MakeWH(origWidth, origHeight); 3178c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 318943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin if (!rect.intersect(region)) { 319943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // If the requested region is entirely outsides the image, just 320943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // returns false 3218c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return false; 3228c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora } 3238c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 324943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin const int sampleSize = this->getSampleSize(); 325943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin SkScaledBitmapSampler sampler(rect.width(), rect.height(), sampleSize); 326943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin const int width = sampler.scaledWidth(); 327943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin const int height = sampler.scaledHeight(); 328943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin 329943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // The image can be decoded directly to decodedBitmap if 330943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // 1. the region is within the image range 331943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // 2. bitmap's config is compatible 332943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // 3. bitmap's size is same as the required region (after sampled) 333943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin bool directDecode = (rect == region) && 334943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin (decodedBitmap->isNull() || 33522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora (isConfigCompatible(decodedBitmap) && 336943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin (decodedBitmap->width() == width) && 33722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora (decodedBitmap->height() == height))); 338943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin SkTScopedPtr<SkBitmap> adb; 339943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin SkBitmap *bitmap = decodedBitmap; 340943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin 341943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin if (!directDecode) { 342943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // allocates a temp bitmap 343943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin bitmap = new SkBitmap; 344943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin adb.reset(bitmap); 3458c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora } 3468c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 347943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin if (bitmap->isNull()) { 348943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin if (!setDecodeConfig(bitmap, width, height)) { 349943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin return false; 350943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin } 351943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // alloc from native heap if it is a temp bitmap. (prevent GC) 352943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin bool allocResult = (bitmap == decodedBitmap) 353943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin ? allocPixelRef(bitmap, NULL) 354943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin : bitmap->allocPixels(); 355943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin if (!allocResult) { 356943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin return return_false(*decodedBitmap, "allocPixelRef"); 357943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin } 358943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin } else { 359943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // This is also called in setDecodeConfig in above block. 360943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin // i.e., when bitmap->isNull() is true. 361943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin if (!chooseFromOneChoice(bitmap->config(), width, height)) { 362943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin return false; 363943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin } 364943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin } 3658c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 366943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin SkAutoLockPixels alp(*bitmap); 3678c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora WebPDecoderConfig config; 3684981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora if (!webp_get_config_resize_crop(config, bitmap, rect, hasAlpha)) { 3698c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return false; 3708c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora } 3718c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 3728c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora // Decode the WebP image data stream using WebP incremental decoding for 3738c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora // the specified cropped image-region. 374943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin if (!webp_idecode(this->inputStream, config)) { 375943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin return false; 376943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin } 377943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin 378943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin if (!directDecode) { 379943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin cropBitmap(decodedBitmap, bitmap, sampleSize, region.x(), region.y(), 380943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin region.width(), region.height(), rect.x(), rect.y()); 381943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin } 382943e1fde4c6ecf0eb8998cd86012caa341a02ccfOwen Lin return true; 3838c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora} 3848c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 38582ed38078af4a2b643415a76e84f88754f804709Vikas Arorabool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap, 38682ed38078af4a2b643415a76e84f88754f804709Vikas Arora Mode mode) { 38782ed38078af4a2b643415a76e84f88754f804709Vikas Arora#ifdef TIME_DECODE 38882ed38078af4a2b643415a76e84f88754f804709Vikas Arora AutoTimeMillis atm("WEBP Decode"); 3898432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#endif 39082ed38078af4a2b643415a76e84f88754f804709Vikas Arora 39122c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora int origWidth, origHeight, hasAlpha; 39222c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) { 3938432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold return false; 3948432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 39522c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora this->hasAlpha = hasAlpha; 3968432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 397c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora const int sampleSize = this->getSampleSize(); 398c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); 399c5013e3870ecf5a7798c1857a3060d880a7bf2c3Vikas Arora 40082ed38078af4a2b643415a76e84f88754f804709Vikas Arora // If only bounds are requested, done 40182ed38078af4a2b643415a76e84f88754f804709Vikas Arora if (SkImageDecoder::kDecodeBounds_Mode == mode) { 402c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(), 403c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase sampler.scaledHeight())) { 404c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase return false; 405c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase } 40682ed38078af4a2b643415a76e84f88754f804709Vikas Arora return true; 40782ed38078af4a2b643415a76e84f88754f804709Vikas Arora } 408c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase#ifdef SK_BUILD_FOR_ANDROID 409c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase // No Bitmap reuse supported for this format 410c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase if (!decodedBitmap->isNull()) { 411c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase return false; 412c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase } 413c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase#endif 414c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(), 415c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase sampler.scaledHeight())) { 416c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase return false; 417c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77Chet Haase } 4188432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 41982ed38078af4a2b643415a76e84f88754f804709Vikas Arora if (!this->allocPixelRef(decodedBitmap, NULL)) { 42082ed38078af4a2b643415a76e84f88754f804709Vikas Arora return return_false(*decodedBitmap, "allocPixelRef"); 4218432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 4228432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 4238c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora SkAutoLockPixels alp(*decodedBitmap); 4248c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora 4258c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora WebPDecoderConfig config; 4264981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora if (!webp_get_config_resize(config, decodedBitmap, origWidth, origHeight, 4274981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora hasAlpha)) { 4288432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold return false; 4298432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 4308432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 4318c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora // Decode the WebP image data stream using WebP incremental decoding. 4328c52c218e8b00b33f837ac4891fcde3a08817169Vikas Arora return webp_idecode(stream, config); 4338432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold} 4348432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 4358432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold/////////////////////////////////////////////////////////////////////////////// 4368432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 437a059123d8eb75302b13a7fd831478413d124d618Vikas Aroratypedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width, 438a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkPMColor* SK_RESTRICT ctable); 439a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 440a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width, 441a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkPMColor*) { 442a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const uint32_t* SK_RESTRICT src = (const uint32_t*)in; 443a059123d8eb75302b13a7fd831478413d124d618Vikas Arora for (int i = 0; i < width; ++i) { 444a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const uint32_t c = *src++; 445a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[0] = SkGetPackedR32(c); 446a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[1] = SkGetPackedG32(c); 447a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[2] = SkGetPackedB32(c); 448a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb += 3; 449a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 450a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 451a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 452a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width, 453a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkPMColor*) { 454a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const uint16_t* SK_RESTRICT src = (const uint16_t*)in; 455a059123d8eb75302b13a7fd831478413d124d618Vikas Arora for (int i = 0; i < width; ++i) { 456a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const uint16_t c = *src++; 457a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[0] = SkPacked16ToR32(c); 458a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[1] = SkPacked16ToG32(c); 459a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[2] = SkPacked16ToB32(c); 460a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb += 3; 461a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 462a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 463a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 464a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width, 465a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkPMColor*) { 466a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; 467a059123d8eb75302b13a7fd831478413d124d618Vikas Arora for (int i = 0; i < width; ++i) { 468a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkPMColor16 c = *src++; 469a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[0] = SkPacked4444ToR32(c); 470a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[1] = SkPacked4444ToG32(c); 471a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[2] = SkPacked4444ToB32(c); 472a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb += 3; 473a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 474a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 475a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 476a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width, 477a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkPMColor* SK_RESTRICT ctable) { 478a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const uint8_t* SK_RESTRICT src = (const uint8_t*)in; 479a059123d8eb75302b13a7fd831478413d124d618Vikas Arora for (int i = 0; i < width; ++i) { 480a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const uint32_t c = ctable[*src++]; 481a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[0] = SkGetPackedR32(c); 482a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[1] = SkGetPackedG32(c); 483a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb[2] = SkGetPackedB32(c); 484a059123d8eb75302b13a7fd831478413d124d618Vikas Arora rgb += 3; 485a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 486a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 487a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 488a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic ScanlineImporter ChooseImporter(const SkBitmap::Config& config) { 489a059123d8eb75302b13a7fd831478413d124d618Vikas Arora switch (config) { 490a059123d8eb75302b13a7fd831478413d124d618Vikas Arora case SkBitmap::kARGB_8888_Config: 491a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return ARGB_8888_To_RGB; 492a059123d8eb75302b13a7fd831478413d124d618Vikas Arora case SkBitmap::kRGB_565_Config: 493a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return RGB_565_To_RGB; 494a059123d8eb75302b13a7fd831478413d124d618Vikas Arora case SkBitmap::kARGB_4444_Config: 495a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return ARGB_4444_To_RGB; 496a059123d8eb75302b13a7fd831478413d124d618Vikas Arora case SkBitmap::kIndex8_Config: 497a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return Index8_To_RGB; 498a059123d8eb75302b13a7fd831478413d124d618Vikas Arora default: 499a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return NULL; 500a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 501a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 502a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 503a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic int StreamWriter(const uint8_t* data, size_t data_size, 504a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const WebPPicture* const picture) { 505a059123d8eb75302b13a7fd831478413d124d618Vikas Arora SkWStream* const stream = (SkWStream*)picture->custom_ptr; 506a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return stream->write(data, data_size) ? 1 : 0; 507a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 508a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 509a059123d8eb75302b13a7fd831478413d124d618Vikas Aroraclass SkWEBPImageEncoder : public SkImageEncoder { 510a059123d8eb75302b13a7fd831478413d124d618Vikas Aroraprotected: 511a059123d8eb75302b13a7fd831478413d124d618Vikas Arora virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality); 512a059123d8eb75302b13a7fd831478413d124d618Vikas Arora}; 513a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 514a059123d8eb75302b13a7fd831478413d124d618Vikas Arorabool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, 515a059123d8eb75302b13a7fd831478413d124d618Vikas Arora int quality) { 516a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkBitmap::Config config = bm.getConfig(); 517a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const ScanlineImporter scanline_import = ChooseImporter(config); 518a059123d8eb75302b13a7fd831478413d124d618Vikas Arora if (NULL == scanline_import) { 519a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return false; 520a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 521a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 522a059123d8eb75302b13a7fd831478413d124d618Vikas Arora SkAutoLockPixels alp(bm); 523a059123d8eb75302b13a7fd831478413d124d618Vikas Arora SkAutoLockColors ctLocker; 524a059123d8eb75302b13a7fd831478413d124d618Vikas Arora if (NULL == bm.getPixels()) { 525a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return false; 526a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 527a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 528a059123d8eb75302b13a7fd831478413d124d618Vikas Arora WebPConfig webp_config; 529a059123d8eb75302b13a7fd831478413d124d618Vikas Arora if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, quality)) { 530a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return false; 531a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 532a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 533a059123d8eb75302b13a7fd831478413d124d618Vikas Arora WebPPicture pic; 534a059123d8eb75302b13a7fd831478413d124d618Vikas Arora WebPPictureInit(&pic); 535a059123d8eb75302b13a7fd831478413d124d618Vikas Arora pic.width = bm.width(); 536a059123d8eb75302b13a7fd831478413d124d618Vikas Arora pic.height = bm.height(); 537a059123d8eb75302b13a7fd831478413d124d618Vikas Arora pic.writer = StreamWriter; 538a059123d8eb75302b13a7fd831478413d124d618Vikas Arora pic.custom_ptr = (void*)stream; 539a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 540a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const SkPMColor* colors = ctLocker.lockColors(bm); 541a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const uint8_t* src = (uint8_t*)bm.getPixels(); 542a059123d8eb75302b13a7fd831478413d124d618Vikas Arora const int rgb_stride = pic.width * 3; 543a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 544a059123d8eb75302b13a7fd831478413d124d618Vikas Arora // Import (for each scanline) the bit-map image (in appropriate color-space) 545a059123d8eb75302b13a7fd831478413d124d618Vikas Arora // to RGB color space. 546a059123d8eb75302b13a7fd831478413d124d618Vikas Arora uint8_t* rgb = new uint8_t[rgb_stride * pic.height]; 547a059123d8eb75302b13a7fd831478413d124d618Vikas Arora for (int y = 0; y < pic.height; ++y) { 548a059123d8eb75302b13a7fd831478413d124d618Vikas Arora scanline_import(src + y * bm.rowBytes(), rgb + y * rgb_stride, 549a059123d8eb75302b13a7fd831478413d124d618Vikas Arora pic.width, colors); 550a059123d8eb75302b13a7fd831478413d124d618Vikas Arora } 551a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 552a059123d8eb75302b13a7fd831478413d124d618Vikas Arora bool ok = WebPPictureImportRGB(&pic, rgb, rgb_stride); 553a059123d8eb75302b13a7fd831478413d124d618Vikas Arora delete[] rgb; 554a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 555a059123d8eb75302b13a7fd831478413d124d618Vikas Arora ok = ok && WebPEncode(&webp_config, &pic); 556a059123d8eb75302b13a7fd831478413d124d618Vikas Arora WebPPictureFree(&pic); 557a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 558a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return ok; 559a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 560a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 561a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 562a059123d8eb75302b13a7fd831478413d124d618Vikas Arora/////////////////////////////////////////////////////////////////////////////// 563a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 5648432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold#include "SkTRegistry.h" 5658432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 5668432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassoldstatic SkImageDecoder* DFactory(SkStream* stream) { 56722c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora int width, height, hasAlpha; 56822c3eb1bb4ab1c58edb7b3dd159e5c1969136c51Vikas Arora if (!webp_parse_header(stream, &width, &height, &hasAlpha)) { 5694981d1421e31f4229bb3d00d8b6dc93f21b03871Vikas Arora return NULL; 5708432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold } 5718432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 5728432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold // Magic matches, call decoder 5738432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold return SkNEW(SkWEBPImageDecoder); 5748432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold} 5758432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 5768432fc7b32e4de877bb86b38c050b944bed53f14Eric HassoldSkImageDecoder* sk_libwebp_dfactory(SkStream* stream) { 5778432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold return DFactory(stream); 5788432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold} 5798432fc7b32e4de877bb86b38c050b944bed53f14Eric Hassold 580a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic SkImageEncoder* EFactory(SkImageEncoder::Type t) { 581a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NULL; 582a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 583a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 584a059123d8eb75302b13a7fd831478413d124d618Vikas AroraSkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) { 585a059123d8eb75302b13a7fd831478413d124d618Vikas Arora return EFactory(t); 586a059123d8eb75302b13a7fd831478413d124d618Vikas Arora} 587a059123d8eb75302b13a7fd831478413d124d618Vikas Arora 588a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libwebp_dfactory); 589a059123d8eb75302b13a7fd831478413d124d618Vikas Arorastatic SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libwebp_efactory); 590