Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: src/images/SkImageDecoder_libwebp.cpp

Issue 16983004: Respect unpremul in webp decoder. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698