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