15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Apple Computer, Inc. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Portions are Copyright (C) 2001 mozilla.org 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Other contributors: 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Stuart Parmenter <stuart@mozilla.com> 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Lesser General Public 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2.1 of the License, or (at your option) any later version. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Lesser General Public License for more details. 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Lesser General Public 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License along with this library; if not, write to the Free Software 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Alternatively, the contents of this file may be used under the terms 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * of either the Mozilla Public License Version 1.1, found at 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (the "GPL"), in which case the provisions of the MPL or the GPL are 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * applicable instead of those above. If you wish to allow use of your 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version of this file only under the terms of one of those two 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * licenses (the MPL or the GPL) and not to allow others to use your 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version of this file under the LGPL, indicate your decision by 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * deletingthe provisions above and replace them with the notice and 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * other provisions required by the MPL or the GPL, as the case may be. 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * If you do not delete the provisions above, a recipient may use your 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version of this file under any of the LGPL, the MPL or the GPL. 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 40a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/image-decoders/png/PNGImageDecoder.h" 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/PlatformInstrumentation.h" 435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/PassOwnPtr.h" 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "png.h" 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if USE(QCMSLIB) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "qcms.h" 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPNG_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 4)) 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define JMPBUF(png_ptr) png_jmpbuf(png_ptr) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define JMPBUF(png_ptr) png_ptr->jmpbuf 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 56c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Gamma constants. 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double cMaxGamma = 21474.83; 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double cDefaultGamma = 2.2; 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double cInverseGamma = 0.45455; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Protect against large PNGs. See Mozilla's bug #251381 for more info. 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const unsigned long cMaxPNGSize = 1000000UL; 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Called if the decoding of the image fails. 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void PNGAPI decodingFailed(png_structp png, png_const_charp) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) longjmp(JMPBUF(png), 1); 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Callbacks given to the read struct. The first is for warnings (we want to 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// treat a particular warning as an error, which is why we have to register this 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// callback). 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void PNGAPI decodingWarning(png_structp png, png_const_charp warningMsg) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Mozilla did this, so we will too. 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Convert a tRNS warning to be an error (see 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // http://bugzilla.mozilla.org/show_bug.cgi?id=251381 ) 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!strncmp(warningMsg, "Missing PLTE before tRNS", 24)) 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_error(png, warningMsg); 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Called when we have obtained the header information (including the size). 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void PNGAPI headerAvailable(png_structp png, png_infop) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->headerAvailable(); 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Called when a row is ready. 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void PNGAPI rowAvailable(png_structp png, png_bytep rowBuffer, png_uint_32 rowIndex, int interlacePass) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->rowAvailable(rowBuffer, rowIndex, interlacePass); 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Called when we have completely finished decoding the image. 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void PNGAPI pngComplete(png_structp png, png_infop) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->pngComplete(); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class PNGImageReader { 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WTF_MAKE_FAST_ALLOCATED; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PNGImageReader(PNGImageDecoder* decoder) 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_readOffset(0) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_currentBufferSize(0) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_decodingSizeOnly(false) 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_hasAlpha(false) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_interlaceBuffer(0) 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if USE(QCMSLIB) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_transform(0) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_rowBuffer() 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning); 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_info = png_create_info_struct(m_png); 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_progressive_read_fn(m_png, decoder, headerAvailable, rowAvailable, pngComplete); 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ~PNGImageReader() 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close(); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void close() 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_png && m_info) 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This will zero the pointers. 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_destroy_read_struct(&m_png, &m_info, 0); 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if USE(QCMSLIB) 1329e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) clearColorTransform(); 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) delete[] m_interlaceBuffer; 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_interlaceBuffer = 0; 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_readOffset = 0; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool decode(const SharedBuffer& data, bool sizeOnly) 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_decodingSizeOnly = sizeOnly; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png)); 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We need to do the setjmp here. Otherwise bad things will happen. 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (setjmp(JMPBUF(m_png))) 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return decoder->setFailed(); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const char* segment; 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) { 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_readOffset += segmentLength; 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_currentBufferSize = m_readOffset; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength); 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We explicitly specify the superclass isSizeAvailable() because we 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // merely want to check if we've managed to set the size, not 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // (recursively) trigger additional decoding if we haven't. 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sizeOnly ? decoder->ImageDecoder::isSizeAvailable() : decoder->isComplete()) 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_structp pngPtr() const { return m_png; } 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_infop infoPtr() const { return m_info; } 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void setReadOffset(unsigned offset) { m_readOffset = offset; } 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned currentBufferSize() const { return m_currentBufferSize; } 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool decodingSizeOnly() const { return m_decodingSizeOnly; } 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void setHasAlpha(bool hasAlpha) { m_hasAlpha = hasAlpha; } 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool hasAlpha() const { return m_hasAlpha; } 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_bytep interlaceBuffer() const { return m_interlaceBuffer; } 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void createInterlaceBuffer(int size) { m_interlaceBuffer = new png_byte[size]; } 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if USE(QCMSLIB) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_bytep rowBuffer() const { return m_rowBuffer.get(); } 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void createRowBuffer(int size) { m_rowBuffer = adoptArrayPtr(new png_byte[size]); } 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) qcms_transform* colorTransform() const { return m_transform; } 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1789e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) void clearColorTransform() 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_transform) 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) qcms_transform_release(m_transform); 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_transform = 0; 1839e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) } 1849e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 1859e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha) 1869e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) { 1879e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) clearColorTransform(); 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (colorProfile.isEmpty()) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!deviceProfile) 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(), colorProfile.size()); 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!inputProfile) 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We currently only support color profiles for RGB and RGBA images. 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(icSigRgbData == qcms_profile_get_color_space(inputProfile)); 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: Don't force perceptual intent if the image profile contains an intent. 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProfile, dataFormat, QCMS_INTENT_PERCEPTUAL); 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) qcms_profile_release(inputProfile); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private: 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_structp m_png; 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_infop m_info; 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned m_readOffset; 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned m_currentBufferSize; 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool m_decodingSizeOnly; 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool m_hasAlpha; 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_bytep m_interlaceBuffer; 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if USE(QCMSLIB) 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) qcms_transform* m_transform; 2161e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) OwnPtr<png_byte[]> m_rowBuffer; 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PNGImageDecoder::PNGImageDecoder(ImageSource::AlphaOption alphaOption, 2218abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption, 22206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) size_t maxDecodedBytes) 22306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) : ImageDecoder(alphaOption, gammaAndColorProfileOption, maxDecodedBytes) 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_doNothingOnFailure(false) 225323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) , m_hasColorProfile(false) 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PNGImageDecoder::~PNGImageDecoder() 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool PNGImageDecoder::isSizeAvailable() 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!ImageDecoder::isSizeAvailable()) 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) decode(true); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ImageDecoder::isSizeAvailable(); 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ImageFrame* PNGImageDecoder::frameBufferAtIndex(size_t index) 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (index) 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_frameBufferCache.isEmpty()) { 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_frameBufferCache.resize(1); 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ImageFrame& frame = m_frameBufferCache[0]; 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.status() != ImageFrame::FrameComplete) { 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PlatformInstrumentation::willDecodeImage("PNG"); 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) decode(false); 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PlatformInstrumentation::didDecodeImage(); 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 25851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) frame.notifyBitmapIfPixelsChanged(); 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return &frame; 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool PNGImageDecoder::setFailed() 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_doNothingOnFailure) 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_reader.clear(); 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ImageDecoder::setFailed(); 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#if USE(QCMSLIB) 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void readColorProfile(png_structp png, png_infop info, ColorProfile& colorProfile) 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifdef PNG_iCCP_SUPPORTED 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char* profileName; 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int compressionType; 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if (PNG_LIBPNG_VER < 10500) 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_charp profile; 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_bytep profile; 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_uint_32 profileLength; 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!png_get_iCCP(png, info, &profileName, &compressionType, &profile, &profileLength)) 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Only accept RGB color profiles from input class devices. 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool ignoreProfile = false; 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char* profileData = reinterpret_cast<char*>(profile); 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (profileLength < ImageDecoder::iccColorProfileHeaderLength) 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ignoreProfile = true; 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (!ImageDecoder::rgbColorProfile(profileData, profileLength)) 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ignoreProfile = true; 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (!ImageDecoder::inputDeviceColorProfile(profileData, profileLength)) 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ignoreProfile = true; 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) ASSERT(colorProfile.isEmpty()); 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!ignoreProfile) 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) colorProfile.append(profileData, profileLength); 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 30019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#endif 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PNGImageDecoder::headerAvailable() 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_structp png = m_reader->pngPtr(); 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_infop info = m_reader->infoPtr(); 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_uint_32 width = png_get_image_width(png, info); 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_uint_32 height = png_get_image_height(png, info); 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Protect against large images. 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (width > cMaxPNGSize || height > cMaxPNGSize) { 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) longjmp(JMPBUF(png), 1); 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We can fill in the size now that the header is available. Avoid memory 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // corruption issues by neutering setFailed() during this call; if we don't 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // do this, failures will cause |m_reader| to be deleted, and our jmpbuf 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // will cease to exist. Note that we'll still properly set the failure flag 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // in this case as soon as we longjmp(). 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_doNothingOnFailure = true; 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool result = setSize(width, height); 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_doNothingOnFailure = false; 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!result) { 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) longjmp(JMPBUF(png), 1); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int bitDepth, colorType, interlaceType, compressionType, filterType, channels; 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, &interlaceType, &compressionType, &filterType); 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The options we set here match what Mozilla does. 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (colorType == PNG_COLOR_TYPE_PALETTE || (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)) 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_expand(png); 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_bytep trns = 0; 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int trnsCount = 0; 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (png_get_valid(png, info, PNG_INFO_tRNS)) { 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_get_tRNS(png, info, &trns, &trnsCount, 0); 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_expand(png); 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (bitDepth == 16) 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_strip_16(png); 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_gray_to_rgb(png); 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#if USE(QCMSLIB) 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((colorType & PNG_COLOR_MASK_COLOR) && !m_ignoreGammaAndColorProfile) { 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We only support color profiles for color PALETTE and RGB[A] PNG. Supporting 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // color profiles for gray-scale images is slightly tricky, at least using the 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // CoreGraphics ICC library, because we expand gray-scale images to RGB but we 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // do not similarly transform the color profile. We'd either need to transform 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the color profile or we'd need to decode into a gray-scale image buffer and 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // hand that to CoreGraphics. 35893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) ColorProfile colorProfile; 35993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) readColorProfile(png, info, colorProfile); 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool decodedImageHasAlpha = (colorType & PNG_COLOR_MASK_ALPHA) || trnsCount; 36193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) m_reader->createColorTransform(colorProfile, decodedImageHasAlpha); 362323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) m_hasColorProfile = !!m_reader->colorTransform(); 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 36493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#endif 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Deal with gamma and keep it under our control. 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double gamma; 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_ignoreGammaAndColorProfile && png_get_gAMA(png, info, &gamma)) { 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((gamma <= 0.0) || (gamma > cMaxGamma)) { 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gamma = cInverseGamma; 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_gAMA(png, info, gamma); 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_gamma(png, cDefaultGamma, gamma); 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_gamma(png, cDefaultGamma, cInverseGamma); 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Tell libpng to send us rows for interlaced pngs. 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (interlaceType == PNG_INTERLACE_ADAM7) 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_set_interlace_handling(png); 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Update our info now. 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_read_update_info(png, info); 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) channels = png_get_channels(png, info); 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(channels == 3 || channels == 4); 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_reader->setHasAlpha(channels == 4); 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_reader->decodingSizeOnly()) { 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If we only needed the size, halt the reader. 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPNG_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5)) 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // '0' argument to png_process_data_pause means: Do not cache unprocessed data. 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_reader->setReadOffset(m_reader->currentBufferSize() - png_process_data_pause(png, 0)); 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size); 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png->buffer_size = 0; 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int) 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_frameBufferCache.isEmpty()) 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Initialize the framebuffer if needed. 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ImageFrame& buffer = m_frameBufferCache[0]; 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (buffer.status() == ImageFrame::FrameEmpty) { 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_structp png = m_reader->pngPtr(); 40993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!buffer.setSize(size().width(), size().height())) { 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) longjmp(JMPBUF(png), 1); 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned colorChannels = m_reader->hasAlpha() ? 4 : 3; 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (PNG_INTERLACE_ADAM7 == png_get_interlace_type(png, m_reader->infoPtr())) { 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_reader->createInterlaceBuffer(colorChannels * size().width() * size().height()); 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_reader->interlaceBuffer()) { 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) longjmp(JMPBUF(png), 1); 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if USE(QCMSLIB) 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_reader->colorTransform()) { 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_reader->createRowBuffer(colorChannels * size().width()); 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_reader->rowBuffer()) { 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) longjmp(JMPBUF(png), 1); 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer.setStatus(ImageFrame::FramePartial); 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer.setHasAlpha(false); 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For PNGs, the frame always fills the entire image. 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /* libpng comments (here to explain what follows). 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this function is called for every row in the image. If the 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * image is interlacing, and you turned on the interlace handler, 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this function will be called for every row in every pass. 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Some of these rows will not be changed from the previous pass. 4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * When the row is not changed, the new_row variable will be NULL. 4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * The rows and passes are called in order, so you don't really 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * need the row_num and pass, but I'm supplying them because it 4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * may make your life easier. 4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Nothing to do if the row is unchanged, or the row is outside 4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the image bounds: libpng may send extra rows, ignore them to 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // make our lives easier. 4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!rowBuffer) 4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 45693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) int y = rowIndex; 45793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (y < 0 || y >= size().height()) 4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /* libpng comments (continued). 4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * For the non-NULL rows of interlaced images, you must call 4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * png_progressive_combine_row() passing in the row and the 4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * old row. You can call this function for NULL rows (it will 4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * just return) and for non-interlaced images (it just does the 4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * memcpy for you) if it will make the code easier. Thus, you 4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * can just do this for all cases: 4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * png_progressive_combine_row(png_ptr, old_row, new_row); 4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * where old_row is what was displayed for previous rows. Note 4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * that the first pass (pass == 0 really) will completely cover 4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the old row, so the rows do not have to be initialized. After 4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the first pass (and only for interlaced images), you will have 4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * to pass the current row, and the function will combine the 4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * old row and the new row. 4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool hasAlpha = m_reader->hasAlpha(); 4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned colorChannels = hasAlpha ? 4 : 3; 4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_bytep row = rowBuffer; 4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (png_bytep interlaceBuffer = m_reader->interlaceBuffer()) { 4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) row = interlaceBuffer + (rowIndex * colorChannels * size().width()); 4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_progressive_combine_row(m_reader->pngPtr(), row, rowBuffer); 4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if USE(QCMSLIB) 4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (qcms_transform* transform = m_reader->colorTransform()) { 4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) qcms_transform_data(transform, row, m_reader->rowBuffer(), size().width()); 4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) row = m_reader->rowBuffer(); 4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 495f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // Write the decoded row pixels to the frame buffer. The repetitive 496f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // form of the row write loops is for speed. 497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ImageFrame::PixelData* address = buffer.getAddr(0, y); 498f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) unsigned alphaMask = 255; 49993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) int width = size().width(); 5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) png_bytep pixel = row; 502f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (hasAlpha) { 503f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (buffer.premultiplyAlpha()) { 504f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) for (int x = 0; x < width; ++x, pixel += 4) { 505f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) buffer.setRGBAPremultiply(address++, pixel[0], pixel[1], pixel[2], pixel[3]); 506f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) alphaMask &= pixel[3]; 507f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 508f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } else { 509f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) for (int x = 0; x < width; ++x, pixel += 4) { 510f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) buffer.setRGBARaw(address++, pixel[0], pixel[1], pixel[2], pixel[3]); 511f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) alphaMask &= pixel[3]; 512f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 513f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 514f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } else { 515f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) for (int x = 0; x < width; ++x, pixel += 3) { 516f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) buffer.setRGBARaw(address++, pixel[0], pixel[1], pixel[2], 255); 517f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 520f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (alphaMask != 255 && !buffer.hasAlpha()) 521f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) buffer.setHasAlpha(true); 52251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 52351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) buffer.setPixelsChanged(true); 5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PNGImageDecoder::pngComplete() 5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_frameBufferCache.isEmpty()) 5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_frameBufferCache.first().setStatus(ImageFrame::FrameComplete); 5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PNGImageDecoder::decode(bool onlySize) 5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (failed()) 5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_reader) 5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_reader = adoptPtr(new PNGImageReader(this)); 5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If we couldn't decode the image but we've received all the data, decoding 5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // has failed. 5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) 5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setFailed(); 5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If we're done decoding the image, we don't need the PNGImageReader 5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // anymore. (If we failed, |m_reader| has already been cleared.) 5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (isComplete()) 5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_reader.clear(); 5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 550c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 551