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

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

Issue 15466004: Make image decoders faster by refactoring hot loops that fills the lines of ImageFrame. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 7 years, 7 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) 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698