Chromium Code Reviews| Index: ui/base/clipboard/clipboard_win.cc |
| diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc |
| index cec06012fbf50e9540fe27d69155a15eba6122e2..a736f638feeb37b53440f69c03fc0a1991e49354 100644 |
| --- a/ui/base/clipboard/clipboard_win.cc |
| +++ b/ui/base/clipboard/clipboard_win.cc |
| @@ -476,18 +476,38 @@ SkBitmap Clipboard::ReadImage(Buffer buffer) const { |
| bitmap->bmiHeader.biHeight, bitmap_bits, bitmap, |
| DIB_RGB_COLORS); |
| } |
| - // SetDIBitsToDevice doesn't properly set alpha values for bitmaps with |
| - // depth < 32bpp so manually fix it up. |
| - if (bitmap->bmiHeader.biBitCount < 32) { |
| - const SkBitmap& device_bitmap = canvas.getDevice()->accessBitmap(true); |
| + // Windows doesn't really handle alpha channels well in many situations. We |
| + // attempt to manually fix the alpha channel here. Since Windows uses |
| + // premultiplied alpha, we scan for instances where (R, G, B) > A. If there |
| + // are any invalid premultiplied colors in the image, we assume the alpha |
| + // channel contains junk and reset the alpha value for all pixels to 255. This |
| + // heuristic will fail on a transparent bitmap containing only black pixels... |
| + const SkBitmap& device_bitmap = canvas.getDevice()->accessBitmap(true); |
| + { |
| SkAutoLockPixels lock(device_bitmap); |
| + bool has_invalid_alpha_channel = false; |
| for (int x = 0; x < device_bitmap.width(); ++x) { |
| for (int y = 0; y < device_bitmap.height(); ++y) { |
| - *device_bitmap.getAddr32(x, y) = |
| - SkColorSetA(*device_bitmap.getAddr32(x, y), 0xFF); |
| + uint32_t pixel = *device_bitmap.getAddr32(x, y); |
| + if (SkColorGetR(pixel) > SkColorGetA(pixel) || |
| + SkColorGetG(pixel) > SkColorGetA(pixel) || |
| + SkColorGetB(pixel) > SkColorGetA(pixel)) { |
| + has_invalid_alpha_channel = true; |
| + break; |
|
tony
2011/09/20 23:26:54
This only breaks out of the inner for loop. You p
dcheng
2011/09/20 23:56:33
Done. Thanks for the catch.
|
| + } |
| + } |
| + } |
| + |
| + if (has_invalid_alpha_channel) { |
| + for (int x = 0; x < device_bitmap.width(); ++x) { |
| + for (int y = 0; y < device_bitmap.height(); ++y) { |
| + *device_bitmap.getAddr32(x, y) = |
| + SkColorSetA(*device_bitmap.getAddr32(x, y), 0xFF); |
| + } |
| } |
| } |
| } |
| + |
| return canvas.ExtractBitmap(); |
| } |