Hash :
5b35c7f6
        
        Author :
  
        
        Date :
2020-05-07T13:40:55
        
      
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>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
//
// 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