Chromium Code Reviews| 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 virtual Format getFormat() const SK_OVERRIDE { | 107 virtual Format getFormat() const SK_OVERRIDE { |
| 108 return kWEBP_Format; | 108 return kWEBP_Format; |
| 109 } | 109 } |
| 110 | 110 |
| 111 protected: | 111 protected: |
| 112 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_ OVERRIDE; | 112 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_ OVERRIDE; |
| 113 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI DE; | 113 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI DE; |
| 114 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 114 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
| 115 | 115 |
| 116 private: | 116 private: |
| 117 /** | |
| 118 * Called when determining the output config to request to webp. | |
| 119 * If the image does not have alpha, there is no need to premultiply. | |
| 120 * If the caller wants unpremultiplied colors, that is respected. | |
| 121 */ | |
| 122 bool shouldPremultiply() const { | |
| 123 return SkToBool(fHasAlpha) && !this->getRequireUnpremultipliedColors(); | |
| 124 } | |
| 125 | |
| 117 bool setDecodeConfig(SkBitmap* decodedBitmap, int width, int height); | 126 bool setDecodeConfig(SkBitmap* decodedBitmap, int width, int height); |
| 127 | |
| 118 SkStream* fInputStream; | 128 SkStream* fInputStream; |
| 119 int fOrigWidth; | 129 int fOrigWidth; |
| 120 int fOrigHeight; | 130 int fOrigHeight; |
| 121 int fHasAlpha; | 131 int fHasAlpha; |
| 122 | 132 |
| 123 typedef SkImageDecoder INHERITED; | 133 typedef SkImageDecoder INHERITED; |
| 124 }; | 134 }; |
| 125 | 135 |
| 126 ////////////////////////////////////////////////////////////////////////// | 136 ////////////////////////////////////////////////////////////////////////// |
| 127 | 137 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 150 | 160 |
| 151 /////////////////////////////////////////////////////////////////////////////// | 161 /////////////////////////////////////////////////////////////////////////////// |
| 152 | 162 |
| 153 // This guy exists just to aid in debugging, as it allows debuggers to just | 163 // This guy exists just to aid in debugging, as it allows debuggers to just |
| 154 // set a break-point in one place to see all error exists. | 164 // set a break-point in one place to see all error exists. |
| 155 static bool return_false(const SkBitmap& bm, const char msg[]) { | 165 static bool return_false(const SkBitmap& bm, const char msg[]) { |
| 156 SkDEBUGF(("libwebp error %s [%d %d]", msg, bm.width(), bm.height())); | 166 SkDEBUGF(("libwebp error %s [%d %d]", msg, bm.width(), bm.height())); |
| 157 return false; // must always return false | 167 return false; // must always return false |
| 158 } | 168 } |
| 159 | 169 |
| 160 static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, int hasAlph a) { | 170 static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, bool premul tiply) { |
| 161 WEBP_CSP_MODE mode = MODE_LAST; | 171 WEBP_CSP_MODE mode = MODE_LAST; |
| 162 SkBitmap::Config config = decodedBitmap->config(); | 172 SkBitmap::Config config = decodedBitmap->config(); |
| 163 // For images that have alpha, choose appropriate color mode (MODE_rgbA, | 173 |
| 164 // MODE_rgbA_4444) that pre-multiplies RGB pixel values with transparency | |
| 165 // factor (alpha). | |
| 166 if (config == SkBitmap::kARGB_8888_Config) { | 174 if (config == SkBitmap::kARGB_8888_Config) { |
| 167 mode = hasAlpha ? MODE_rgbA : MODE_RGBA; | 175 mode = premultiply ? MODE_rgbA : MODE_RGBA; |
| 168 } else if (config == SkBitmap::kARGB_4444_Config) { | 176 } else if (config == SkBitmap::kARGB_4444_Config) { |
| 169 mode = hasAlpha ? MODE_rgbA_4444 : MODE_RGBA_4444; | 177 mode = premultiply ? MODE_rgbA_4444 : MODE_RGBA_4444; |
| 170 } else if (config == SkBitmap::kRGB_565_Config) { | 178 } else if (config == SkBitmap::kRGB_565_Config) { |
| 171 mode = MODE_RGB_565; | 179 mode = MODE_RGB_565; |
| 172 } | 180 } |
| 173 SkASSERT(MODE_LAST != mode); | 181 SkASSERT(MODE_LAST != mode); |
| 174 return mode; | 182 return mode; |
| 175 } | 183 } |
| 176 | 184 |
| 177 // Incremental WebP image decoding. Reads input buffer of 64K size iteratively | 185 // Incremental WebP image decoding. Reads input buffer of 64K size iteratively |
| 178 // and decodes this block to appropriate color-space as per config object. | 186 // and decodes this block to appropriate color-space as per config object. |
| 179 static bool webp_idecode(SkStream* stream, WebPDecoderConfig* config) { | 187 static bool webp_idecode(SkStream* stream, WebPDecoderConfig* config) { |
| 180 WebPIDecoder* idec = WebPIDecode(NULL, 0, config); | 188 WebPIDecoder* idec = WebPIDecode(NULL, 0, config); |
| 181 if (NULL == idec) { | 189 if (NULL == idec) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 | 225 |
| 218 if (bytesRemaining > 0) { | 226 if (bytesRemaining > 0) { |
| 219 return false; | 227 return false; |
| 220 } else { | 228 } else { |
| 221 return true; | 229 return true; |
| 222 } | 230 } |
| 223 } | 231 } |
| 224 | 232 |
| 225 static bool webp_get_config_resize(WebPDecoderConfig* config, | 233 static bool webp_get_config_resize(WebPDecoderConfig* config, |
| 226 SkBitmap* decodedBitmap, | 234 SkBitmap* decodedBitmap, |
| 227 int width, int height, int hasAlpha) { | 235 int width, int height, bool premultiply) { |
| 228 WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap, hasAlpha); | 236 WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap, premultiply); |
| 229 if (MODE_LAST == mode) { | 237 if (MODE_LAST == mode) { |
| 230 return false; | 238 return false; |
| 231 } | 239 } |
| 232 | 240 |
| 233 if (0 == WebPInitDecoderConfig(config)) { | 241 if (0 == WebPInitDecoderConfig(config)) { |
| 234 return false; | 242 return false; |
| 235 } | 243 } |
| 236 | 244 |
| 237 config->output.colorspace = mode; | 245 config->output.colorspace = mode; |
| 238 config->output.u.RGBA.rgba = (uint8_t*)decodedBitmap->getPixels(); | 246 config->output.u.RGBA.rgba = (uint8_t*)decodedBitmap->getPixels(); |
| 239 config->output.u.RGBA.stride = decodedBitmap->rowBytes(); | 247 config->output.u.RGBA.stride = decodedBitmap->rowBytes(); |
| 240 config->output.u.RGBA.size = decodedBitmap->getSize(); | 248 config->output.u.RGBA.size = decodedBitmap->getSize(); |
| 241 config->output.is_external_memory = 1; | 249 config->output.is_external_memory = 1; |
| 242 | 250 |
| 243 if (width != decodedBitmap->width() || height != decodedBitmap->height()) { | 251 if (width != decodedBitmap->width() || height != decodedBitmap->height()) { |
| 244 config->options.use_scaling = 1; | 252 config->options.use_scaling = 1; |
| 245 config->options.scaled_width = decodedBitmap->width(); | 253 config->options.scaled_width = decodedBitmap->width(); |
| 246 config->options.scaled_height = decodedBitmap->height(); | 254 config->options.scaled_height = decodedBitmap->height(); |
| 247 } | 255 } |
| 248 | 256 |
| 249 return true; | 257 return true; |
| 250 } | 258 } |
| 251 | 259 |
| 252 static bool webp_get_config_resize_crop(WebPDecoderConfig* config, | 260 static bool webp_get_config_resize_crop(WebPDecoderConfig* config, |
| 253 SkBitmap* decodedBitmap, | 261 SkBitmap* decodedBitmap, |
| 254 const SkIRect& region, int hasAlpha) { | 262 const SkIRect& region, bool premultiply) { |
| 255 | 263 |
| 256 if (!webp_get_config_resize(config, decodedBitmap, region.width(), | 264 if (!webp_get_config_resize(config, decodedBitmap, region.width(), |
| 257 region.height(), hasAlpha)) { | 265 region.height(), premultiply)) { |
| 258 return false; | 266 return false; |
| 259 } | 267 } |
| 260 | 268 |
| 261 config->options.use_cropping = 1; | 269 config->options.use_cropping = 1; |
| 262 config->options.crop_left = region.fLeft; | 270 config->options.crop_left = region.fLeft; |
| 263 config->options.crop_top = region.fTop; | 271 config->options.crop_top = region.fTop; |
| 264 config->options.crop_width = region.width(); | 272 config->options.crop_width = region.width(); |
| 265 config->options.crop_height = region.height(); | 273 config->options.crop_height = region.height(); |
| 266 | 274 |
| 267 return true; | 275 return true; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 } else { | 373 } else { |
| 366 // This is also called in setDecodeConfig in above block. | 374 // This is also called in setDecodeConfig in above block. |
| 367 // i.e., when bitmap->isNull() is true. | 375 // i.e., when bitmap->isNull() is true. |
| 368 if (!chooseFromOneChoice(bitmap->config(), width, height)) { | 376 if (!chooseFromOneChoice(bitmap->config(), width, height)) { |
| 369 return false; | 377 return false; |
| 370 } | 378 } |
| 371 } | 379 } |
| 372 | 380 |
| 373 SkAutoLockPixels alp(*bitmap); | 381 SkAutoLockPixels alp(*bitmap); |
| 374 WebPDecoderConfig config; | 382 WebPDecoderConfig config; |
| 375 if (!webp_get_config_resize_crop(&config, bitmap, rect, fHasAlpha)) { | 383 if (!webp_get_config_resize_crop(&config, bitmap, rect, |
| 384 this->shouldPremultiply())) { | |
| 376 return false; | 385 return false; |
| 377 } | 386 } |
| 378 | 387 |
| 379 // Decode the WebP image data stream using WebP incremental decoding for | 388 // Decode the WebP image data stream using WebP incremental decoding for |
| 380 // the specified cropped image-region. | 389 // the specified cropped image-region. |
| 381 if (!webp_idecode(this->fInputStream, &config)) { | 390 if (!webp_idecode(this->fInputStream, &config)) { |
| 382 return false; | 391 return false; |
| 383 } | 392 } |
| 384 | 393 |
| 385 if (!directDecode) { | 394 if (!directDecode) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 } | 432 } |
| 424 | 433 |
| 425 if (!this->allocPixelRef(decodedBitmap, NULL)) { | 434 if (!this->allocPixelRef(decodedBitmap, NULL)) { |
| 426 return return_false(*decodedBitmap, "allocPixelRef"); | 435 return return_false(*decodedBitmap, "allocPixelRef"); |
| 427 } | 436 } |
| 428 | 437 |
| 429 SkAutoLockPixels alp(*decodedBitmap); | 438 SkAutoLockPixels alp(*decodedBitmap); |
| 430 | 439 |
| 431 WebPDecoderConfig config; | 440 WebPDecoderConfig config; |
| 432 if (!webp_get_config_resize(&config, decodedBitmap, origWidth, origHeight, | 441 if (!webp_get_config_resize(&config, decodedBitmap, origWidth, origHeight, |
| 433 hasAlpha)) { | 442 this->shouldPremultiply())) { |
|
scroggo
2013/06/13 20:03:14
Note that shouldPremultiply will check fHasAlpha,
| |
| 434 return false; | 443 return false; |
| 435 } | 444 } |
| 436 | 445 |
| 437 // Decode the WebP image data stream using WebP incremental decoding. | 446 // Decode the WebP image data stream using WebP incremental decoding. |
| 438 return webp_idecode(stream, &config); | 447 return webp_idecode(stream, &config); |
| 439 } | 448 } |
| 440 | 449 |
| 441 /////////////////////////////////////////////////////////////////////////////// | 450 /////////////////////////////////////////////////////////////////////////////// |
| 442 | 451 |
| 443 typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width, | 452 typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width, |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 593 return SkImageDecoder::kUnknown_Format; | 602 return SkImageDecoder::kUnknown_Format; |
| 594 } | 603 } |
| 595 | 604 |
| 596 static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) { | 605 static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) { |
| 597 return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NUL L; | 606 return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NUL L; |
| 598 } | 607 } |
| 599 | 608 |
| 600 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libwebp_dfactory); | 609 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libwebp_dfactory); |
| 601 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_webp ); | 610 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_webp ); |
| 602 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libwebp_efact ory); | 611 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libwebp_efact ory); |
| OLD | NEW |