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