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