OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2006 Apple Computer, Inc. | 2 * Copyright (C) 2006 Apple Computer, Inc. |
3 * Copyright (C) 2007-2009 Torch Mobile, Inc. | 3 * Copyright (C) 2007-2009 Torch Mobile, Inc. |
4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
5 * | 5 * |
6 * Portions are Copyright (C) 2001 mozilla.org | 6 * Portions are Copyright (C) 2001 mozilla.org |
7 * | 7 * |
8 * Other contributors: | 8 * Other contributors: |
9 * Stuart Parmenter <stuart@mozilla.com> | 9 * Stuart Parmenter <stuart@mozilla.com> |
10 * | 10 * |
(...skipping 24 matching lines...) Expand all Loading... | |
35 * other provisions required by the MPL or the GPL, as the case may be. | 35 * other provisions required by the MPL or the GPL, as the case may be. |
36 * If you do not delete the provisions above, a recipient may use your | 36 * If you do not delete the provisions above, a recipient may use your |
37 * version of this file under any of the LGPL, the MPL or the GPL. | 37 * version of this file under any of the LGPL, the MPL or the GPL. |
38 */ | 38 */ |
39 | 39 |
40 #include "config.h" | 40 #include "config.h" |
41 #include "core/platform/image-decoders/png/PNGImageDecoder.h" | 41 #include "core/platform/image-decoders/png/PNGImageDecoder.h" |
42 | 42 |
43 #include "core/platform/PlatformInstrumentation.h" | 43 #include "core/platform/PlatformInstrumentation.h" |
44 #include "png.h" | 44 #include "png.h" |
45 #include <wtf/OwnArrayPtr.h> | 45 #include "wtf/MathExtras.h" |
46 #include <wtf/PassOwnPtr.h> | 46 #include "wtf/OwnArrayPtr.h" |
47 #include "wtf/PassOwnPtr.h" | |
47 | 48 |
48 #if USE(QCMSLIB) | 49 #if USE(QCMSLIB) |
49 #include "qcms.h" | 50 #include "qcms.h" |
50 #endif | 51 #endif |
51 | 52 |
52 #if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPN G_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 4)) | 53 #if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPN G_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 4)) |
53 #define JMPBUF(png_ptr) png_jmpbuf(png_ptr) | 54 #define JMPBUF(png_ptr) png_jmpbuf(png_ptr) |
54 #else | 55 #else |
55 #define JMPBUF(png_ptr) png_ptr->jmpbuf | 56 #define JMPBUF(png_ptr) png_ptr->jmpbuf |
56 #endif | 57 #endif |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
395 #if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPN G_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5)) | 396 #if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPN G_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5)) |
396 // '0' argument to png_process_data_pause means: Do not cache unprocesse d data. | 397 // '0' argument to png_process_data_pause means: Do not cache unprocesse d data. |
397 m_reader->setReadOffset(m_reader->currentBufferSize() - png_process_data _pause(png, 0)); | 398 m_reader->setReadOffset(m_reader->currentBufferSize() - png_process_data _pause(png, 0)); |
398 #else | 399 #else |
399 m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size ); | 400 m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size ); |
400 png->buffer_size = 0; | 401 png->buffer_size = 0; |
401 #endif | 402 #endif |
402 } | 403 } |
403 } | 404 } |
404 | 405 |
406 static inline void setPixelRGB(ImageFrame::PixelData* dest, png_bytep pixel) | |
407 { | |
408 *dest = 0xFF000000U | pixel[0] << 16 | pixel[1] << 8 | pixel[2]; | |
409 } | |
410 | |
411 static inline void setPixelRGBA(ImageFrame::PixelData* dest, png_bytep pixel, un signed char& nonTrivialAlphaMask) | |
412 { | |
413 unsigned char a = pixel[3]; | |
414 *dest = a << 24 | pixel[0] << 16 | pixel[1] << 8 | pixel[2]; | |
415 nonTrivialAlphaMask |= (255 - a); | |
416 } | |
417 | |
418 static inline void setPixelPremultipliedRGBA(ImageFrame::PixelData* dest, png_by tep pixel, unsigned char& nonTrivialAlphaMask) | |
419 { | |
420 unsigned char a = pixel[3]; | |
421 unsigned char r = WTF::fastDivideBy255(pixel[0] * a); | |
Noel Gordon
2013/05/25 05:58:26
Agree with Peter that we should consolidate these
| |
422 unsigned char g = WTF::fastDivideBy255(pixel[1] * a); | |
423 unsigned char b = WTF::fastDivideBy255(pixel[2] * a); | |
424 | |
425 *dest = a << 24 | r << 16 | g << 8 | b; | |
Noel Gordon
2013/05/25 05:58:26
A second reason to consolidate is that here, and e
| |
426 nonTrivialAlphaMask |= (255 - a); | |
Noel Gordon
2013/05/25 05:58:26
If nonTrivialAlphaMask was initialized to 255 say,
| |
427 } | |
428 | |
405 void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int) | 429 void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int) |
406 { | 430 { |
407 if (m_frameBufferCache.isEmpty()) | 431 if (m_frameBufferCache.isEmpty()) |
408 return; | 432 return; |
409 | 433 |
410 // Initialize the framebuffer if needed. | 434 // Initialize the framebuffer if needed. |
411 ImageFrame& buffer = m_frameBufferCache[0]; | 435 ImageFrame& buffer = m_frameBufferCache[0]; |
412 if (buffer.status() == ImageFrame::FrameEmpty) { | 436 if (buffer.status() == ImageFrame::FrameEmpty) { |
413 png_structp png = m_reader->pngPtr(); | 437 png_structp png = m_reader->pngPtr(); |
414 if (!buffer.setSize(scaledSize().width(), scaledSize().height())) { | 438 if (!buffer.setSize(scaledSize().width(), scaledSize().height())) { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
493 #if USE(QCMSLIB) | 517 #if USE(QCMSLIB) |
494 if (qcms_transform* transform = m_reader->colorTransform()) { | 518 if (qcms_transform* transform = m_reader->colorTransform()) { |
495 qcms_transform_data(transform, row, m_reader->rowBuffer(), size().width( )); | 519 qcms_transform_data(transform, row, m_reader->rowBuffer(), size().width( )); |
496 row = m_reader->rowBuffer(); | 520 row = m_reader->rowBuffer(); |
497 } | 521 } |
498 #endif | 522 #endif |
499 | 523 |
500 // Write the decoded row pixels to the frame buffer. | 524 // Write the decoded row pixels to the frame buffer. |
501 ImageFrame::PixelData* address = buffer.getAddr(0, y); | 525 ImageFrame::PixelData* address = buffer.getAddr(0, y); |
502 int width = scaledSize().width(); | 526 int width = scaledSize().width(); |
503 bool nonTrivialAlpha = false; | 527 unsigned char nonTrivialAlphaMask = 0; |
504 | 528 |
505 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) | 529 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) |
Noel Gordon
2013/05/25 05:58:26
Yes, was removed at https://codereview.chromium.or
| |
506 for (int x = 0; x < width; ++x) { | 530 if (m_scaled) { |
507 png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChann els; | 531 for (int x = 0; x < width; ++x) { |
508 unsigned alpha = hasAlpha ? pixel[3] : 255; | 532 png_bytep pixel = row + m_scaledColumns[x] * colorChannels; |
509 buffer.setRGBA(address++, pixel[0], pixel[1], pixel[2], alpha); | 533 unsigned alpha = hasAlpha ? pixel[3] : 255; |
510 nonTrivialAlpha |= alpha < 255; | 534 buffer.setRGBA(address++, pixel[0], pixel[1], pixel[2], alpha); |
535 nonTrivialAlphaMask |= (255 - alpha); | |
536 } | |
537 } else | |
538 #endif | |
539 { | |
540 png_bytep pixel = row; | |
541 if (hasAlpha) { | |
542 if (buffer.premultiplyAlpha()) { | |
543 for (int x = 0; x < width; ++x, pixel += 4) | |
544 setPixelPremultipliedRGBA(address++, pixel, nonTrivialAlphaM ask); | |
545 } else { | |
546 for (int x = 0; x < width; ++x, pixel += 4) | |
547 setPixelRGBA(address++, pixel, nonTrivialAlphaMask); | |
548 } | |
549 } else { | |
550 for (int x = 0; x < width; ++x, pixel += 3) | |
551 setPixelRGB(address++, pixel); | |
552 } | |
511 } | 553 } |
512 #else | |
513 ASSERT(!m_scaled); | |
514 png_bytep pixel = row; | |
515 for (int x = 0; x < width; ++x, pixel += colorChannels) { | |
516 unsigned alpha = hasAlpha ? pixel[3] : 255; | |
517 buffer.setRGBA(address++, pixel[0], pixel[1], pixel[2], alpha); | |
518 nonTrivialAlpha |= alpha < 255; | |
519 } | |
520 #endif | |
521 | 554 |
522 if (nonTrivialAlpha && !buffer.hasAlpha()) | 555 |
523 buffer.setHasAlpha(nonTrivialAlpha); | 556 if (nonTrivialAlphaMask && !buffer.hasAlpha()) |
557 buffer.setHasAlpha(true); | |
524 } | 558 } |
525 | 559 |
526 void PNGImageDecoder::pngComplete() | 560 void PNGImageDecoder::pngComplete() |
527 { | 561 { |
528 if (!m_frameBufferCache.isEmpty()) | 562 if (!m_frameBufferCache.isEmpty()) |
529 m_frameBufferCache.first().setStatus(ImageFrame::FrameComplete); | 563 m_frameBufferCache.first().setStatus(ImageFrame::FrameComplete); |
530 } | 564 } |
531 | 565 |
532 void PNGImageDecoder::decode(bool onlySize) | 566 void PNGImageDecoder::decode(bool onlySize) |
533 { | 567 { |
534 if (failed()) | 568 if (failed()) |
535 return; | 569 return; |
536 | 570 |
537 if (!m_reader) | 571 if (!m_reader) |
538 m_reader = adoptPtr(new PNGImageReader(this)); | 572 m_reader = adoptPtr(new PNGImageReader(this)); |
539 | 573 |
540 // If we couldn't decode the image but we've received all the data, decoding | 574 // If we couldn't decode the image but we've received all the data, decoding |
541 // has failed. | 575 // has failed. |
542 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) | 576 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) |
543 setFailed(); | 577 setFailed(); |
544 // If we're done decoding the image, we don't need the PNGImageReader | 578 // If we're done decoding the image, we don't need the PNGImageReader |
545 // anymore. (If we failed, |m_reader| has already been cleared.) | 579 // anymore. (If we failed, |m_reader| has already been cleared.) |
546 else if (isComplete()) | 580 else if (isComplete()) |
547 m_reader.clear(); | 581 m_reader.clear(); |
548 } | 582 } |
549 | 583 |
550 } // namespace WebCore | 584 } // namespace WebCore |
OLD | NEW |