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

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

Issue 2756463003: Remove opaque alpha channel special case (Closed)
Patch Set: Checking if JPEGImageDecoder::OutputScanlines()'s SetHasAlpha(true) is under test Created 3 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
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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 const ColorBehavior& color_behavior, 44 const ColorBehavior& color_behavior,
45 size_t max_decoded_bytes, 45 size_t max_decoded_bytes,
46 size_t offset) 46 size_t offset)
47 : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes), 47 : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes),
48 offset_(offset), 48 offset_(offset),
49 current_frame_(0), 49 current_frame_(0),
50 // It would be logical to default to kAnimationNone, but BitmapImage uses 50 // It would be logical to default to kAnimationNone, but BitmapImage uses
51 // that as a signal to never check again, meaning the actual count will 51 // that as a signal to never check again, meaning the actual count will
52 // never be respected. 52 // never be respected.
53 repetition_count_(kAnimationLoopOnce), 53 repetition_count_(kAnimationLoopOnce),
54 has_alpha_channel_(false), 54 has_alpha_channel_(false) {}
55 current_buffer_saw_alpha_(false) {}
56 55
57 PNGImageDecoder::~PNGImageDecoder() {} 56 PNGImageDecoder::~PNGImageDecoder() {}
58 57
59 bool PNGImageDecoder::SetFailed() { 58 bool PNGImageDecoder::SetFailed() {
60 reader_.reset(); 59 reader_.reset();
61 return ImageDecoder::SetFailed(); 60 return ImageDecoder::SetFailed();
62 } 61 }
63 62
64 size_t PNGImageDecoder::DecodeFrameCount() { 63 size_t PNGImageDecoder::DecodeFrameCount() {
65 Parse(ParseQuery::kMetaData); 64 Parse(ParseQuery::kMetaData);
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 290
292 if (PNG_INTERLACE_ADAM7 == 291 if (PNG_INTERLACE_ADAM7 ==
293 png_get_interlace_type(png, reader_->InfoPtr())) { 292 png_get_interlace_type(png, reader_->InfoPtr())) {
294 unsigned color_channels = has_alpha_channel_ ? 4 : 3; 293 unsigned color_channels = has_alpha_channel_ ? 4 : 3;
295 reader_->CreateInterlaceBuffer(color_channels * Size().Area()); 294 reader_->CreateInterlaceBuffer(color_channels * Size().Area());
296 if (!reader_->InterlaceBuffer()) { 295 if (!reader_->InterlaceBuffer()) {
297 longjmp(JMPBUF(png), 1); 296 longjmp(JMPBUF(png), 1);
298 return; 297 return;
299 } 298 }
300 } 299 }
301
302 current_buffer_saw_alpha_ = false;
303 } 300 }
304 301
305 const IntRect& frame_rect = buffer.OriginalFrameRect(); 302 const IntRect& frame_rect = buffer.OriginalFrameRect();
306 DCHECK(IntRect(IntPoint(), Size()).Contains(frame_rect)); 303 DCHECK(IntRect(IntPoint(), Size()).Contains(frame_rect));
307 304
308 /* libpng comments (here to explain what follows). 305 /* libpng comments (here to explain what follows).
309 * 306 *
310 * this function is called for every row in the image. If the 307 * this function is called for every row in the image. If the
311 * image is interlacing, and you turned on the interlace handler, 308 * image is interlacing, and you turned on the interlace handler,
312 * this function will be called for every row in every pass. 309 * this function will be called for every row in every pass.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 // where R, G, and/or B are greater than A. The legacy drawing 377 // where R, G, and/or B are greater than A. The legacy drawing
381 // pipeline does not know how to handle this. 378 // pipeline does not know how to handle this.
382 if (SkColorSpaceXform* xform = ColorTransform()) { 379 if (SkColorSpaceXform* xform = ColorTransform()) {
383 SkColorSpaceXform::ColorFormat color_format = 380 SkColorSpaceXform::ColorFormat color_format =
384 SkColorSpaceXform::kRGBA_8888_ColorFormat; 381 SkColorSpaceXform::kRGBA_8888_ColorFormat;
385 xform->apply(color_format, dst_row, color_format, src_ptr, width, 382 xform->apply(color_format, dst_row, color_format, src_ptr, width,
386 kUnpremul_SkAlphaType); 383 kUnpremul_SkAlphaType);
387 src_ptr = png_bytep(dst_row); 384 src_ptr = png_bytep(dst_row);
388 } 385 }
389 386
390 unsigned alpha_mask = 255;
391 if (frame_buffer_cache_[current_frame_].GetAlphaBlendSource() == 387 if (frame_buffer_cache_[current_frame_].GetAlphaBlendSource() ==
392 ImageFrame::kBlendAtopBgcolor) { 388 ImageFrame::kBlendAtopBgcolor) {
393 if (buffer.PremultiplyAlpha()) { 389 if (buffer.PremultiplyAlpha()) {
394 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; 390 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width;
395 dst_pixel++, src_ptr += 4) { 391 dst_pixel++, src_ptr += 4) {
396 ImageFrame::SetRGBAPremultiply(dst_pixel, src_ptr[0], src_ptr[1], 392 ImageFrame::SetRGBAPremultiply(dst_pixel, src_ptr[0], src_ptr[1],
397 src_ptr[2], src_ptr[3]); 393 src_ptr[2], src_ptr[3]);
398 alpha_mask &= src_ptr[3];
399 } 394 }
400 } else { 395 } else {
401 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; 396 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width;
402 dst_pixel++, src_ptr += 4) { 397 dst_pixel++, src_ptr += 4) {
403 ImageFrame::SetRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2], 398 ImageFrame::SetRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2],
404 src_ptr[3]); 399 src_ptr[3]);
405 alpha_mask &= src_ptr[3];
406 } 400 }
407 } 401 }
408 } else { 402 } else {
409 // Now, the blend method is ImageFrame::BlendAtopPreviousFrame. Since the 403 // Now, the blend method is ImageFrame::BlendAtopPreviousFrame. Since the
410 // frame data of the previous frame is copied at InitFrameBuffer, we can 404 // frame data of the previous frame is copied at InitFrameBuffer, we can
411 // blend the pixel of this frame, stored in |src_ptr|, over the previous 405 // blend the pixel of this frame, stored in |src_ptr|, over the previous
412 // pixel stored in |dst_pixel|. 406 // pixel stored in |dst_pixel|.
413 if (buffer.PremultiplyAlpha()) { 407 if (buffer.PremultiplyAlpha()) {
414 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; 408 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width;
415 dst_pixel++, src_ptr += 4) { 409 dst_pixel++, src_ptr += 4) {
416 ImageFrame::BlendRGBAPremultiplied(dst_pixel, src_ptr[0], src_ptr[1], 410 ImageFrame::BlendRGBAPremultiplied(dst_pixel, src_ptr[0], src_ptr[1],
417 src_ptr[2], src_ptr[3]); 411 src_ptr[2], src_ptr[3]);
418 alpha_mask &= src_ptr[3];
419 } 412 }
420 } else { 413 } else {
421 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; 414 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width;
422 dst_pixel++, src_ptr += 4) { 415 dst_pixel++, src_ptr += 4) {
423 ImageFrame::BlendRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], 416 ImageFrame::BlendRGBARaw(dst_pixel, src_ptr[0], src_ptr[1],
424 src_ptr[2], src_ptr[3]); 417 src_ptr[2], src_ptr[3]);
425 alpha_mask &= src_ptr[3];
426 } 418 }
427 } 419 }
428 } 420 }
429
430 if (alpha_mask != 255)
431 current_buffer_saw_alpha_ = true;
432
433 } else { 421 } else {
434 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; 422 for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width;
435 src_ptr += 3, ++dst_pixel) { 423 src_ptr += 3, ++dst_pixel) {
436 ImageFrame::SetRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2], 424 ImageFrame::SetRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2],
437 255); 425 255);
438 } 426 }
439 427
440 // We'll apply the color space xform to opaque pixels after they have been 428 // We'll apply the color space xform to opaque pixels after they have been
441 // written to the ImageFrame, purely because SkColorSpaceXform supports 429 // written to the ImageFrame, purely because SkColorSpaceXform supports
442 // RGBA (and not RGB). 430 // RGBA (and not RGB).
(...skipping 12 matching lines...) Expand all
455 443
456 if (reader_->InterlaceBuffer()) 444 if (reader_->InterlaceBuffer())
457 reader_->ClearInterlaceBuffer(); 445 reader_->ClearInterlaceBuffer();
458 446
459 ImageFrame& buffer = frame_buffer_cache_[current_frame_]; 447 ImageFrame& buffer = frame_buffer_cache_[current_frame_];
460 if (buffer.GetStatus() == ImageFrame::kFrameEmpty) { 448 if (buffer.GetStatus() == ImageFrame::kFrameEmpty) {
461 longjmp(JMPBUF(reader_->PngPtr()), 1); 449 longjmp(JMPBUF(reader_->PngPtr()), 1);
462 return; 450 return;
463 } 451 }
464 452
465 if (!current_buffer_saw_alpha_)
466 CorrectAlphaWhenFrameBufferSawNoAlpha(current_frame_);
467
468 buffer.SetStatus(ImageFrame::kFrameComplete); 453 buffer.SetStatus(ImageFrame::kFrameComplete);
469 } 454 }
470 455
471 bool PNGImageDecoder::FrameIsCompleteAtIndex(size_t index) const { 456 bool PNGImageDecoder::FrameIsCompleteAtIndex(size_t index) const {
472 if (!IsDecodedSizeAvailable()) 457 if (!IsDecodedSizeAvailable())
473 return false; 458 return false;
474 459
475 DCHECK(!Failed() && reader_); 460 DCHECK(!Failed() && reader_);
476 461
477 // For non-animated images, return whether the status of the frame is 462 // For non-animated images, return whether the status of the frame is
478 // ImageFrame::FrameComplete with ImageDecoder::FrameIsCompleteAtIndex. 463 // ImageFrame::FrameComplete with ImageDecoder::FrameIsCompleteAtIndex.
479 // This matches the behavior of WEBPImageDecoder. 464 // This matches the behavior of WEBPImageDecoder.
480 if (reader_->ParseCompleted() && reader_->FrameCount() == 1) 465 if (reader_->ParseCompleted() && reader_->FrameCount() == 1)
481 return ImageDecoder::FrameIsCompleteAtIndex(index); 466 return ImageDecoder::FrameIsCompleteAtIndex(index);
482 467
483 return reader_->FrameIsReceivedAtIndex(index); 468 return reader_->FrameIsReceivedAtIndex(index);
484 } 469 }
485 470
486 float PNGImageDecoder::FrameDurationAtIndex(size_t index) const { 471 float PNGImageDecoder::FrameDurationAtIndex(size_t index) const {
487 if (index < frame_buffer_cache_.size()) 472 if (index < frame_buffer_cache_.size())
488 return frame_buffer_cache_[index].Duration(); 473 return frame_buffer_cache_[index].Duration();
489 return 0; 474 return 0;
490 } 475 }
491 476
492 } // namespace blink 477 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698