OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010, The Android Open Source Project | 2 * Copyright 2010, The Android Open Source Project |
3 * | 3 * |
4 * Licensed under the Apache License, Version 2.0 (the "License"); | 4 * Licensed under the Apache License, Version 2.0 (the "License"); |
5 * you may not use this file except in compliance with 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 | 6 * You may obtain a copy of the License at |
7 * | 7 * |
8 * http://www.apache.org/licenses/LICENSE-2.0 | 8 * http://www.apache.org/licenses/LICENSE-2.0 |
9 * | 9 * |
10 * Unless required by applicable law or agreed to in writing, software | 10 * Unless required by applicable law or agreed to in writing, software |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 fOrigWidth = 0; | 96 fOrigWidth = 0; |
97 fOrigHeight = 0; | 97 fOrigHeight = 0; |
98 fHasAlpha = 0; | 98 fHasAlpha = 0; |
99 } | 99 } |
100 | 100 |
101 Format getFormat() const override { | 101 Format getFormat() const override { |
102 return kWEBP_Format; | 102 return kWEBP_Format; |
103 } | 103 } |
104 | 104 |
105 protected: | 105 protected: |
106 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) o
verride; | |
107 bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) override; | |
108 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override; | 106 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override; |
109 | 107 |
110 private: | 108 private: |
111 /** | 109 /** |
112 * Called when determining the output config to request to webp. | 110 * Called when determining the output config to request to webp. |
113 * If the image does not have alpha, there is no need to premultiply. | 111 * If the image does not have alpha, there is no need to premultiply. |
114 * If the caller wants unpremultiplied colors, that is respected. | 112 * If the caller wants unpremultiplied colors, that is respected. |
115 */ | 113 */ |
116 bool shouldPremultiply() const { | 114 bool shouldPremultiply() const { |
117 return SkToBool(fHasAlpha) && !this->getRequireUnpremultipliedColors(); | 115 return SkToBool(fHasAlpha) && !this->getRequireUnpremultipliedColors(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 #endif | 151 #endif |
154 | 152 |
155 /////////////////////////////////////////////////////////////////////////////// | 153 /////////////////////////////////////////////////////////////////////////////// |
156 | 154 |
157 // This guy exists just to aid in debugging, as it allows debuggers to just | 155 // This guy exists just to aid in debugging, as it allows debuggers to just |
158 // set a break-point in one place to see all error exists. | 156 // set a break-point in one place to see all error exists. |
159 static void print_webp_error(const SkBitmap& bm, const char msg[]) { | 157 static void print_webp_error(const SkBitmap& bm, const char msg[]) { |
160 SkDEBUGF(("libwebp error %s [%d %d]", msg, bm.width(), bm.height())); | 158 SkDEBUGF(("libwebp error %s [%d %d]", msg, bm.width(), bm.height())); |
161 } | 159 } |
162 | 160 |
163 static bool return_false(const SkBitmap& bm, const char msg[]) { | |
164 print_webp_error(bm, msg); | |
165 return false; // must always return false | |
166 } | |
167 | |
168 static SkImageDecoder::Result return_failure(const SkBitmap& bm, const char msg[
]) { | 161 static SkImageDecoder::Result return_failure(const SkBitmap& bm, const char msg[
]) { |
169 print_webp_error(bm, msg); | 162 print_webp_error(bm, msg); |
170 return SkImageDecoder::kFailure; // must always return kFailure | 163 return SkImageDecoder::kFailure; // must always return kFailure |
171 } | 164 } |
172 | 165 |
173 /////////////////////////////////////////////////////////////////////////////// | 166 /////////////////////////////////////////////////////////////////////////////// |
174 | 167 |
175 static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, bool premul
tiply) { | 168 static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, bool premul
tiply) { |
176 WEBP_CSP_MODE mode = MODE_LAST; | 169 WEBP_CSP_MODE mode = MODE_LAST; |
177 const SkColorType ct = decodedBitmap->colorType(); | 170 const SkColorType ct = decodedBitmap->colorType(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 | 251 |
259 if (width != decodedBitmap->width() || height != decodedBitmap->height()) { | 252 if (width != decodedBitmap->width() || height != decodedBitmap->height()) { |
260 config->options.use_scaling = 1; | 253 config->options.use_scaling = 1; |
261 config->options.scaled_width = decodedBitmap->width(); | 254 config->options.scaled_width = decodedBitmap->width(); |
262 config->options.scaled_height = decodedBitmap->height(); | 255 config->options.scaled_height = decodedBitmap->height(); |
263 } | 256 } |
264 | 257 |
265 return true; | 258 return true; |
266 } | 259 } |
267 | 260 |
268 static bool webp_get_config_resize_crop(WebPDecoderConfig* config, | |
269 SkBitmap* decodedBitmap, | |
270 const SkIRect& region, bool premultiply)
{ | |
271 | |
272 if (!webp_get_config_resize(config, decodedBitmap, region.width(), | |
273 region.height(), premultiply)) { | |
274 return false; | |
275 } | |
276 | |
277 config->options.use_cropping = 1; | |
278 config->options.crop_left = region.fLeft; | |
279 config->options.crop_top = region.fTop; | |
280 config->options.crop_width = region.width(); | |
281 config->options.crop_height = region.height(); | |
282 | |
283 return true; | |
284 } | |
285 | |
286 bool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap, int width, int
height) { | 261 bool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap, int width, int
height) { |
287 SkColorType colorType = this->getPrefColorType(k32Bit_SrcDepth, SkToBool(fHa
sAlpha)); | 262 SkColorType colorType = this->getPrefColorType(k32Bit_SrcDepth, SkToBool(fHa
sAlpha)); |
288 | 263 |
289 // YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats. | 264 // YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats. |
290 if (fHasAlpha) { | 265 if (fHasAlpha) { |
291 if (colorType != kARGB_4444_SkColorType) { | 266 if (colorType != kARGB_4444_SkColorType) { |
292 colorType = kN32_SkColorType; | 267 colorType = kN32_SkColorType; |
293 } | 268 } |
294 } else { | 269 } else { |
295 if (colorType != kRGB_565_SkColorType && colorType != kARGB_4444_SkColor
Type) { | 270 if (colorType != kRGB_565_SkColorType && colorType != kARGB_4444_SkColor
Type) { |
296 colorType = kN32_SkColorType; | 271 colorType = kN32_SkColorType; |
297 } | 272 } |
298 } | 273 } |
299 | 274 |
300 SkAlphaType alphaType = kOpaque_SkAlphaType; | 275 SkAlphaType alphaType = kOpaque_SkAlphaType; |
301 if (SkToBool(fHasAlpha)) { | 276 if (SkToBool(fHasAlpha)) { |
302 if (this->getRequireUnpremultipliedColors()) { | 277 if (this->getRequireUnpremultipliedColors()) { |
303 alphaType = kUnpremul_SkAlphaType; | 278 alphaType = kUnpremul_SkAlphaType; |
304 } else { | 279 } else { |
305 alphaType = kPremul_SkAlphaType; | 280 alphaType = kPremul_SkAlphaType; |
306 } | 281 } |
307 } | 282 } |
308 return decodedBitmap->setInfo(SkImageInfo::Make(width, height, colorType, al
phaType)); | 283 return decodedBitmap->setInfo(SkImageInfo::Make(width, height, colorType, al
phaType)); |
309 } | 284 } |
310 | 285 |
311 bool SkWEBPImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, | |
312 int *width, int *height) { | |
313 SkAutoTDelete<SkStreamRewindable> streamDeleter(stream); | |
314 int origWidth, origHeight, hasAlpha; | |
315 if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) { | |
316 return false; | |
317 } | |
318 | |
319 if (!stream->rewind()) { | |
320 SkDebugf("Failed to rewind webp stream!"); | |
321 return false; | |
322 } | |
323 | |
324 *width = origWidth; | |
325 *height = origHeight; | |
326 | |
327 this->fInputStream.reset(streamDeleter.detach()); | |
328 this->fOrigWidth = origWidth; | |
329 this->fOrigHeight = origHeight; | |
330 this->fHasAlpha = hasAlpha; | |
331 | |
332 return true; | |
333 } | |
334 | |
335 static bool is_config_compatible(const SkBitmap& bitmap) { | |
336 const SkColorType ct = bitmap.colorType(); | |
337 return ct == kARGB_4444_SkColorType || ct == kRGB_565_SkColorType || ct == k
N32_SkColorType; | |
338 } | |
339 | |
340 bool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap, | |
341 const SkIRect& region) { | |
342 SkIRect rect = SkIRect::MakeWH(fOrigWidth, fOrigHeight); | |
343 | |
344 if (!rect.intersect(region)) { | |
345 // If the requested region is entirely outsides the image, return false | |
346 return false; | |
347 } | |
348 | |
349 const int sampleSize = this->getSampleSize(); | |
350 SkScaledBitmapSampler sampler(rect.width(), rect.height(), sampleSize); | |
351 const int width = sampler.scaledWidth(); | |
352 const int height = sampler.scaledHeight(); | |
353 | |
354 // The image can be decoded directly to decodedBitmap if | |
355 // 1. the region is within the image range | |
356 // 2. bitmap's config is compatible | |
357 // 3. bitmap's size is same as the required region (after sampled) | |
358 bool directDecode = (rect == region) && | |
359 (decodedBitmap->isNull() || | |
360 (is_config_compatible(*decodedBitmap) && | |
361 (decodedBitmap->width() == width) && | |
362 (decodedBitmap->height() == height))); | |
363 | |
364 SkBitmap tmpBitmap; | |
365 SkBitmap *bitmap = decodedBitmap; | |
366 | |
367 if (!directDecode) { | |
368 bitmap = &tmpBitmap; | |
369 } | |
370 | |
371 if (bitmap->isNull()) { | |
372 if (!setDecodeConfig(bitmap, width, height)) { | |
373 return false; | |
374 } | |
375 // alloc from native heap if it is a temp bitmap. (prevent GC) | |
376 bool allocResult = (bitmap == decodedBitmap) | |
377 ? allocPixelRef(bitmap, nullptr) | |
378 : bitmap->tryAllocPixels(); | |
379 if (!allocResult) { | |
380 return return_false(*decodedBitmap, "allocPixelRef"); | |
381 } | |
382 } | |
383 | |
384 SkAutoLockPixels alp(*bitmap); | |
385 WebPDecoderConfig config; | |
386 if (!webp_get_config_resize_crop(&config, bitmap, rect, | |
387 this->shouldPremultiply())) { | |
388 return false; | |
389 } | |
390 | |
391 // Decode the WebP image data stream using WebP incremental decoding for | |
392 // the specified cropped image-region. | |
393 if (!webp_idecode(this->fInputStream, &config)) { | |
394 return false; | |
395 } | |
396 | |
397 if (!directDecode) { | |
398 return cropBitmap(decodedBitmap, bitmap, sampleSize, region.x(), region.
y(), | |
399 region.width(), region.height(), rect.x(), rect.y()); | |
400 } | |
401 return true; | |
402 } | |
403 | |
404 SkImageDecoder::Result SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap*
decodedBitmap, | 286 SkImageDecoder::Result SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap*
decodedBitmap, |
405 Mode mode) { | 287 Mode mode) { |
406 #ifdef TIME_DECODE | 288 #ifdef TIME_DECODE |
407 AutoTimeMillis atm("WEBP Decode"); | 289 AutoTimeMillis atm("WEBP Decode"); |
408 #endif | 290 #endif |
409 | 291 |
410 int origWidth, origHeight, hasAlpha; | 292 int origWidth, origHeight, hasAlpha; |
411 if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) { | 293 if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) { |
412 return kFailure; | 294 return kFailure; |
413 } | 295 } |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 return SkImageDecoder::kUnknown_Format; | 550 return SkImageDecoder::kUnknown_Format; |
669 } | 551 } |
670 | 552 |
671 static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) { | 553 static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) { |
672 return (SkImageEncoder::kWEBP_Type == t) ? new SkWEBPImageEncoder : nullptr; | 554 return (SkImageEncoder::kWEBP_Type == t) ? new SkWEBPImageEncoder : nullptr; |
673 } | 555 } |
674 | 556 |
675 static SkImageDecoder_DecodeReg gDReg(sk_libwebp_dfactory); | 557 static SkImageDecoder_DecodeReg gDReg(sk_libwebp_dfactory); |
676 static SkImageDecoder_FormatReg gFormatReg(get_format_webp); | 558 static SkImageDecoder_FormatReg gFormatReg(get_format_webp); |
677 static SkImageEncoder_EncodeReg gEReg(sk_libwebp_efactory); | 559 static SkImageEncoder_EncodeReg gEReg(sk_libwebp_efactory); |
OLD | NEW |