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