- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / images / SkImageDecoder_libwebp.cpp
1 /*
2  * Copyright 2010, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "SkImageDecoder.h"
18 #include "SkImageEncoder.h"
19 #include "SkColorPriv.h"
20 #include "SkScaledBitmapSampler.h"
21 #include "SkStream.h"
22 #include "SkTemplates.h"
23 #include "SkUtils.h"
24
25 // A WebP decoder only, on top of (subset of) libwebp
26 // For more information on WebP image format, and libwebp library, see:
27 //   http://code.google.com/speed/webp/
28 //   http://www.webmproject.org/code/#libwebp_webp_image_decoder_library
29 //   http://review.webmproject.org/gitweb?p=libwebp.git
30
31 #include <stdio.h>
32 extern "C" {
33 // If moving libwebp out of skia source tree, path for webp headers must be
34 // updated accordingly. Here, we enforce using local copy in webp sub-directory.
35 #include "webp/decode.h"
36 #include "webp/encode.h"
37 }
38
39 // this enables timing code to report milliseconds for a decode
40 //#define TIME_DECODE
41
42 //////////////////////////////////////////////////////////////////////////
43 //////////////////////////////////////////////////////////////////////////
44
45 // Define VP8 I/O on top of Skia stream
46
47 //////////////////////////////////////////////////////////////////////////
48 //////////////////////////////////////////////////////////////////////////
49
50 static const size_t WEBP_VP8_HEADER_SIZE = 64;
51 static const size_t WEBP_IDECODE_BUFFER_SZ = (1 << 16);
52
53 // Parse headers of RIFF container, and check for valid Webp (VP8) content.
54 static bool webp_parse_header(SkStream* stream, int* width, int* height, int* alpha) {
55     unsigned char buffer[WEBP_VP8_HEADER_SIZE];
56     size_t bytesToRead = WEBP_VP8_HEADER_SIZE;
57     size_t totalBytesRead = 0;
58     do {
59         unsigned char* dst = buffer + totalBytesRead;
60         const size_t bytesRead = stream->read(dst, bytesToRead);
61         if (0 == bytesRead) {
62             // Could not read any bytes. Check to see if we are at the end (exit
63             // condition), and continue reading if not. Important for streams
64             // that do not have all the data ready.
65             continue;
66         }
67         bytesToRead -= bytesRead;
68         totalBytesRead += bytesRead;
69         SkASSERT(bytesToRead + totalBytesRead == WEBP_VP8_HEADER_SIZE);
70     } while (!stream->isAtEnd() && bytesToRead > 0);
71
72     WebPBitstreamFeatures features;
73     VP8StatusCode status = WebPGetFeatures(buffer, totalBytesRead, &features);
74     if (VP8_STATUS_OK != status) {
75         return false; // Invalid WebP file.
76     }
77     *width = features.width;
78     *height = features.height;
79     *alpha = features.has_alpha;
80
81     // sanity check for image size that's about to be decoded.
82     {
83         Sk64 size;
84         size.setMul(*width, *height);
85         if (size.isNeg() || !size.is32()) {
86             return false;
87         }
88         // now check that if we are 4-bytes per pixel, we also don't overflow
89         if (size.get32() > (0x7FFFFFFF >> 2)) {
90             return false;
91         }
92     }
93     return true;
94 }
95
96 class SkWEBPImageDecoder: public SkImageDecoder {
97 public:
98     SkWEBPImageDecoder() {
99         fInputStream = NULL;
100         fOrigWidth = 0;
101         fOrigHeight = 0;
102         fHasAlpha = 0;
103     }
104     virtual ~SkWEBPImageDecoder() {
105         SkSafeUnref(fInputStream);
106     }
107
108     virtual Format getFormat() const SK_OVERRIDE {
109         return kWEBP_Format;
110     }
111
112 protected:
113     virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
114     virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
115     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
116
117 private:
118     /**
119      *  Called when determining the output config to request to webp.
120      *  If the image does not have alpha, there is no need to premultiply.
121      *  If the caller wants unpremultiplied colors, that is respected.
122      */
123     bool shouldPremultiply() const {
124         return SkToBool(fHasAlpha) && !this->getRequireUnpremultipliedColors();
125     }
126
127     bool setDecodeConfig(SkBitmap* decodedBitmap, int width, int height);
128
129     SkStream* fInputStream;
130     int fOrigWidth;
131     int fOrigHeight;
132     int fHasAlpha;
133
134     typedef SkImageDecoder INHERITED;
135 };
136
137 //////////////////////////////////////////////////////////////////////////
138
139 #ifdef TIME_DECODE
140
141 #include "SkTime.h"
142
143 class AutoTimeMillis {
144 public:
145     AutoTimeMillis(const char label[]) :
146         fLabel(label) {
147         if (NULL == fLabel) {
148             fLabel = "";
149         }
150         fNow = SkTime::GetMSecs();
151     }
152     ~AutoTimeMillis() {
153         SkDebugf("---- Time (ms): %s %d\n", fLabel, SkTime::GetMSecs() - fNow);
154     }
155 private:
156     const char* fLabel;
157     SkMSec fNow;
158 };
159
160 #endif
161
162 ///////////////////////////////////////////////////////////////////////////////
163
164 // This guy exists just to aid in debugging, as it allows debuggers to just
165 // set a break-point in one place to see all error exists.
166 static bool return_false(const SkBitmap& bm, const char msg[]) {
167     SkDEBUGF(("libwebp error %s [%d %d]", msg, bm.width(), bm.height()));
168     return false; // must always return false
169 }
170
171 static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, bool premultiply) {
172     WEBP_CSP_MODE mode = MODE_LAST;
173     SkBitmap::Config config = decodedBitmap->config();
174
175     if (config == SkBitmap::kARGB_8888_Config) {
176         mode = premultiply ? MODE_rgbA : MODE_RGBA;
177     } else if (config == SkBitmap::kARGB_4444_Config) {
178         mode = premultiply ? MODE_rgbA_4444 : MODE_RGBA_4444;
179     } else if (config == SkBitmap::kRGB_565_Config) {
180         mode = MODE_RGB_565;
181     }
182     SkASSERT(MODE_LAST != mode);
183     return mode;
184 }
185
186 // Incremental WebP image decoding. Reads input buffer of 64K size iteratively
187 // and decodes this block to appropriate color-space as per config object.
188 static bool webp_idecode(SkStream* stream, WebPDecoderConfig* config) {
189     WebPIDecoder* idec = WebPIDecode(NULL, 0, config);
190     if (NULL == idec) {
191         WebPFreeDecBuffer(&config->output);
192         return false;
193     }
194
195     if (!stream->rewind()) {
196         SkDebugf("Failed to rewind webp stream!");
197         return false;
198     }
199     const size_t readBufferSize = stream->hasLength() ?
200             SkTMin(stream->getLength(), WEBP_IDECODE_BUFFER_SZ) : WEBP_IDECODE_BUFFER_SZ;
201     SkAutoMalloc srcStorage(readBufferSize);
202     unsigned char* input = (uint8_t*)srcStorage.get();
203     if (NULL == input) {
204         WebPIDelete(idec);
205         WebPFreeDecBuffer(&config->output);
206         return false;
207     }
208
209     bool success = true;
210     VP8StatusCode status = VP8_STATUS_SUSPENDED;
211     do {
212         const size_t bytesRead = stream->read(input, readBufferSize);
213         if (0 == bytesRead) {
214             success = false;
215             break;
216         }
217
218         status = WebPIAppend(idec, input, bytesRead);
219         if (VP8_STATUS_OK != status && VP8_STATUS_SUSPENDED != status) {
220             success = false;
221             break;
222         }
223     } while (VP8_STATUS_OK != status);
224     srcStorage.free();
225     WebPIDelete(idec);
226     WebPFreeDecBuffer(&config->output);
227
228     return success;
229 }
230
231 static bool webp_get_config_resize(WebPDecoderConfig* config,
232                                    SkBitmap* decodedBitmap,
233                                    int width, int height, bool premultiply) {
234     WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap, premultiply);
235     if (MODE_LAST == mode) {
236         return false;
237     }
238
239     if (0 == WebPInitDecoderConfig(config)) {
240         return false;
241     }
242
243     config->output.colorspace = mode;
244     config->output.u.RGBA.rgba = (uint8_t*)decodedBitmap->getPixels();
245     config->output.u.RGBA.stride = (int) decodedBitmap->rowBytes();
246     config->output.u.RGBA.size = decodedBitmap->getSize();
247     config->output.is_external_memory = 1;
248
249     if (width != decodedBitmap->width() || height != decodedBitmap->height()) {
250         config->options.use_scaling = 1;
251         config->options.scaled_width = decodedBitmap->width();
252         config->options.scaled_height = decodedBitmap->height();
253     }
254
255     return true;
256 }
257
258 static bool webp_get_config_resize_crop(WebPDecoderConfig* config,
259                                         SkBitmap* decodedBitmap,
260                                         const SkIRect& region, bool premultiply) {
261
262     if (!webp_get_config_resize(config, decodedBitmap, region.width(),
263                                 region.height(), premultiply)) {
264       return false;
265     }
266
267     config->options.use_cropping = 1;
268     config->options.crop_left = region.fLeft;
269     config->options.crop_top = region.fTop;
270     config->options.crop_width = region.width();
271     config->options.crop_height = region.height();
272
273     return true;
274 }
275
276 bool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap,
277                                          int width, int height) {
278     SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, SkToBool(fHasAlpha));
279
280     // YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats.
281     if (fHasAlpha) {
282         if (config != SkBitmap::kARGB_4444_Config) {
283             config = SkBitmap::kARGB_8888_Config;
284         }
285     } else {
286         if (config != SkBitmap::kRGB_565_Config &&
287             config != SkBitmap::kARGB_4444_Config) {
288             config = SkBitmap::kARGB_8888_Config;
289         }
290     }
291
292     if (!this->chooseFromOneChoice(config, width, height)) {
293         return false;
294     }
295
296     return decodedBitmap->setConfig(config, width, height, 0,
297                                     fHasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType);
298 }
299
300 bool SkWEBPImageDecoder::onBuildTileIndex(SkStreamRewindable* stream,
301                                           int *width, int *height) {
302     int origWidth, origHeight, hasAlpha;
303     if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
304         return false;
305     }
306
307     if (!stream->rewind()) {
308         SkDebugf("Failed to rewind webp stream!");
309         return false;
310     }
311
312     *width = origWidth;
313     *height = origHeight;
314
315     SkRefCnt_SafeAssign(this->fInputStream, stream);
316     this->fOrigWidth = origWidth;
317     this->fOrigHeight = origHeight;
318     this->fHasAlpha = hasAlpha;
319
320     return true;
321 }
322
323 static bool is_config_compatible(const SkBitmap& bitmap) {
324     SkBitmap::Config config = bitmap.config();
325     return config == SkBitmap::kARGB_4444_Config ||
326            config == SkBitmap::kRGB_565_Config ||
327            config == SkBitmap::kARGB_8888_Config;
328 }
329
330 bool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap,
331                                         const SkIRect& region) {
332     SkIRect rect = SkIRect::MakeWH(fOrigWidth, fOrigHeight);
333
334     if (!rect.intersect(region)) {
335         // If the requested region is entirely outsides the image, return false
336         return false;
337     }
338
339     const int sampleSize = this->getSampleSize();
340     SkScaledBitmapSampler sampler(rect.width(), rect.height(), sampleSize);
341     const int width = sampler.scaledWidth();
342     const int height = sampler.scaledHeight();
343
344     // The image can be decoded directly to decodedBitmap if
345     //   1. the region is within the image range
346     //   2. bitmap's config is compatible
347     //   3. bitmap's size is same as the required region (after sampled)
348     bool directDecode = (rect == region) &&
349                         (decodedBitmap->isNull() ||
350                          (is_config_compatible(*decodedBitmap) &&
351                          (decodedBitmap->width() == width) &&
352                          (decodedBitmap->height() == height)));
353
354     SkBitmap tmpBitmap;
355     SkBitmap *bitmap = decodedBitmap;
356
357     if (!directDecode) {
358         bitmap = &tmpBitmap;
359     }
360
361     if (bitmap->isNull()) {
362         if (!setDecodeConfig(bitmap, width, height)) {
363             return false;
364         }
365         // alloc from native heap if it is a temp bitmap. (prevent GC)
366         bool allocResult = (bitmap == decodedBitmap)
367                                ? allocPixelRef(bitmap, NULL)
368                                : bitmap->allocPixels();
369         if (!allocResult) {
370             return return_false(*decodedBitmap, "allocPixelRef");
371         }
372     } else {
373         // This is also called in setDecodeConfig in above block.
374         // i.e., when bitmap->isNull() is true.
375         if (!chooseFromOneChoice(bitmap->config(), width, height)) {
376             return false;
377         }
378     }
379
380     SkAutoLockPixels alp(*bitmap);
381     WebPDecoderConfig config;
382     if (!webp_get_config_resize_crop(&config, bitmap, rect,
383                                      this->shouldPremultiply())) {
384         return false;
385     }
386
387     // Decode the WebP image data stream using WebP incremental decoding for
388     // the specified cropped image-region.
389     if (!webp_idecode(this->fInputStream, &config)) {
390         return false;
391     }
392
393     if (!directDecode) {
394         cropBitmap(decodedBitmap, bitmap, sampleSize, region.x(), region.y(),
395                    region.width(), region.height(), rect.x(), rect.y());
396     }
397     return true;
398 }
399
400 bool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
401                                   Mode mode) {
402 #ifdef TIME_DECODE
403     AutoTimeMillis atm("WEBP Decode");
404 #endif
405
406     int origWidth, origHeight, hasAlpha;
407     if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
408         return false;
409     }
410     this->fHasAlpha = hasAlpha;
411
412     const int sampleSize = this->getSampleSize();
413     SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
414     if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(),
415                          sampler.scaledHeight())) {
416         return false;
417     }
418
419     // If only bounds are requested, done
420     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
421         return true;
422     }
423
424     if (!this->allocPixelRef(decodedBitmap, NULL)) {
425         return return_false(*decodedBitmap, "allocPixelRef");
426     }
427
428     SkAutoLockPixels alp(*decodedBitmap);
429
430     WebPDecoderConfig config;
431     if (!webp_get_config_resize(&config, decodedBitmap, origWidth, origHeight,
432                                 this->shouldPremultiply())) {
433         return false;
434     }
435
436     // Decode the WebP image data stream using WebP incremental decoding.
437     return webp_idecode(stream, &config);
438 }
439
440 ///////////////////////////////////////////////////////////////////////////////
441
442 typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width,
443                                  const SkPMColor* SK_RESTRICT ctable);
444
445 static void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
446                              const SkPMColor*) {
447   const uint32_t* SK_RESTRICT src = (const uint32_t*)in;
448   for (int i = 0; i < width; ++i) {
449       const uint32_t c = *src++;
450       rgb[0] = SkGetPackedR32(c);
451       rgb[1] = SkGetPackedG32(c);
452       rgb[2] = SkGetPackedB32(c);
453       rgb += 3;
454   }
455 }
456
457 static void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
458                            const SkPMColor*) {
459   const uint16_t* SK_RESTRICT src = (const uint16_t*)in;
460   for (int i = 0; i < width; ++i) {
461       const uint16_t c = *src++;
462       rgb[0] = SkPacked16ToR32(c);
463       rgb[1] = SkPacked16ToG32(c);
464       rgb[2] = SkPacked16ToB32(c);
465       rgb += 3;
466   }
467 }
468
469 static void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
470                              const SkPMColor*) {
471   const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in;
472   for (int i = 0; i < width; ++i) {
473       const SkPMColor16 c = *src++;
474       rgb[0] = SkPacked4444ToR32(c);
475       rgb[1] = SkPacked4444ToG32(c);
476       rgb[2] = SkPacked4444ToB32(c);
477       rgb += 3;
478   }
479 }
480
481 static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
482                           const SkPMColor* SK_RESTRICT ctable) {
483   const uint8_t* SK_RESTRICT src = (const uint8_t*)in;
484   for (int i = 0; i < width; ++i) {
485       const uint32_t c = ctable[*src++];
486       rgb[0] = SkGetPackedR32(c);
487       rgb[1] = SkGetPackedG32(c);
488       rgb[2] = SkGetPackedB32(c);
489       rgb += 3;
490   }
491 }
492
493 static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) {
494     switch (config) {
495         case SkBitmap::kARGB_8888_Config:
496             return ARGB_8888_To_RGB;
497         case SkBitmap::kRGB_565_Config:
498             return RGB_565_To_RGB;
499         case SkBitmap::kARGB_4444_Config:
500             return ARGB_4444_To_RGB;
501         case SkBitmap::kIndex8_Config:
502             return Index8_To_RGB;
503         default:
504             return NULL;
505     }
506 }
507
508 static int stream_writer(const uint8_t* data, size_t data_size,
509                          const WebPPicture* const picture) {
510   SkWStream* const stream = (SkWStream*)picture->custom_ptr;
511   return stream->write(data, data_size) ? 1 : 0;
512 }
513
514 class SkWEBPImageEncoder : public SkImageEncoder {
515 protected:
516     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK_OVERRIDE;
517
518 private:
519     typedef SkImageEncoder INHERITED;
520 };
521
522 bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm,
523                                   int quality) {
524     const SkBitmap::Config config = bm.config();
525     const ScanlineImporter scanline_import = ChooseImporter(config);
526     if (NULL == scanline_import) {
527         return false;
528     }
529
530     SkAutoLockPixels alp(bm);
531     SkAutoLockColors ctLocker;
532     if (NULL == bm.getPixels()) {
533         return false;
534     }
535
536     WebPConfig webp_config;
537     if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, (float) quality)) {
538         return false;
539     }
540
541     WebPPicture pic;
542     WebPPictureInit(&pic);
543     pic.width = bm.width();
544     pic.height = bm.height();
545     pic.writer = stream_writer;
546     pic.custom_ptr = (void*)stream;
547
548     const SkPMColor* colors = ctLocker.lockColors(bm);
549     const uint8_t* src = (uint8_t*)bm.getPixels();
550     const int rgbStride = pic.width * 3;
551
552     // Import (for each scanline) the bit-map image (in appropriate color-space)
553     // to RGB color space.
554     uint8_t* rgb = new uint8_t[rgbStride * pic.height];
555     for (int y = 0; y < pic.height; ++y) {
556         scanline_import(src + y * bm.rowBytes(), rgb + y * rgbStride,
557                         pic.width, colors);
558     }
559
560     bool ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride));
561     delete[] rgb;
562
563     ok = ok && WebPEncode(&webp_config, &pic);
564     WebPPictureFree(&pic);
565
566     return ok;
567 }
568
569
570 ///////////////////////////////////////////////////////////////////////////////
571 DEFINE_DECODER_CREATOR(WEBPImageDecoder);
572 DEFINE_ENCODER_CREATOR(WEBPImageEncoder);
573 ///////////////////////////////////////////////////////////////////////////////
574
575 static SkImageDecoder* sk_libwebp_dfactory(SkStreamRewindable* stream) {
576     int width, height, hasAlpha;
577     if (!webp_parse_header(stream, &width, &height, &hasAlpha)) {
578         return NULL;
579     }
580
581     // Magic matches, call decoder
582     return SkNEW(SkWEBPImageDecoder);
583 }
584
585 static SkImageDecoder::Format get_format_webp(SkStreamRewindable* stream) {
586     int width, height, hasAlpha;
587     if (webp_parse_header(stream, &width, &height, &hasAlpha)) {
588         return SkImageDecoder::kWEBP_Format;
589     }
590     return SkImageDecoder::kUnknown_Format;
591 }
592
593 static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) {
594       return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NULL;
595 }
596
597 static SkImageDecoder_DecodeReg gDReg(sk_libwebp_dfactory);
598 static SkImageDecoder_FormatReg gFormatReg(get_format_webp);
599 static SkImageEncoder_EncodeReg gEReg(sk_libwebp_efactory);