pngwriter.cc revision 12582:e4f0727b353e
112838Sgabeblack@google.com/* 212838Sgabeblack@google.com * Copyright (c) 2017 ARM Limited 312838Sgabeblack@google.com * All rights reserved 412838Sgabeblack@google.com * 512838Sgabeblack@google.com * The license below extends only to copyright in the software and shall 612838Sgabeblack@google.com * not be construed as granting a license to any other intellectual 712838Sgabeblack@google.com * property including but not limited to intellectual property relating 812838Sgabeblack@google.com * to a hardware implementation of the functionality of the software 912838Sgabeblack@google.com * licensed hereunder. You may use the software subject to the license 1012838Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated 1112838Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software, 1212838Sgabeblack@google.com * modified or unmodified, in source code or in binary form. 1312838Sgabeblack@google.com * 1412838Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 1512838Sgabeblack@google.com * modification, are permitted provided that the following conditions are 1612838Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 1712838Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 1812838Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1912838Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 2012838Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 2112838Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 2212838Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 2312838Sgabeblack@google.com * this software without specific prior written permission. 2412838Sgabeblack@google.com * 2512838Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2612838Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2712838Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2812838Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2912838Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3012838Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3112952Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3212953Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3312960Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3412838Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3513128Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3612838Sgabeblack@google.com * 3712838Sgabeblack@google.com * Authors: Giacomo Travaglini 3812838Sgabeblack@google.com */ 3912838Sgabeblack@google.com 4012838Sgabeblack@google.com/** 4112838Sgabeblack@google.com * @file Definition of a class that writes a frame buffer to a png 4212838Sgabeblack@google.com */ 4312994Sgabeblack@google.com 4412838Sgabeblack@google.com#include "base/pngwriter.hh" 4512838Sgabeblack@google.com 4612838Sgabeblack@google.comextern "C" 4712838Sgabeblack@google.com{ 4812838Sgabeblack@google.com#include <png.h> 4912994Sgabeblack@google.com} 5012838Sgabeblack@google.com 5112838Sgabeblack@google.com#include <cstdio> 5212994Sgabeblack@google.com#include <cstdlib> 5312994Sgabeblack@google.com 5412994Sgabeblack@google.com#include "base/logging.hh" 5512994Sgabeblack@google.com 5612952Sgabeblack@google.comconst char* PngWriter::_imgExtension = "png"; 5712838Sgabeblack@google.com 5812838Sgabeblack@google.com/** 5913087Sgabeblack@google.com * Write callback to use with libpng APIs 6013087Sgabeblack@google.com * 6112939Sgabeblack@google.com * @param pngPtr pointer to the png_struct structure 6213087Sgabeblack@google.com * @param data pointer to the data being written 6313087Sgabeblack@google.com * @param length number of bytes being written 6413087Sgabeblack@google.com */ 6513087Sgabeblack@google.comstatic void 6613087Sgabeblack@google.comwritePng(png_structp pngPtr, png_bytep data, png_size_t length) 6712939Sgabeblack@google.com{ 6812939Sgabeblack@google.com // Here we get our IO pointer back from the write struct 6912939Sgabeblack@google.com // and we cast it into a ostream* type. 7012939Sgabeblack@google.com std::ostream* strmPtr = reinterpret_cast<std::ostream*>( 7112939Sgabeblack@google.com png_get_io_ptr(pngPtr) 7212939Sgabeblack@google.com ); 7312939Sgabeblack@google.com 7412939Sgabeblack@google.com // Write length bytes to data 7512939Sgabeblack@google.com strmPtr->write(reinterpret_cast<const char *>(data), length); 7612939Sgabeblack@google.com} 7712939Sgabeblack@google.com 7812952Sgabeblack@google.comstruct PngWriter::PngStructHandle { 7912952Sgabeblack@google.com private: 8012952Sgabeblack@google.com // Make PngStructHandle uncopyable 8112952Sgabeblack@google.com PngStructHandle(const PngStructHandle&) = delete; 8212838Sgabeblack@google.com PngStructHandle& operator=(const PngStructHandle&) = delete; 8312952Sgabeblack@google.com public: 8412952Sgabeblack@google.com 8512838Sgabeblack@google.com PngStructHandle() : 8612838Sgabeblack@google.com pngWriteP(NULL), pngInfoP(NULL) 8712952Sgabeblack@google.com { 8812952Sgabeblack@google.com // Creating write structure 8912838Sgabeblack@google.com pngWriteP = png_create_write_struct( 9012952Sgabeblack@google.com PNG_LIBPNG_VER_STRING, NULL, NULL, NULL 9112952Sgabeblack@google.com ); 9212838Sgabeblack@google.com 9312838Sgabeblack@google.com if (pngWriteP) { 9412838Sgabeblack@google.com // Creating info structure 9512838Sgabeblack@google.com pngInfoP = png_create_info_struct(pngWriteP); 9612952Sgabeblack@google.com } 9712952Sgabeblack@google.com } 9812838Sgabeblack@google.com 9912838Sgabeblack@google.com ~PngStructHandle() 10012838Sgabeblack@google.com { 10112838Sgabeblack@google.com if (pngWriteP) { 10212838Sgabeblack@google.com png_destroy_write_struct(&pngWriteP, &pngInfoP); 10312838Sgabeblack@google.com } 10412952Sgabeblack@google.com } 10512838Sgabeblack@google.com 10612838Sgabeblack@google.com /** Pointer to PNG Write struct */ 10712838Sgabeblack@google.com png_structp pngWriteP; 10812838Sgabeblack@google.com 10912952Sgabeblack@google.com /** Pointer to PNG Info struct */ 11012838Sgabeblack@google.com png_infop pngInfoP; 11112952Sgabeblack@google.com}; 11212952Sgabeblack@google.com 11312952Sgabeblack@google.comvoid 11412952Sgabeblack@google.comPngWriter::write(std::ostream &png) const 11512952Sgabeblack@google.com{ 11612838Sgabeblack@google.com 11712838Sgabeblack@google.com // Height of the frame buffer 11812838Sgabeblack@google.com unsigned height = fb.height(); 11912838Sgabeblack@google.com unsigned width = fb.width(); 12012952Sgabeblack@google.com 12112838Sgabeblack@google.com // Do not write if frame buffer is empty 12212952Sgabeblack@google.com if (!fb.area()) { 12312952Sgabeblack@google.com png.flush(); 12412838Sgabeblack@google.com return; 12512838Sgabeblack@google.com } 12612838Sgabeblack@google.com 12712952Sgabeblack@google.com // Initialize Png structures 12812838Sgabeblack@google.com PngStructHandle handle; 12912952Sgabeblack@google.com 13012838Sgabeblack@google.com // Png info/write pointers. 13112838Sgabeblack@google.com png_structp pngPtr = handle.pngWriteP; 13212838Sgabeblack@google.com png_infop infoPtr = handle.pngInfoP; 13312952Sgabeblack@google.com 13412838Sgabeblack@google.com if (!pngPtr) { 13512952Sgabeblack@google.com warn("Frame buffer dump aborted: Unable to create" 13612838Sgabeblack@google.com "Png Write Struct\n"); 13712838Sgabeblack@google.com return; 13812952Sgabeblack@google.com } 13912952Sgabeblack@google.com 14012838Sgabeblack@google.com if (!infoPtr) { 14112952Sgabeblack@google.com warn("Frame buffer dump aborted: Unable to create" 14212952Sgabeblack@google.com "Png Info Struct\n"); 14312952Sgabeblack@google.com return; 14412838Sgabeblack@google.com } 14512838Sgabeblack@google.com 14612838Sgabeblack@google.com // We cannot use default libpng write function since it requires 14712838Sgabeblack@google.com // a file pointer (FILE*), whereas we want to use the ostream. 14812838Sgabeblack@google.com // The following function replaces the write function with a custom 14912838Sgabeblack@google.com // one provided by us (writePng) 15012952Sgabeblack@google.com png_set_write_fn(pngPtr, (png_voidp)&png, writePng, NULL); 15112838Sgabeblack@google.com 15212838Sgabeblack@google.com png_set_IHDR(pngPtr, infoPtr, width, height, 8, 15312838Sgabeblack@google.com PNG_COLOR_TYPE_RGB, 15412838Sgabeblack@google.com PNG_INTERLACE_NONE, 15512838Sgabeblack@google.com PNG_COMPRESSION_TYPE_DEFAULT, 15612952Sgabeblack@google.com PNG_FILTER_TYPE_DEFAULT); 15712838Sgabeblack@google.com 15812838Sgabeblack@google.com png_write_info(pngPtr, infoPtr); 15912838Sgabeblack@google.com 16012838Sgabeblack@google.com // libpng requires an array of pointers to the frame buffer's rows. 16112838Sgabeblack@google.com std::vector<PixelType> rowPacked(width); 16212952Sgabeblack@google.com for (unsigned y=0; y < height; ++y) { 16312952Sgabeblack@google.com for (unsigned x=0; x < width; ++x) { 16412838Sgabeblack@google.com rowPacked[x] = fb.pixel(x, y); 16512838Sgabeblack@google.com } 16612838Sgabeblack@google.com 16712838Sgabeblack@google.com png_write_row(pngPtr, 16812838Sgabeblack@google.com reinterpret_cast<png_bytep>(rowPacked.data()) 16912952Sgabeblack@google.com ); 17012952Sgabeblack@google.com } 17112838Sgabeblack@google.com 17212838Sgabeblack@google.com // End of write 17312838Sgabeblack@google.com png_write_end(pngPtr, NULL); 17412838Sgabeblack@google.com} 17512838Sgabeblack@google.com 17612952Sgabeblack@google.com