Home | History | Annotate | Download | only in image-encoders
      1 /*
      2  * Copyright (c) 2006-2009, Google Inc. All rights reserved.
      3  * Copyright (c) 2009 Torch Mobile, Inc. All rights reserved.
      4  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions are
      8  * met:
      9  *
     10  *     * Redistributions of source code must retain the above copyright
     11  * notice, this list of conditions and the following disclaimer.
     12  *     * Redistributions in binary form must reproduce the above
     13  * copyright notice, this list of conditions and the following disclaimer
     14  * in the documentation and/or other materials provided with the
     15  * distribution.
     16  *     * Neither the name of Google Inc. nor the names of its
     17  * contributors may be used to endorse or promote products derived from
     18  * this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include "config.h"
     34 #include "PNGImageEncoder.h"
     35 
     36 #include "IntSize.h"
     37 #include "png.h"
     38 #include <wtf/Vector.h>
     39 
     40 namespace WebCore {
     41 
     42 // Encoder --------------------------------------------------------------------
     43 //
     44 // This section of the code is based on nsPNGEncoder.cpp in Mozilla
     45 // (Copyright 2005 Google Inc.)
     46 
     47 // Passed around as the io_ptr in the png structs so our callbacks know where
     48 // to write data.
     49 struct PNGEncoderState {
     50     PNGEncoderState(Vector<char>* o) : m_dump(o) {}
     51     Vector<char>* m_dump;
     52 };
     53 
     54 // Called by libpng to flush its internal buffer to ours.
     55 void encoderWriteCallback(png_structp png, png_bytep data, png_size_t size)
     56 {
     57     PNGEncoderState* state = static_cast<PNGEncoderState*>(png_get_io_ptr(png));
     58     ASSERT(state->m_dump);
     59 
     60     size_t oldSize = state->m_dump->size();
     61     state->m_dump->resize(oldSize + size);
     62     char* destination = state->m_dump->data() + oldSize;
     63     memcpy(destination, data, size);
     64 }
     65 
     66 // Automatically destroys the given write structs on destruction to make
     67 // cleanup and error handling code cleaner.
     68 class PNGWriteStructDestroyer {
     69 public:
     70     PNGWriteStructDestroyer(png_struct** ps, png_info** pi)
     71         : m_pngStruct(ps)
     72         , m_pngInfo(pi)
     73     {
     74     }
     75 
     76     ~PNGWriteStructDestroyer()
     77     {
     78         png_destroy_write_struct(m_pngStruct, m_pngInfo);
     79     }
     80 
     81 private:
     82     png_struct** m_pngStruct;
     83     png_info** m_pngInfo;
     84 };
     85 
     86 bool compressRGBABigEndianToPNG(unsigned char* rgbaBigEndianData, const IntSize& size, Vector<char>& pngData)
     87 {
     88     png_struct* pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL);
     89     if (!pngPtr)
     90         return false;
     91 
     92     png_info* infoPtr = png_create_info_struct(pngPtr);
     93     if (!infoPtr) {
     94         png_destroy_write_struct(&pngPtr, 0);
     95         return false;
     96     }
     97     PNGWriteStructDestroyer destroyer(&pngPtr, &infoPtr);
     98 
     99     // The destroyer will ensure that the structures are cleaned up in this
    100     // case, even though we may get here as a jump from random parts of the
    101     // PNG library called below.
    102     if (setjmp(png_jmpbuf(pngPtr)))
    103         return false;
    104 
    105     // Set our callback for libpng to give us the data.
    106     PNGEncoderState state(&pngData);
    107     png_set_write_fn(pngPtr, &state, encoderWriteCallback, 0);
    108 
    109     int pngOutputColorType = PNG_COLOR_TYPE_RGB_ALPHA;
    110 
    111     png_set_IHDR(pngPtr, infoPtr, size.width(), size.height(), 8, pngOutputColorType,
    112                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
    113                  PNG_FILTER_TYPE_DEFAULT);
    114     png_write_info(pngPtr, infoPtr);
    115 
    116     unsigned bytesPerRow = size.width() * 4;
    117     for (unsigned y = 0; y < size.height(); ++y) {
    118         png_write_row(pngPtr, rgbaBigEndianData);
    119         rgbaBigEndianData += bytesPerRow;
    120     }
    121 
    122     png_write_end(pngPtr, infoPtr);
    123     return true;
    124 }
    125 
    126 } // namespace WebCore
    127