168513a70bcd92384395513322f1b801e7bf9c729Steve Block/* 268513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (c) 2006-2009, Google Inc. All rights reserved. 368513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (c) 2009 Torch Mobile, Inc. All rights reserved. 468513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 568513a70bcd92384395513322f1b801e7bf9c729Steve Block * 668513a70bcd92384395513322f1b801e7bf9c729Steve Block * Redistribution and use in source and binary forms, with or without 768513a70bcd92384395513322f1b801e7bf9c729Steve Block * modification, are permitted provided that the following conditions are 868513a70bcd92384395513322f1b801e7bf9c729Steve Block * met: 968513a70bcd92384395513322f1b801e7bf9c729Steve Block * 1068513a70bcd92384395513322f1b801e7bf9c729Steve Block * * Redistributions of source code must retain the above copyright 1168513a70bcd92384395513322f1b801e7bf9c729Steve Block * notice, this list of conditions and the following disclaimer. 1268513a70bcd92384395513322f1b801e7bf9c729Steve Block * * Redistributions in binary form must reproduce the above 1368513a70bcd92384395513322f1b801e7bf9c729Steve Block * copyright notice, this list of conditions and the following disclaimer 1468513a70bcd92384395513322f1b801e7bf9c729Steve Block * in the documentation and/or other materials provided with the 1568513a70bcd92384395513322f1b801e7bf9c729Steve Block * distribution. 1668513a70bcd92384395513322f1b801e7bf9c729Steve Block * * Neither the name of Google Inc. nor the names of its 1768513a70bcd92384395513322f1b801e7bf9c729Steve Block * contributors may be used to endorse or promote products derived from 1868513a70bcd92384395513322f1b801e7bf9c729Steve Block * this software without specific prior written permission. 1968513a70bcd92384395513322f1b801e7bf9c729Steve Block * 2068513a70bcd92384395513322f1b801e7bf9c729Steve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2168513a70bcd92384395513322f1b801e7bf9c729Steve Block * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2268513a70bcd92384395513322f1b801e7bf9c729Steve Block * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2368513a70bcd92384395513322f1b801e7bf9c729Steve Block * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2468513a70bcd92384395513322f1b801e7bf9c729Steve Block * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2568513a70bcd92384395513322f1b801e7bf9c729Steve Block * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2668513a70bcd92384395513322f1b801e7bf9c729Steve Block * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2768513a70bcd92384395513322f1b801e7bf9c729Steve Block * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2868513a70bcd92384395513322f1b801e7bf9c729Steve Block * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2968513a70bcd92384395513322f1b801e7bf9c729Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3068513a70bcd92384395513322f1b801e7bf9c729Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3168513a70bcd92384395513322f1b801e7bf9c729Steve Block */ 3268513a70bcd92384395513322f1b801e7bf9c729Steve Block 3368513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "config.h" 3468513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "PNGImageEncoder.h" 3568513a70bcd92384395513322f1b801e7bf9c729Steve Block 3668513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "IntSize.h" 3768513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "png.h" 3868513a70bcd92384395513322f1b801e7bf9c729Steve Block#include <wtf/Vector.h> 3968513a70bcd92384395513322f1b801e7bf9c729Steve Block 4068513a70bcd92384395513322f1b801e7bf9c729Steve Blocknamespace WebCore { 4168513a70bcd92384395513322f1b801e7bf9c729Steve Block 4268513a70bcd92384395513322f1b801e7bf9c729Steve Block// Encoder -------------------------------------------------------------------- 4368513a70bcd92384395513322f1b801e7bf9c729Steve Block// 4468513a70bcd92384395513322f1b801e7bf9c729Steve Block// This section of the code is based on nsPNGEncoder.cpp in Mozilla 4568513a70bcd92384395513322f1b801e7bf9c729Steve Block// (Copyright 2005 Google Inc.) 4668513a70bcd92384395513322f1b801e7bf9c729Steve Block 4768513a70bcd92384395513322f1b801e7bf9c729Steve Block// Passed around as the io_ptr in the png structs so our callbacks know where 4868513a70bcd92384395513322f1b801e7bf9c729Steve Block// to write data. 4968513a70bcd92384395513322f1b801e7bf9c729Steve Blockstruct PNGEncoderState { 5068513a70bcd92384395513322f1b801e7bf9c729Steve Block PNGEncoderState(Vector<char>* o) : m_dump(o) {} 5168513a70bcd92384395513322f1b801e7bf9c729Steve Block Vector<char>* m_dump; 5268513a70bcd92384395513322f1b801e7bf9c729Steve Block}; 5368513a70bcd92384395513322f1b801e7bf9c729Steve Block 5468513a70bcd92384395513322f1b801e7bf9c729Steve Block// Called by libpng to flush its internal buffer to ours. 5568513a70bcd92384395513322f1b801e7bf9c729Steve Blockvoid encoderWriteCallback(png_structp png, png_bytep data, png_size_t size) 5668513a70bcd92384395513322f1b801e7bf9c729Steve Block{ 5768513a70bcd92384395513322f1b801e7bf9c729Steve Block PNGEncoderState* state = static_cast<PNGEncoderState*>(png_get_io_ptr(png)); 5868513a70bcd92384395513322f1b801e7bf9c729Steve Block ASSERT(state->m_dump); 5968513a70bcd92384395513322f1b801e7bf9c729Steve Block 6068513a70bcd92384395513322f1b801e7bf9c729Steve Block size_t oldSize = state->m_dump->size(); 6168513a70bcd92384395513322f1b801e7bf9c729Steve Block state->m_dump->resize(oldSize + size); 6268513a70bcd92384395513322f1b801e7bf9c729Steve Block char* destination = state->m_dump->data() + oldSize; 6368513a70bcd92384395513322f1b801e7bf9c729Steve Block memcpy(destination, data, size); 6468513a70bcd92384395513322f1b801e7bf9c729Steve Block} 6568513a70bcd92384395513322f1b801e7bf9c729Steve Block 6668513a70bcd92384395513322f1b801e7bf9c729Steve Block// Automatically destroys the given write structs on destruction to make 6768513a70bcd92384395513322f1b801e7bf9c729Steve Block// cleanup and error handling code cleaner. 6868513a70bcd92384395513322f1b801e7bf9c729Steve Blockclass PNGWriteStructDestroyer { 6968513a70bcd92384395513322f1b801e7bf9c729Steve Blockpublic: 7068513a70bcd92384395513322f1b801e7bf9c729Steve Block PNGWriteStructDestroyer(png_struct** ps, png_info** pi) 7168513a70bcd92384395513322f1b801e7bf9c729Steve Block : m_pngStruct(ps) 7268513a70bcd92384395513322f1b801e7bf9c729Steve Block , m_pngInfo(pi) 7368513a70bcd92384395513322f1b801e7bf9c729Steve Block { 7468513a70bcd92384395513322f1b801e7bf9c729Steve Block } 7568513a70bcd92384395513322f1b801e7bf9c729Steve Block 7668513a70bcd92384395513322f1b801e7bf9c729Steve Block ~PNGWriteStructDestroyer() 7768513a70bcd92384395513322f1b801e7bf9c729Steve Block { 7868513a70bcd92384395513322f1b801e7bf9c729Steve Block png_destroy_write_struct(m_pngStruct, m_pngInfo); 7968513a70bcd92384395513322f1b801e7bf9c729Steve Block } 8068513a70bcd92384395513322f1b801e7bf9c729Steve Block 8168513a70bcd92384395513322f1b801e7bf9c729Steve Blockprivate: 8268513a70bcd92384395513322f1b801e7bf9c729Steve Block png_struct** m_pngStruct; 8368513a70bcd92384395513322f1b801e7bf9c729Steve Block png_info** m_pngInfo; 8468513a70bcd92384395513322f1b801e7bf9c729Steve Block}; 8568513a70bcd92384395513322f1b801e7bf9c729Steve Block 8668513a70bcd92384395513322f1b801e7bf9c729Steve Blockbool compressRGBABigEndianToPNG(unsigned char* rgbaBigEndianData, const IntSize& size, Vector<char>& pngData) 8768513a70bcd92384395513322f1b801e7bf9c729Steve Block{ 8868513a70bcd92384395513322f1b801e7bf9c729Steve Block png_struct* pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); 8968513a70bcd92384395513322f1b801e7bf9c729Steve Block if (!pngPtr) 9068513a70bcd92384395513322f1b801e7bf9c729Steve Block return false; 9168513a70bcd92384395513322f1b801e7bf9c729Steve Block 9268513a70bcd92384395513322f1b801e7bf9c729Steve Block png_info* infoPtr = png_create_info_struct(pngPtr); 9368513a70bcd92384395513322f1b801e7bf9c729Steve Block if (!infoPtr) { 9468513a70bcd92384395513322f1b801e7bf9c729Steve Block png_destroy_write_struct(&pngPtr, 0); 9568513a70bcd92384395513322f1b801e7bf9c729Steve Block return false; 9668513a70bcd92384395513322f1b801e7bf9c729Steve Block } 9768513a70bcd92384395513322f1b801e7bf9c729Steve Block PNGWriteStructDestroyer destroyer(&pngPtr, &infoPtr); 9868513a70bcd92384395513322f1b801e7bf9c729Steve Block 9968513a70bcd92384395513322f1b801e7bf9c729Steve Block // The destroyer will ensure that the structures are cleaned up in this 10068513a70bcd92384395513322f1b801e7bf9c729Steve Block // case, even though we may get here as a jump from random parts of the 10168513a70bcd92384395513322f1b801e7bf9c729Steve Block // PNG library called below. 10268513a70bcd92384395513322f1b801e7bf9c729Steve Block if (setjmp(png_jmpbuf(pngPtr))) 10368513a70bcd92384395513322f1b801e7bf9c729Steve Block return false; 10468513a70bcd92384395513322f1b801e7bf9c729Steve Block 10568513a70bcd92384395513322f1b801e7bf9c729Steve Block // Set our callback for libpng to give us the data. 10668513a70bcd92384395513322f1b801e7bf9c729Steve Block PNGEncoderState state(&pngData); 10768513a70bcd92384395513322f1b801e7bf9c729Steve Block png_set_write_fn(pngPtr, &state, encoderWriteCallback, 0); 10868513a70bcd92384395513322f1b801e7bf9c729Steve Block 10968513a70bcd92384395513322f1b801e7bf9c729Steve Block int pngOutputColorType = PNG_COLOR_TYPE_RGB_ALPHA; 11068513a70bcd92384395513322f1b801e7bf9c729Steve Block 11168513a70bcd92384395513322f1b801e7bf9c729Steve Block png_set_IHDR(pngPtr, infoPtr, size.width(), size.height(), 8, pngOutputColorType, 11268513a70bcd92384395513322f1b801e7bf9c729Steve Block PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, 11368513a70bcd92384395513322f1b801e7bf9c729Steve Block PNG_FILTER_TYPE_DEFAULT); 11468513a70bcd92384395513322f1b801e7bf9c729Steve Block png_write_info(pngPtr, infoPtr); 11568513a70bcd92384395513322f1b801e7bf9c729Steve Block 11668513a70bcd92384395513322f1b801e7bf9c729Steve Block unsigned bytesPerRow = size.width() * 4; 11768513a70bcd92384395513322f1b801e7bf9c729Steve Block for (unsigned y = 0; y < size.height(); ++y) { 11868513a70bcd92384395513322f1b801e7bf9c729Steve Block png_write_row(pngPtr, rgbaBigEndianData); 11968513a70bcd92384395513322f1b801e7bf9c729Steve Block rgbaBigEndianData += bytesPerRow; 12068513a70bcd92384395513322f1b801e7bf9c729Steve Block } 12168513a70bcd92384395513322f1b801e7bf9c729Steve Block 12268513a70bcd92384395513322f1b801e7bf9c729Steve Block png_write_end(pngPtr, infoPtr); 12368513a70bcd92384395513322f1b801e7bf9c729Steve Block return true; 12468513a70bcd92384395513322f1b801e7bf9c729Steve Block} 12568513a70bcd92384395513322f1b801e7bf9c729Steve Block 12668513a70bcd92384395513322f1b801e7bf9c729Steve Block} // namespace WebCore 127