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

Side by Side Diff: third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp

Issue 2716533002: [PNGImageDecoder] Clean up readColorSpace, TODOs, cruft (Closed)
Patch Set: Remove unused transparency variables. Created 3 years, 10 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
« 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 (C) 2006 Apple Computer, Inc. 2 * Copyright (C) 2006 Apple Computer, Inc.
3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
4 * 4 *
5 * Portions are Copyright (C) 2001 mozilla.org 5 * Portions are Copyright (C) 2001 mozilla.org
6 * 6 *
7 * Other contributors: 7 * Other contributors:
8 * Stuart Parmenter <stuart@mozilla.com> 8 * Stuart Parmenter <stuart@mozilla.com>
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 47
48 PNGImageDecoder::PNGImageDecoder(AlphaOption alphaOption, 48 PNGImageDecoder::PNGImageDecoder(AlphaOption alphaOption,
49 const ColorBehavior& colorBehavior, 49 const ColorBehavior& colorBehavior,
50 size_t maxDecodedBytes, 50 size_t maxDecodedBytes,
51 size_t offset) 51 size_t offset)
52 : ImageDecoder(alphaOption, colorBehavior, maxDecodedBytes), 52 : ImageDecoder(alphaOption, colorBehavior, maxDecodedBytes),
53 m_offset(offset) {} 53 m_offset(offset) {}
54 54
55 PNGImageDecoder::~PNGImageDecoder() {} 55 PNGImageDecoder::~PNGImageDecoder() {}
56 56
57 inline float pngFixedToFloat(png_fixed_point x) { 57 inline sk_sp<SkColorSpace> readColorSpace(png_structp png, png_infop info) {
58 return ((float)x) * 0.00001f; 58 if (png_get_valid(png, info, PNG_INFO_sRGB))
59 } 59 return SkColorSpace::MakeSRGB();
60 60
61 inline sk_sp<SkColorSpace> readColorSpace(png_structp png, png_infop info) { 61 png_charp name;
62 if (png_get_valid(png, info, PNG_INFO_sRGB)) { 62 int compression;
63 return SkColorSpace::MakeSRGB(); 63 png_bytep profile;
64 } 64 png_uint_32 length;
65 65 if (png_get_iCCP(png, info, &name, &compression, &profile, &length))
66 png_charp name = nullptr;
67 int compression = 0;
68 png_bytep profile = nullptr;
69 png_uint_32 length = 0;
70 if (png_get_iCCP(png, info, &name, &compression, &profile, &length)) {
71 return SkColorSpace::MakeICC(profile, length); 66 return SkColorSpace::MakeICC(profile, length);
72 }
73 67
74 png_fixed_point chrm[8]; 68 png_fixed_point chrm[8];
75 if (png_get_cHRM_fixed(png, info, &chrm[0], &chrm[1], &chrm[2], &chrm[3], 69 if (!png_get_cHRM_fixed(png, info, &chrm[0], &chrm[1], &chrm[2], &chrm[3],
76 &chrm[4], &chrm[5], &chrm[6], &chrm[7])) { 70 &chrm[4], &chrm[5], &chrm[6], &chrm[7]))
77 SkColorSpacePrimaries primaries; 71 return nullptr;
78 primaries.fRX = pngFixedToFloat(chrm[2]);
79 primaries.fRY = pngFixedToFloat(chrm[3]);
80 primaries.fGX = pngFixedToFloat(chrm[4]);
81 primaries.fGY = pngFixedToFloat(chrm[5]);
82 primaries.fBX = pngFixedToFloat(chrm[6]);
83 primaries.fBY = pngFixedToFloat(chrm[7]);
84 primaries.fWX = pngFixedToFloat(chrm[0]);
85 primaries.fWY = pngFixedToFloat(chrm[1]);
86 72
87 SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor); 73 png_fixed_point inverseGamma;
88 if (primaries.toXYZD50(&toXYZD50)) { 74 if (!png_get_gAMA_fixed(png, info, &inverseGamma))
89 png_fixed_point gammaFixed; 75 return nullptr;
90 if (PNG_INFO_gAMA == png_get_gAMA_fixed(png, info, &gammaFixed)) {
91 SkColorSpaceTransferFn fn;
92 fn.fA = 1.0f;
93 fn.fB = fn.fC = fn.fD = fn.fE = fn.fF = 0.0f;
94 // This is necessary because the gAMA chunk actually stores 1/gamma.
95 fn.fG = 1.0f / pngFixedToFloat(gammaFixed);
96 return SkColorSpace::MakeRGB(fn, toXYZD50);
97 }
98 76
99 // Note that we only use the cHRM tag when gAMA is present. The 77 // cHRM and gAMA tags are both present. The PNG spec states that cHRM is
100 // specification states that the cHRM is valid even without a gAMA 78 // valid even without gAMA but we cannot apply the cHRM without guessing
101 // tag, but we cannot apply the cHRM without guessing a transfer 79 // a gAMA. Color correction is not a guessing game: match the behavior
102 // function. It's possible that we should guess sRGB transfer 80 // of Safari and Firefox instead (compat).
103 // function, given that unmarked PNGs should be treated as sRGB.
104 // However, the current behavior matches Safari and Firefox.
105 }
106 }
107 81
108 return nullptr; 82 struct pngFixedToFloat {
83 explicit pngFixedToFloat(png_fixed_point value)
84 : floatValue(.00001f * value) {}
85 operator float() { return floatValue; }
86 float floatValue;
87 };
88
89 SkColorSpacePrimaries primaries;
90 primaries.fRX = pngFixedToFloat(chrm[2]);
91 primaries.fRY = pngFixedToFloat(chrm[3]);
92 primaries.fGX = pngFixedToFloat(chrm[4]);
93 primaries.fGY = pngFixedToFloat(chrm[5]);
94 primaries.fBX = pngFixedToFloat(chrm[6]);
95 primaries.fBY = pngFixedToFloat(chrm[7]);
96 primaries.fWX = pngFixedToFloat(chrm[0]);
97 primaries.fWY = pngFixedToFloat(chrm[1]);
98
99 SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
100 if (!primaries.toXYZD50(&toXYZD50))
101 return nullptr;
102
103 SkColorSpaceTransferFn fn;
104 fn.fG = 1.0f / pngFixedToFloat(inverseGamma);
105 fn.fA = 1.0f;
106 fn.fB = fn.fC = fn.fD = fn.fE = fn.fF = 0.0f;
107
108 return SkColorSpace::MakeRGB(fn, toXYZD50);
109 } 109 }
110 110
111 void PNGImageDecoder::headerAvailable() { 111 void PNGImageDecoder::headerAvailable() {
112 png_structp png = m_reader->pngPtr(); 112 png_structp png = m_reader->pngPtr();
113 png_infop info = m_reader->infoPtr(); 113 png_infop info = m_reader->infoPtr();
114 png_uint_32 width = png_get_image_width(png, info); 114 png_uint_32 width = png_get_image_width(png, info);
115 png_uint_32 height = png_get_image_height(png, info); 115 png_uint_32 height = png_get_image_height(png, info);
116 116
117 // Protect against large PNGs. See http://bugzil.la/251381 for more details. 117 // Protect against large PNGs. See http://bugzil.la/251381 for more details.
118 const unsigned long maxPNGSize = 1000000UL; 118 const unsigned long maxPNGSize = 1000000UL;
119 if (width > maxPNGSize || height > maxPNGSize) { 119 if (width > maxPNGSize || height > maxPNGSize) {
120 longjmp(JMPBUF(png), 1); 120 longjmp(JMPBUF(png), 1);
121 return; 121 return;
122 } 122 }
123 123
124 // Set the image size now that the image header is available. 124 // Set the image size now that the image header is available.
125 if (!setSize(width, height)) { 125 if (!setSize(width, height)) {
126 longjmp(JMPBUF(png), 1); 126 longjmp(JMPBUF(png), 1);
127 return; 127 return;
128 } 128 }
129 129
130 int bitDepth, colorType, interlaceType, compressionType, filterType, channels; 130 int bitDepth, colorType, interlaceType, compressionType;
131 png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, 131 png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType,
132 &interlaceType, &compressionType, &filterType); 132 &interlaceType, &compressionType, nullptr);
133 133
134 // The options we set here match what Mozilla does. 134 // The options we set here match what Mozilla does.
135 135
136 // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. 136 // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA.
137 if (colorType == PNG_COLOR_TYPE_PALETTE || 137 if (colorType == PNG_COLOR_TYPE_PALETTE ||
138 (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)) 138 (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8))
139 png_set_expand(png); 139 png_set_expand(png);
140 140
141 png_bytep trns = 0; 141 if (png_get_valid(png, info, PNG_INFO_tRNS))
142 int trnsCount = 0;
143 if (png_get_valid(png, info, PNG_INFO_tRNS)) {
144 png_get_tRNS(png, info, &trns, &trnsCount, 0);
145 png_set_expand(png); 142 png_set_expand(png);
146 }
147 143
148 if (bitDepth == 16) 144 if (bitDepth == 16)
149 png_set_strip_16(png); 145 png_set_strip_16(png);
150 146
151 if (colorType == PNG_COLOR_TYPE_GRAY || 147 if (colorType == PNG_COLOR_TYPE_GRAY ||
152 colorType == PNG_COLOR_TYPE_GRAY_ALPHA) 148 colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
153 png_set_gray_to_rgb(png); 149 png_set_gray_to_rgb(png);
154 150
155 if ((colorType & PNG_COLOR_MASK_COLOR) && !ignoresColorSpace()) { 151 if ((colorType & PNG_COLOR_MASK_COLOR) && !ignoresColorSpace()) {
156 // We only support color profiles for color PALETTE and RGB[A] PNG. 152 // We only support color profiles for color PALETTE and RGB[A] PNG.
157 // Supporting color profiles for gray-scale images is slightly tricky, at 153 // TODO(msarret): Add GRAY profile support, block CYMK?
158 // least using the CoreGraphics ICC library, because we expand gray-scale 154 if (sk_sp<SkColorSpace> colorSpace = readColorSpace(png, info))
159 // images to RGB but we do not similarly transform the color profile. We'd 155 setEmbeddedColorSpace(std::move(colorSpace));
160 // either need to transform the color profile or we'd need to decode into a
161 // gray-scale image buffer and hand that to CoreGraphics.
162 sk_sp<SkColorSpace> colorSpace = readColorSpace(png, info);
163 if (colorSpace) {
164 setEmbeddedColorSpace(colorSpace);
165 }
166 } 156 }
167 157
168 if (!hasEmbeddedColorSpace()) { 158 if (!hasEmbeddedColorSpace()) {
169 // TODO (msarett):
170 // Applying the transfer function (gamma) should be handled by
171 // SkColorSpaceXform. Here we always convert to a transfer function that
172 // is a 2.2 exponential. This is a little strange given that the dst
173 // transfer function is not necessarily a 2.2 exponential.
174 // TODO (msarett):
175 // Often, PNGs that specify their transfer function with the gAMA tag will
176 // also specify their gamut with the cHRM tag. We should read this tag
177 // and do a full color space transformation if it is present.
178 const double inverseGamma = 0.45455; 159 const double inverseGamma = 0.45455;
179 const double defaultGamma = 2.2; 160 const double defaultGamma = 2.2;
180 double gamma; 161 double gamma;
181 if (!ignoresColorSpace() && png_get_gAMA(png, info, &gamma)) { 162 if (!ignoresColorSpace() && png_get_gAMA(png, info, &gamma)) {
182 const double maxGamma = 21474.83; 163 const double maxGamma = 21474.83;
183 if ((gamma <= 0.0) || (gamma > maxGamma)) { 164 if ((gamma <= 0.0) || (gamma > maxGamma)) {
184 gamma = inverseGamma; 165 gamma = inverseGamma;
185 png_set_gAMA(png, info, gamma); 166 png_set_gAMA(png, info, gamma);
186 } 167 }
187 png_set_gamma(png, defaultGamma, gamma); 168 png_set_gamma(png, defaultGamma, gamma);
188 } else { 169 } else {
189 png_set_gamma(png, defaultGamma, inverseGamma); 170 png_set_gamma(png, defaultGamma, inverseGamma);
190 } 171 }
191 } 172 }
192 173
193 // Tell libpng to send us rows for interlaced pngs. 174 // Tell libpng to send us rows for interlaced pngs.
194 if (interlaceType == PNG_INTERLACE_ADAM7) 175 if (interlaceType == PNG_INTERLACE_ADAM7)
195 png_set_interlace_handling(png); 176 png_set_interlace_handling(png);
196 177
197 // Update our info now. 178 // Update our info now (so we can get color channel info).
198 png_read_update_info(png, info); 179 png_read_update_info(png, info);
199 channels = png_get_channels(png, info);
200 ASSERT(channels == 3 || channels == 4);
201 180
181 int channels = png_get_channels(png, info);
182 DCHECK(channels == 3 || channels == 4);
202 m_reader->setHasAlpha(channels == 4); 183 m_reader->setHasAlpha(channels == 4);
203 184
204 if (m_reader->decodingSizeOnly()) { 185 if (m_reader->decodingSizeOnly()) {
205 // If we only needed the size, halt the reader. 186 // If we only needed the size, halt the reader.
206 #if PNG_LIBPNG_VER_MAJOR > 1 || \ 187 #if PNG_LIBPNG_VER_MAJOR > 1 || \
207 (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5) 188 (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5)
208 // Passing '0' tells png_process_data_pause() not to cache unprocessed data. 189 // Passing '0' tells png_process_data_pause() not to cache unprocessed data.
209 m_reader->setReadOffset(m_reader->currentBufferSize() - 190 m_reader->setReadOffset(m_reader->currentBufferSize() -
210 png_process_data_pause(png, 0)); 191 png_process_data_pause(png, 0));
211 #else 192 #else
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 } 224 }
244 225
245 buffer.setStatus(ImageFrame::FramePartial); 226 buffer.setStatus(ImageFrame::FramePartial);
246 buffer.setHasAlpha(false); 227 buffer.setHasAlpha(false);
247 228
248 // For PNGs, the frame always fills the entire image. 229 // For PNGs, the frame always fills the entire image.
249 buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); 230 buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
250 } 231 }
251 232
252 /* libpng comments (here to explain what follows). 233 /* libpng comments (here to explain what follows).
253 * 234 *
254 * this function is called for every row in the image. If the 235 * this function is called for every row in the image. If the
255 * image is interlacing, and you turned on the interlace handler, 236 * image is interlacing, and you turned on the interlace handler,
256 * this function will be called for every row in every pass. 237 * this function will be called for every row in every pass.
257 * Some of these rows will not be changed from the previous pass. 238 * Some of these rows will not be changed from the previous pass.
258 * When the row is not changed, the new_row variable will be NULL. 239 * When the row is not changed, the new_row variable will be NULL.
259 * The rows and passes are called in order, so you don't really 240 * The rows and passes are called in order, so you don't really
260 * need the row_num and pass, but I'm supplying them because it 241 * need the row_num and pass, but I'm supplying them because it
261 * may make your life easier. 242 * may make your life easier.
262 */ 243 */
263 244
264 // Nothing to do if the row is unchanged, or the row is outside 245 // Nothing to do if the row is unchanged, or the row is outside
265 // the image bounds: libpng may send extra rows, ignore them to 246 // the image bounds: libpng may send extra rows, ignore them to
266 // make our lives easier. 247 // make our lives easier.
267 if (!rowBuffer) 248 if (!rowBuffer)
268 return; 249 return;
269 int y = rowIndex; 250 int y = rowIndex;
270 if (y < 0 || y >= size().height()) 251 if (y < 0 || y >= size().height())
271 return; 252 return;
272 253
273 /* libpng comments (continued). 254 /* libpng comments (continued).
274 * 255 *
275 * For the non-NULL rows of interlaced images, you must call 256 * For the non-NULL rows of interlaced images, you must call
276 * png_progressive_combine_row() passing in the row and the 257 * png_progressive_combine_row() passing in the row and the
277 * old row. You can call this function for NULL rows (it will 258 * old row. You can call this function for NULL rows (it will
278 * just return) and for non-interlaced images (it just does the 259 * just return) and for non-interlaced images (it just does the
279 * memcpy for you) if it will make the code easier. Thus, you 260 * memcpy for you) if it will make the code easier. Thus, you
280 * can just do this for all cases: 261 * can just do this for all cases:
281 * 262 *
282 * png_progressive_combine_row(png_ptr, old_row, new_row); 263 * png_progressive_combine_row(png_ptr, old_row, new_row);
283 * 264 *
284 * where old_row is what was displayed for previous rows. Note 265 * where old_row is what was displayed for previous rows. Note
285 * that the first pass (pass == 0 really) will completely cover 266 * that the first pass (pass == 0 really) will completely cover
286 * the old row, so the rows do not have to be initialized. After 267 * the old row, so the rows do not have to be initialized. After
287 * the first pass (and only for interlaced images), you will have 268 * the first pass (and only for interlaced images), you will have
288 * to pass the current row, and the function will combine the 269 * to pass the current row, and the function will combine the
289 * old row and the new row. 270 * old row and the new row.
290 */ 271 */
291 272
292 bool hasAlpha = m_reader->hasAlpha(); 273 bool hasAlpha = m_reader->hasAlpha();
293 png_bytep row = rowBuffer; 274 png_bytep row = rowBuffer;
294 275
295 if (png_bytep interlaceBuffer = m_reader->interlaceBuffer()) { 276 if (png_bytep interlaceBuffer = m_reader->interlaceBuffer()) {
296 unsigned colorChannels = hasAlpha ? 4 : 3; 277 unsigned colorChannels = hasAlpha ? 4 : 3;
297 row = interlaceBuffer + (rowIndex * colorChannels * size().width()); 278 row = interlaceBuffer + (rowIndex * colorChannels * size().width());
298 png_progressive_combine_row(m_reader->pngPtr(), row, rowBuffer); 279 png_progressive_combine_row(m_reader->pngPtr(), row, rowBuffer);
299 } 280 }
300 281
301 // Write the decoded row pixels to the frame buffer. The repetitive 282 // Write the decoded row pixels to the frame buffer. The repetitive
302 // form of the row write loops is for speed. 283 // form of the row write loops is for speed.
303 ImageFrame::PixelData* const dstRow = buffer.getAddr(0, y); 284 ImageFrame::PixelData* const dstRow = buffer.getAddr(0, y);
304 unsigned alphaMask = 255;
305 int width = size().width(); 285 int width = size().width();
306 286
307 png_bytep srcPtr = row; 287 png_bytep srcPtr = row;
308 if (hasAlpha) { 288 if (hasAlpha) {
309 // Here we apply the color space transformation to the dst space. 289 // Here we apply the color space transformation to the dst space.
310 // It does not really make sense to transform to a gamma-encoded 290 // It does not really make sense to transform to a gamma-encoded
311 // space and then immediately after, perform a linear premultiply. 291 // space and then immediately after, perform a linear premultiply.
312 // Ideally we would pass kPremul_SkAlphaType to xform->apply(), 292 // Ideally we would pass kPremul_SkAlphaType to xform->apply(),
313 // instructing SkColorSpaceXform to perform the linear premultiply 293 // instructing SkColorSpaceXform to perform the linear premultiply
314 // while the pixels are a linear space. 294 // while the pixels are a linear space.
315 // We cannot do this because when we apply the gamma encoding after 295 // We cannot do this because when we apply the gamma encoding after
316 // the premultiply, we will very likely end up with valid pixels 296 // the premultiply, we will very likely end up with valid pixels
317 // where R, G, and/or B are greater than A. The legacy drawing 297 // where R, G, and/or B are greater than A. The legacy drawing
318 // pipeline does not know how to handle this. 298 // pipeline does not know how to handle this.
319 if (SkColorSpaceXform* xform = colorTransform()) { 299 if (SkColorSpaceXform* xform = colorTransform()) {
320 SkColorSpaceXform::ColorFormat colorFormat = 300 SkColorSpaceXform::ColorFormat colorFormat =
321 SkColorSpaceXform::kRGBA_8888_ColorFormat; 301 SkColorSpaceXform::kRGBA_8888_ColorFormat;
322 xform->apply(colorFormat, dstRow, colorFormat, srcPtr, size().width(), 302 xform->apply(colorFormat, dstRow, colorFormat, srcPtr, size().width(),
323 kUnpremul_SkAlphaType); 303 kUnpremul_SkAlphaType);
324 srcPtr = (png_bytep)dstRow; 304 srcPtr = png_bytep(dstRow);
325 } 305 }
326 306
307 unsigned alphaMask = 255;
327 if (buffer.premultiplyAlpha()) { 308 if (buffer.premultiplyAlpha()) {
328 for (auto *dstPixel = dstRow; dstPixel < dstRow + width; 309 for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
329 dstPixel++, srcPtr += 4) { 310 srcPtr += 4, ++dstPixel) {
330 buffer.setRGBAPremultiply(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], 311 buffer.setRGBAPremultiply(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2],
331 srcPtr[3]); 312 srcPtr[3]);
332 alphaMask &= srcPtr[3]; 313 alphaMask &= srcPtr[3];
333 } 314 }
334 } else { 315 } else {
335 for (auto *dstPixel = dstRow; dstPixel < dstRow + width; 316 for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
336 dstPixel++, srcPtr += 4) { 317 srcPtr += 4, ++dstPixel) {
337 buffer.setRGBARaw(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], srcPtr[3]); 318 buffer.setRGBARaw(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], srcPtr[3]);
338 alphaMask &= srcPtr[3]; 319 alphaMask &= srcPtr[3];
339 } 320 }
340 } 321 }
322
323 if (alphaMask != 255 && !buffer.hasAlpha())
324 buffer.setHasAlpha(true);
325
341 } else { 326 } else {
342 for (auto *dstPixel = dstRow; dstPixel < dstRow + width; 327 for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
343 dstPixel++, srcPtr += 3) { 328 srcPtr += 3, ++dstPixel) {
344 buffer.setRGBARaw(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], 255); 329 buffer.setRGBARaw(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], 255);
345 } 330 }
346 331
347 // We'll apply the color space xform to opaque pixels after they have been 332 // We'll apply the color space xform to opaque pixels after they have been
348 // written to the ImageFrame, purely because SkColorSpaceXform supports 333 // written to the ImageFrame, purely because SkColorSpaceXform supports
349 // RGBA (and not RGB). 334 // RGBA (and not RGB).
350 if (SkColorSpaceXform* xform = colorTransform()) { 335 if (SkColorSpaceXform* xform = colorTransform()) {
351 xform->apply(xformColorFormat(), dstRow, xformColorFormat(), dstRow, 336 xform->apply(xformColorFormat(), dstRow, xformColorFormat(), dstRow,
352 size().width(), kOpaque_SkAlphaType); 337 size().width(), kOpaque_SkAlphaType);
353 } 338 }
354 } 339 }
355 340
356 if (alphaMask != 255 && !buffer.hasAlpha())
357 buffer.setHasAlpha(true);
358
359 buffer.setPixelsChanged(true); 341 buffer.setPixelsChanged(true);
360 } 342 }
361 343
362 void PNGImageDecoder::complete() { 344 void PNGImageDecoder::complete() {
363 if (m_frameBufferCache.isEmpty()) 345 if (m_frameBufferCache.isEmpty())
364 return; 346 return;
365 347
366 m_frameBufferCache[0].setStatus(ImageFrame::FrameComplete); 348 m_frameBufferCache[0].setStatus(ImageFrame::FrameComplete);
367 } 349 }
368 350
(...skipping 12 matching lines...) Expand all
381 // has failed. 363 // has failed.
382 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) 364 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived())
383 setFailed(); 365 setFailed();
384 366
385 // If decoding is done or failed, we don't need the PNGImageReader anymore. 367 // If decoding is done or failed, we don't need the PNGImageReader anymore.
386 if (isComplete(this) || failed()) 368 if (isComplete(this) || failed())
387 m_reader.reset(); 369 m_reader.reset();
388 } 370 }
389 371
390 } // namespace blink 372 } // namespace blink
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