Edit

kc3-lang/angle/util/png_utils.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2020-05-07 13:40:55
    Hash : 5b35c7f6
    Message : Fix up screenshot saving for trace tests. Now works when run in a sequence. Also saves RGB images to avoid issues with the alpha being inconsistent and also flips images vertically to fix the rendering. Bug: angleproject:4615 Change-Id: I8d3b38c5d914e0ca2227320ac42a0e28acd12c4d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2187971 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Cody Northrop <cnorthrop@google.com>

  • util/png_utils.cpp
  • //
    // Copyright 2020 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // png_utils: Wrapper around libpng.
    //
    
    #include "util/png_utils.h"
    
    #include <array>
    #include <cstring>
    
    #include <png.h>
    
    namespace angle
    {
    namespace
    {
    class ScopedFILE
    {
      public:
        ScopedFILE(FILE *fp) : mFP(fp) {}
        ~ScopedFILE() { close(); }
    
        FILE *get() const { return mFP; }
    
        void close()
        {
            if (mFP)
            {
                fclose(mFP);
                mFP = nullptr;
            }
        }
    
      private:
        FILE *mFP;
    };
    }  // namespace
    
    bool SavePNGRGB(const char *fileName,
                    const char *title,
                    uint32_t width,
                    uint32_t height,
                    const std::vector<uint8_t> &data)
    {
        ScopedFILE fp(fopen(fileName, "wb"));
        if (!fp.get())
        {
            fprintf(stderr, "Error opening '%s'.\n", fileName);
            return false;
        }
    
        png_struct *writeStruct =
            png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
        if (!writeStruct)
        {
            fprintf(stderr, "Error on png_create_write_struct.\n");
            return false;
        }
    
        png_info *infoStruct = png_create_info_struct(writeStruct);
        if (!infoStruct)
        {
            fprintf(stderr, "Error on png_create_info_struct.\n");
            return false;
        }
    
        if (setjmp(png_jmpbuf(writeStruct)))
        {
            fp.close();
            png_free_data(writeStruct, infoStruct, PNG_FREE_ALL, -1);
            png_destroy_write_struct(&writeStruct, &infoStruct);
            return false;
        }
    
        png_init_io(writeStruct, fp.get());
    
        // Write header (8 bit colour depth)
        png_set_IHDR(writeStruct, infoStruct, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
                     PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    
        // Set title
        if (title != nullptr && strlen(title) > 0)
        {
            std::array<char, 50> mutableKey = {};
            strcpy(mutableKey.data(), "Title");
            std::array<char, 200> mutableText = {};
            strncpy(mutableText.data(), title, 199);
    
            png_text titleText;
            titleText.compression = PNG_TEXT_COMPRESSION_NONE;
            titleText.key         = mutableKey.data();
            titleText.text        = mutableText.data();
            png_set_text(writeStruct, infoStruct, &titleText, 1);
        }
    
        png_write_info(writeStruct, infoStruct);
    
        // RGB 3-byte stride.
        const uint32_t rowStride = width * 3;
        for (uint32_t row = 0; row < height; ++row)
        {
            uint32_t rowOffset = row * rowStride;
            png_write_row(writeStruct, &data[rowOffset]);
        }
    
        png_write_end(writeStruct, infoStruct);
    
        fp.close();
        png_free_data(writeStruct, infoStruct, PNG_FREE_ALL, -1);
        png_destroy_write_struct(&writeStruct, &infoStruct);
        return true;
    }
    }  // namespace angle