pngwriter.cc revision 12334
112230Sgiacomo.travaglini@arm.com/* 212230Sgiacomo.travaglini@arm.com * Copyright (c) 2017 ARM Limited 312230Sgiacomo.travaglini@arm.com * All rights reserved 412230Sgiacomo.travaglini@arm.com * 512230Sgiacomo.travaglini@arm.com * The license below extends only to copyright in the software and shall 612230Sgiacomo.travaglini@arm.com * not be construed as granting a license to any other intellectual 712230Sgiacomo.travaglini@arm.com * property including but not limited to intellectual property relating 812230Sgiacomo.travaglini@arm.com * to a hardware implementation of the functionality of the software 912230Sgiacomo.travaglini@arm.com * licensed hereunder. You may use the software subject to the license 1012230Sgiacomo.travaglini@arm.com * terms below provided that you ensure that this notice is replicated 1112230Sgiacomo.travaglini@arm.com * unmodified and in its entirety in all distributions of the software, 1212230Sgiacomo.travaglini@arm.com * modified or unmodified, in source code or in binary form. 1312230Sgiacomo.travaglini@arm.com * 1412230Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without 1512230Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions are 1612230Sgiacomo.travaglini@arm.com * met: redistributions of source code must retain the above copyright 1712230Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer; 1812230Sgiacomo.travaglini@arm.com * redistributions in binary form must reproduce the above copyright 1912230Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer in the 2012230Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution; 2112230Sgiacomo.travaglini@arm.com * neither the name of the copyright holders nor the names of its 2212230Sgiacomo.travaglini@arm.com * contributors may be used to endorse or promote products derived from 2312230Sgiacomo.travaglini@arm.com * this software without specific prior written permission. 2412230Sgiacomo.travaglini@arm.com * 2512230Sgiacomo.travaglini@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2612230Sgiacomo.travaglini@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2712230Sgiacomo.travaglini@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2812230Sgiacomo.travaglini@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2912230Sgiacomo.travaglini@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3012230Sgiacomo.travaglini@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3112230Sgiacomo.travaglini@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3212230Sgiacomo.travaglini@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3312230Sgiacomo.travaglini@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3412230Sgiacomo.travaglini@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3512230Sgiacomo.travaglini@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3612230Sgiacomo.travaglini@arm.com * 3712230Sgiacomo.travaglini@arm.com * Authors: Giacomo Travaglini 3812230Sgiacomo.travaglini@arm.com */ 3912230Sgiacomo.travaglini@arm.com 4012230Sgiacomo.travaglini@arm.com/** 4112230Sgiacomo.travaglini@arm.com * @file Definition of a class that writes a frame buffer to a png 4212230Sgiacomo.travaglini@arm.com */ 4312230Sgiacomo.travaglini@arm.com 4412230Sgiacomo.travaglini@arm.com#include "base/pngwriter.hh" 4512230Sgiacomo.travaglini@arm.com 4612230Sgiacomo.travaglini@arm.comextern "C" 4712230Sgiacomo.travaglini@arm.com{ 4812230Sgiacomo.travaglini@arm.com#include <png.h> 4912230Sgiacomo.travaglini@arm.com} 5012230Sgiacomo.travaglini@arm.com 5112230Sgiacomo.travaglini@arm.com#include <cstdio> 5212230Sgiacomo.travaglini@arm.com#include <cstdlib> 5312230Sgiacomo.travaglini@arm.com 5412334Sgabeblack@google.com#include "base/logging.hh" 5512230Sgiacomo.travaglini@arm.com 5612230Sgiacomo.travaglini@arm.comconst char* PngWriter::_imgExtension = "png"; 5712230Sgiacomo.travaglini@arm.com 5812230Sgiacomo.travaglini@arm.com/** 5912230Sgiacomo.travaglini@arm.com * Write callback to use with libpng APIs 6012230Sgiacomo.travaglini@arm.com * 6112230Sgiacomo.travaglini@arm.com * @param pngPtr pointer to the png_struct structure 6212230Sgiacomo.travaglini@arm.com * @param data pointer to the data being written 6312230Sgiacomo.travaglini@arm.com * @param length number of bytes being written 6412230Sgiacomo.travaglini@arm.com */ 6512230Sgiacomo.travaglini@arm.comstatic void 6612230Sgiacomo.travaglini@arm.comwritePng(png_structp pngPtr, png_bytep data, png_size_t length) 6712230Sgiacomo.travaglini@arm.com{ 6812230Sgiacomo.travaglini@arm.com // Here we get our IO pointer back from the write struct 6912230Sgiacomo.travaglini@arm.com // and we cast it into a ostream* type. 7012230Sgiacomo.travaglini@arm.com std::ostream* strmPtr = reinterpret_cast<std::ostream*>( 7112230Sgiacomo.travaglini@arm.com png_get_io_ptr(pngPtr) 7212230Sgiacomo.travaglini@arm.com ); 7312230Sgiacomo.travaglini@arm.com 7412230Sgiacomo.travaglini@arm.com // Write length bytes to data 7512230Sgiacomo.travaglini@arm.com strmPtr->write(reinterpret_cast<const char *>(data), length); 7612230Sgiacomo.travaglini@arm.com} 7712230Sgiacomo.travaglini@arm.com 7812230Sgiacomo.travaglini@arm.comstruct PngWriter::PngStructHandle { 7912230Sgiacomo.travaglini@arm.com private: 8012230Sgiacomo.travaglini@arm.com // Make PngStructHandle uncopyable 8112230Sgiacomo.travaglini@arm.com PngStructHandle(const PngStructHandle&) = delete; 8212230Sgiacomo.travaglini@arm.com PngStructHandle& operator=(const PngStructHandle&) = delete; 8312230Sgiacomo.travaglini@arm.com public: 8412230Sgiacomo.travaglini@arm.com 8512230Sgiacomo.travaglini@arm.com PngStructHandle() : 8612230Sgiacomo.travaglini@arm.com pngWriteP(NULL), pngInfoP(NULL) 8712230Sgiacomo.travaglini@arm.com { 8812230Sgiacomo.travaglini@arm.com // Creating write structure 8912230Sgiacomo.travaglini@arm.com pngWriteP = png_create_write_struct( 9012230Sgiacomo.travaglini@arm.com PNG_LIBPNG_VER_STRING, NULL, NULL, NULL 9112230Sgiacomo.travaglini@arm.com ); 9212230Sgiacomo.travaglini@arm.com 9312230Sgiacomo.travaglini@arm.com if (pngWriteP) { 9412230Sgiacomo.travaglini@arm.com // Creating info structure 9512230Sgiacomo.travaglini@arm.com pngInfoP = png_create_info_struct(pngWriteP); 9612230Sgiacomo.travaglini@arm.com } 9712230Sgiacomo.travaglini@arm.com } 9812230Sgiacomo.travaglini@arm.com 9912230Sgiacomo.travaglini@arm.com ~PngStructHandle() 10012230Sgiacomo.travaglini@arm.com { 10112230Sgiacomo.travaglini@arm.com if (pngWriteP) { 10212230Sgiacomo.travaglini@arm.com png_destroy_write_struct(&pngWriteP, &pngInfoP); 10312230Sgiacomo.travaglini@arm.com } 10412230Sgiacomo.travaglini@arm.com } 10512230Sgiacomo.travaglini@arm.com 10612230Sgiacomo.travaglini@arm.com /** Pointer to PNG Write struct */ 10712230Sgiacomo.travaglini@arm.com png_structp pngWriteP; 10812230Sgiacomo.travaglini@arm.com 10912230Sgiacomo.travaglini@arm.com /** Pointer to PNG Info struct */ 11012230Sgiacomo.travaglini@arm.com png_infop pngInfoP; 11112230Sgiacomo.travaglini@arm.com}; 11212230Sgiacomo.travaglini@arm.com 11312230Sgiacomo.travaglini@arm.comvoid 11412230Sgiacomo.travaglini@arm.comPngWriter::write(std::ostream &png) const 11512230Sgiacomo.travaglini@arm.com{ 11612230Sgiacomo.travaglini@arm.com 11712230Sgiacomo.travaglini@arm.com // Height of the frame buffer 11812230Sgiacomo.travaglini@arm.com unsigned height = fb.height(); 11912230Sgiacomo.travaglini@arm.com unsigned width = fb.width(); 12012230Sgiacomo.travaglini@arm.com 12112230Sgiacomo.travaglini@arm.com // Do not write if frame buffer is empty 12212230Sgiacomo.travaglini@arm.com if (!fb.area()) { 12312230Sgiacomo.travaglini@arm.com png.flush(); 12412230Sgiacomo.travaglini@arm.com return; 12512230Sgiacomo.travaglini@arm.com } 12612230Sgiacomo.travaglini@arm.com 12712230Sgiacomo.travaglini@arm.com // Initialize Png structures 12812230Sgiacomo.travaglini@arm.com PngStructHandle handle; 12912230Sgiacomo.travaglini@arm.com 13012230Sgiacomo.travaglini@arm.com // Png info/write pointers. 13112230Sgiacomo.travaglini@arm.com png_structp pngPtr = handle.pngWriteP; 13212230Sgiacomo.travaglini@arm.com png_infop infoPtr = handle.pngInfoP; 13312230Sgiacomo.travaglini@arm.com 13412230Sgiacomo.travaglini@arm.com if (!pngPtr) { 13512230Sgiacomo.travaglini@arm.com warn("Frame buffer dump aborted: Unable to create" 13612230Sgiacomo.travaglini@arm.com "Png Write Struct\n"); 13712230Sgiacomo.travaglini@arm.com return; 13812230Sgiacomo.travaglini@arm.com } 13912230Sgiacomo.travaglini@arm.com 14012230Sgiacomo.travaglini@arm.com if (!infoPtr) { 14112230Sgiacomo.travaglini@arm.com warn("Frame buffer dump aborted: Unable to create" 14212230Sgiacomo.travaglini@arm.com "Png Info Struct\n"); 14312230Sgiacomo.travaglini@arm.com return; 14412230Sgiacomo.travaglini@arm.com } 14512230Sgiacomo.travaglini@arm.com 14612230Sgiacomo.travaglini@arm.com // We cannot use default libpng write function since it requires 14712230Sgiacomo.travaglini@arm.com // a file pointer (FILE*), whereas we want to use the ostream. 14812230Sgiacomo.travaglini@arm.com // The following function replaces the write function with a custom 14912230Sgiacomo.travaglini@arm.com // one provided by us (writePng) 15012230Sgiacomo.travaglini@arm.com png_set_write_fn(pngPtr, (png_voidp)&png, writePng, NULL); 15112230Sgiacomo.travaglini@arm.com 15212230Sgiacomo.travaglini@arm.com png_set_IHDR(pngPtr, infoPtr, width, height, 8, 15312230Sgiacomo.travaglini@arm.com PNG_COLOR_TYPE_RGB, 15412230Sgiacomo.travaglini@arm.com PNG_INTERLACE_NONE, 15512230Sgiacomo.travaglini@arm.com PNG_COMPRESSION_TYPE_DEFAULT, 15612230Sgiacomo.travaglini@arm.com PNG_FILTER_TYPE_DEFAULT); 15712230Sgiacomo.travaglini@arm.com 15812230Sgiacomo.travaglini@arm.com png_write_info(pngPtr, infoPtr); 15912230Sgiacomo.travaglini@arm.com 16012230Sgiacomo.travaglini@arm.com // libpng requires an array of pointers to the frame buffer's rows. 16112230Sgiacomo.travaglini@arm.com std::vector<PixelType> rowPacked(width); 16212230Sgiacomo.travaglini@arm.com for (unsigned y=0; y < height; ++y) { 16312230Sgiacomo.travaglini@arm.com for (unsigned x=0; x < height; ++x) { 16412230Sgiacomo.travaglini@arm.com rowPacked[x] = fb.pixel(x, y); 16512230Sgiacomo.travaglini@arm.com } 16612230Sgiacomo.travaglini@arm.com 16712230Sgiacomo.travaglini@arm.com png_write_row(pngPtr, 16812230Sgiacomo.travaglini@arm.com reinterpret_cast<png_bytep>(rowPacked.data()) 16912230Sgiacomo.travaglini@arm.com ); 17012230Sgiacomo.travaglini@arm.com } 17112230Sgiacomo.travaglini@arm.com 17212230Sgiacomo.travaglini@arm.com // End of write 17312230Sgiacomo.travaglini@arm.com png_write_end(pngPtr, NULL); 17412230Sgiacomo.travaglini@arm.com} 17512230Sgiacomo.travaglini@arm.com 176