From c44d5f06fcea7af11d03f62a2670030c65ad0089 Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Sat, 10 Mar 2018 12:52:52 +0100 Subject: Make sure png file gets closed by wrapping the file descriptor into a class with destructor --- BuddhaTest/include/Helpers.h | 13 +++++++++++++ BuddhaTest/src/Helpers.cpp | 35 ++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/BuddhaTest/include/Helpers.h b/BuddhaTest/include/Helpers.h index c24e2c7..ad14305 100644 --- a/BuddhaTest/include/Helpers.h +++ b/BuddhaTest/include/Helpers.h @@ -2,6 +2,7 @@ #include #include #include +#include //includes FILE typedef namespace Helpers { @@ -9,4 +10,16 @@ namespace Helpers GLuint LoadComputeShader(const char * compute_file_path); void WriteOutputPNG(const std::vector& data, unsigned int width, unsigned int height); + + /** Wraps around a C file descriptor. Libpng could be taught to use C++ streams, but I'm too lazy and rather wrap this ugly thing up, so it gets cleaned... */ + class ScopedCFileDescriptor + { + public: + ScopedCFileDescriptor(const char *path, const char *mode); + ~ScopedCFileDescriptor(); + FILE * Get() const; + bool IsValid() const; + private: + FILE * Descriptor; + }; } diff --git a/BuddhaTest/src/Helpers.cpp b/BuddhaTest/src/Helpers.cpp index cf925be..fb362ab 100644 --- a/BuddhaTest/src/Helpers.cpp +++ b/BuddhaTest/src/Helpers.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -147,6 +148,7 @@ namespace Helpers glDeleteShader(ComputeShaderID); return ProgramID; } + void WriteOutputPNG(const std::vector& data, unsigned int width, unsigned int height) { png_byte ** row_pointers = static_cast(calloc(height,sizeof(void *))); @@ -175,32 +177,29 @@ namespace Helpers } } - //beware, this is going to be ugly C syntax, but well, libpng... - FILE * fp = fopen("image.png", "wb"); - if(!fp) + ScopedCFileDescriptor fd("image.png", "wb"); + if(!fd.IsValid()) { + std::cout << "Failed to open image.png for writing." << std::endl; return; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if(!png_ptr) { - fclose(fp); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - fclose(fp); return; } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); return; } - png_init_io(png_ptr, fp); + png_init_io(png_ptr, fd.Get()); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); @@ -218,4 +217,26 @@ namespace Helpers free(row_pointers); } + + ScopedCFileDescriptor::ScopedCFileDescriptor(const char *path, const char *mode) + { + Descriptor = fopen(path,mode); + } + + ScopedCFileDescriptor::~ScopedCFileDescriptor() + { + if(IsValid()) + fclose(Descriptor); + } + + FILE * ScopedCFileDescriptor::Get() const + { + return Descriptor; + } + + bool ScopedCFileDescriptor::IsValid() const + { + return Descriptor != nullptr; + } + } -- cgit v1.2.3