pngwriter.cc revision 12582
172SN/A/*
211274Sshingarov@labware.com * Copyright (c) 2017 ARM Limited
310597Sgabeblack@google.com * All rights reserved
41762SN/A *
572SN/A * The license below extends only to copyright in the software and shall
672SN/A * not be construed as granting a license to any other intellectual
772SN/A * property including but not limited to intellectual property relating
872SN/A * to a hardware implementation of the functionality of the software
972SN/A * licensed hereunder.  You may use the software subject to the license
1072SN/A * terms below provided that you ensure that this notice is replicated
1172SN/A * unmodified and in its entirety in all distributions of the software,
1272SN/A * modified or unmodified, in source code or in binary form.
1372SN/A *
1472SN/A * Redistribution and use in source and binary forms, with or without
1572SN/A * modification, are permitted provided that the following conditions are
1672SN/A * met: redistributions of source code must retain the above copyright
1772SN/A * notice, this list of conditions and the following disclaimer;
1872SN/A * redistributions in binary form must reproduce the above copyright
1972SN/A * notice, this list of conditions and the following disclaimer in the
2072SN/A * documentation and/or other materials provided with the distribution;
2172SN/A * neither the name of the copyright holders nor the names of its
2272SN/A * contributors may be used to endorse or promote products derived from
2372SN/A * this software without specific prior written permission.
2472SN/A *
2572SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2672SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2772SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2872SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302665Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3111274Sshingarov@labware.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3272SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3372SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
358332Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
368332Snate@binkert.org *
372SN/A * Authors: Giacomo Travaglini
382SN/A */
392SN/A
402SN/A/**
412SN/A * @file Definition of a class that writes a frame buffer to a png
422SN/A */
432SN/A
445543Ssaidi@eecs.umich.edu#include "base/pngwriter.hh"
455543Ssaidi@eecs.umich.edu
462SN/Aextern "C"
472SN/A{
482SN/A#include <png.h>
492SN/A}
502SN/A
512SN/A#include <cstdio>
522SN/A#include <cstdlib>
532SN/A
542SN/A#include "base/logging.hh"
552SN/A
562SN/Aconst char* PngWriter::_imgExtension = "png";
575543Ssaidi@eecs.umich.edu
585543Ssaidi@eecs.umich.edu/**
592SN/A * Write callback to use with libpng APIs
602SN/A *
612SN/A * @param pngPtr  pointer to the png_struct structure
622SN/A * @param data    pointer to the data being written
632SN/A * @param length  number of bytes being written
642SN/A */
652SN/Astatic void
662SN/AwritePng(png_structp pngPtr, png_bytep data, png_size_t length)
672SN/A{
682SN/A    // Here we get our IO pointer back from the write struct
692SN/A    // and we cast it into a ostream* type.
702SN/A    std::ostream* strmPtr = reinterpret_cast<std::ostream*>(
712SN/A        png_get_io_ptr(pngPtr)
722SN/A    );
732SN/A
742SN/A    // Write length bytes to data
755543Ssaidi@eecs.umich.edu    strmPtr->write(reinterpret_cast<const char *>(data), length);
762SN/A}
772SN/A
782SN/Astruct PngWriter::PngStructHandle {
792SN/A  private:
802SN/A    // Make PngStructHandle uncopyable
812SN/A    PngStructHandle(const PngStructHandle&) = delete;
822SN/A    PngStructHandle& operator=(const PngStructHandle&) = delete;
832SN/A  public:
842SN/A
852SN/A    PngStructHandle() :
862SN/A        pngWriteP(NULL), pngInfoP(NULL)
872SN/A    {
882SN/A        // Creating write structure
892SN/A        pngWriteP = png_create_write_struct(
902SN/A            PNG_LIBPNG_VER_STRING, NULL, NULL, NULL
912SN/A        );
922SN/A
932SN/A        if (pngWriteP) {
942SN/A            // Creating info structure
955543Ssaidi@eecs.umich.edu            pngInfoP = png_create_info_struct(pngWriteP);
965543Ssaidi@eecs.umich.edu        }
972SN/A    }
982SN/A
992SN/A    ~PngStructHandle()
1002SN/A    {
1012SN/A        if (pngWriteP) {
1022SN/A            png_destroy_write_struct(&pngWriteP, &pngInfoP);
1032SN/A        }
1042SN/A    }
1052SN/A
1062SN/A    /** Pointer to PNG Write struct */
1072SN/A    png_structp pngWriteP;
1082SN/A
1092SN/A    /** Pointer to PNG Info struct */
1102SN/A    png_infop pngInfoP;
1112SN/A};
1122SN/A
1132SN/Avoid
1142SN/APngWriter::write(std::ostream &png) const
1152SN/A{
1162SN/A
1172SN/A    // Height of the frame buffer
1182SN/A    unsigned height = fb.height();
1192SN/A    unsigned width  = fb.width();
1202SN/A
1212SN/A    // Do not write if frame buffer is empty
12211793Sbrandon.potter@amd.com    if (!fb.area()) {
12311793Sbrandon.potter@amd.com        png.flush();
1242SN/A        return;
1258229Snate@binkert.org    }
1262SN/A
12711793Sbrandon.potter@amd.com    // Initialize Png structures
12812019Sgabeblack@google.com    PngStructHandle handle;
1296712Snate@binkert.org
1301717SN/A    // Png info/write pointers.
1312SN/A    png_structp pngPtr  = handle.pngWriteP;
1322521SN/A    png_infop   infoPtr = handle.pngInfoP;
13356SN/A
13456SN/A    if (!pngPtr) {
13556SN/A        warn("Frame buffer dump aborted: Unable to create"
1366658Snate@binkert.org             "Png Write Struct\n");
13710597Sgabeblack@google.com        return;
1388229Snate@binkert.org    }
1392680Sktlim@umich.edu
1408232Snate@binkert.org    if (!infoPtr) {
14111793Sbrandon.potter@amd.com        warn("Frame buffer dump aborted: Unable to create"
1422521SN/A             "Png Info Struct\n");
1438706Sandreas.hansson@arm.com        return;
1448784Sgblack@eecs.umich.edu    }
1451717SN/A
1462SN/A    // We cannot use default libpng write function since it requires
1472SN/A    // a file pointer (FILE*), whereas we want to use the ostream.
1482107SN/A    // The following function replaces the write function with a custom
1492SN/A    // one provided by us (writePng)
15012031Sgabeblack@google.com    png_set_write_fn(pngPtr, (png_voidp)&png, writePng, NULL);
15112031Sgabeblack@google.com
15212031Sgabeblack@google.com    png_set_IHDR(pngPtr, infoPtr, width, height, 8,
15312031Sgabeblack@google.com                 PNG_COLOR_TYPE_RGB,
15412031Sgabeblack@google.com                 PNG_INTERLACE_NONE,
15512031Sgabeblack@google.com                 PNG_COMPRESSION_TYPE_DEFAULT,
15612031Sgabeblack@google.com                 PNG_FILTER_TYPE_DEFAULT);
1573536Sgblack@eecs.umich.edu
1582SN/A    png_write_info(pngPtr, infoPtr);
15912449Sgabeblack@google.com
16012449Sgabeblack@google.com    // libpng requires an array of pointers to the frame buffer's rows.
16112449Sgabeblack@google.com    std::vector<PixelType> rowPacked(width);
16212449Sgabeblack@google.com    for (unsigned y=0; y < height; ++y) {
16312449Sgabeblack@google.com        for (unsigned x=0; x < width; ++x) {
16412449Sgabeblack@google.com            rowPacked[x] = fb.pixel(x, y);
16512449Sgabeblack@google.com        }
16612449Sgabeblack@google.com
16712449Sgabeblack@google.com        png_write_row(pngPtr,
16812449Sgabeblack@google.com            reinterpret_cast<png_bytep>(rowPacked.data())
16912449Sgabeblack@google.com        );
17012449Sgabeblack@google.com    }
17112449Sgabeblack@google.com
17212449Sgabeblack@google.com    // End of write
17312449Sgabeblack@google.com    png_write_end(pngPtr, NULL);
17412449Sgabeblack@google.com}
17512449Sgabeblack@google.com
17612449Sgabeblack@google.com