| 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 |