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 |