From 3b4fc2dfea8c3882a9f308932c296b5f63d2576a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 30 Apr 2024 03:17:24 +0300 Subject: [PATCH] leaks fix (valgrind full leak check) in world --- src/assets/AssetsLoader.cpp | 2 +- src/assets/assetload_funcs.cpp | 2 +- src/coders/imageio.cpp | 4 +- src/coders/png.cpp | 386 ++++++++++++++++----------------- src/coders/png.h | 16 -- src/coders/png.hpp | 16 ++ src/frontend/debug_panel.cpp | 3 +- src/graphics/core/Atlas.cpp | 2 +- src/graphics/core/Texture.cpp | 4 +- src/graphics/core/Texture.hpp | 2 +- 10 files changed, 215 insertions(+), 222 deletions(-) delete mode 100644 src/coders/png.h create mode 100644 src/coders/png.hpp diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 33f48cf7..0c8368ba 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -218,7 +218,7 @@ bool AssetsLoader::loadExternalTexture( if (fs::exists(path)) { try { auto image = imageio::read(path.string()); - assets->store(Texture::from(image.get()), name); + assets->store(Texture::from(image.get()).release(), name); return true; } catch (const std::exception& err) { logger.error() << "error while loading external " diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index b7143fdb..7bff4395 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -41,7 +41,7 @@ assetload::postfunc assetload::texture( imageio::read(paths->find(filename+".png").u8string()).release() ); return [name, image](auto assets) { - assets->store(Texture::from(image.get()), name); + assets->store(Texture::from(image.get()).release(), name); }; } diff --git a/src/coders/imageio.cpp b/src/coders/imageio.cpp index 89fb2518..cfddb3b2 100644 --- a/src/coders/imageio.cpp +++ b/src/coders/imageio.cpp @@ -1,6 +1,6 @@ #include "imageio.hpp" -#include "png.h" +#include "png.hpp" #include "../graphics/core/ImageData.hpp" #include @@ -9,7 +9,7 @@ namespace fs = std::filesystem; -using image_reader = std::function; +using image_reader = std::function(const std::string&)>; using image_writer = std::function; static std::unordered_map readers { diff --git a/src/coders/png.cpp b/src/coders/png.cpp index e347adf9..5f98ced7 100644 --- a/src/coders/png.cpp +++ b/src/coders/png.cpp @@ -1,12 +1,14 @@ -#include "png.h" - -#include -#include -#include +#include "png.hpp" #include "../graphics/core/ImageData.hpp" #include "../graphics/core/Texture.hpp" #include "../files/files.h" +#include "../debug/Logger.hpp" + +#include +#include + +static debug::Logger logger("png-coder"); #ifndef _WIN32 #define LIBPNG @@ -19,78 +21,76 @@ int _png_write(const char* filename, uint width, uint height, const ubyte* data, bool alpha) { uint pixsize = alpha ? 4 : 3; - // Open file for writing (binary mode) - FILE* fp = fopen(filename, "wb"); - if (fp == nullptr) { - fprintf(stderr, "Could not open file %s for writing\n", filename); - fclose(fp); - return 1; - } + // Open file for writing (binary mode) + FILE* fp = fopen(filename, "wb"); + if (fp == nullptr) { + logger.error() << "could not open file " << filename << " for writing"; + fclose(fp); + return 1; + } - // Initialize write structure - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (png_ptr == nullptr) { - fprintf(stderr, "Could not allocate write struct\n"); - fclose(fp); - png_destroy_write_struct(&png_ptr, (png_infopp)nullptr); - return 1; - } + // Initialize write structure + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (png_ptr == nullptr) { + logger.error() << "could not allocate write struct"; + fclose(fp); + return 1; + } - // Initialize info structure - png_infop info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == nullptr) { - fprintf(stderr, "Could not allocate info struct\n"); - fclose(fp); - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - png_destroy_write_struct(&png_ptr, (png_infopp)nullptr); - return 1; - - } + // Initialize info structure + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == nullptr) { + logger.error() << "could not allocate info struct"; + fclose(fp); + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + png_destroy_write_struct(&png_ptr, (png_infopp)nullptr); + return 1; + + } - // Setup Exception handling - if (setjmp(png_jmpbuf(png_ptr))) { - fprintf(stderr, "Error during png creation\n"); - fclose(fp); - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - png_destroy_write_struct(&png_ptr, (png_infopp)nullptr); - return 1; - } + // Setup Exception handling + if (setjmp(png_jmpbuf(png_ptr))) { + logger.error() << "error during png creation"; + fclose(fp); + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + png_destroy_write_struct(&png_ptr, &info_ptr); + return 1; + } - png_init_io(png_ptr, fp); + png_init_io(png_ptr, fp); - // Write header (8 bit colour depth) - png_set_IHDR(png_ptr, info_ptr, width, height, - 8, + // Write header (8 bit colour depth) + png_set_IHDR(png_ptr, info_ptr, width, height, + 8, alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - png_write_info(png_ptr, info_ptr); + png_write_info(png_ptr, info_ptr); - std::unique_ptr row(new png_byte[pixsize * width]); - - // Write image data - for (uint y = 0; y < height; y++) { - for (uint x = 0; x < width; x++) { + auto row = std::make_unique(pixsize * width); + // Write image data + for (uint y = 0; y < height; y++) { + for (uint x = 0; x < width; x++) { for (uint i = 0; i < pixsize; i++) { row[x * pixsize + i] = (png_byte)data[(y * width + x) * pixsize + i]; } - } - png_write_row(png_ptr, row.get()); - } + } + png_write_row(png_ptr, row.get()); + } - // End write - png_write_end(png_ptr, nullptr); + // End write + png_write_end(png_ptr, nullptr); - fclose(fp); - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - png_destroy_write_struct(&png_ptr, (png_infopp)nullptr); - return 0; + fclose(fp); + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + png_destroy_write_struct(&png_ptr, &info_ptr); + return 0; } -ImageData* _png_load(const char* file){ +std::unique_ptr _png_load(const char* file){ FILE* fp = nullptr; if ((fp = fopen(file, "rb")) == nullptr) { return nullptr; @@ -175,12 +175,12 @@ ImageData* _png_load(const char* file){ format = ImageFormat::rgb888; break; default: - printf("Color type %d not supported!\n", color_type); + logger.error() << "color type " << color_type << " is not supported!"; png_destroy_read_struct(&png, &info, &end_info); - fclose(fp); + fclose(fp); return nullptr; } - ImageData* image = new ImageData(format, width, height, (void*)image_data.release()); + auto image = std::make_unique(format, width, height, (void*)image_data.release()); png_destroy_read_struct(&png, &info, &end_info); fclose(fp); return image; @@ -194,167 +194,159 @@ ImageData* _png_load(const char* file){ static const int SPNG_SUCCESS = 0; //returns spng result code int _png_write(const char* filename, uint width, uint height, const ubyte* data, bool alpha) { - int fmt; - int ret = 0; - spng_ctx* ctx = nullptr; - spng_ihdr ihdr = { 0 }; - uint pixsize = alpha ? 4 : 3; + int fmt; + int ret = 0; + spng_ctx* ctx = nullptr; + spng_ihdr ihdr = { 0 }; + uint pixsize = alpha ? 4 : 3; - ctx = spng_ctx_new(SPNG_CTX_ENCODER); - spng_set_option(ctx, SPNG_ENCODE_TO_BUFFER, 1); + ctx = spng_ctx_new(SPNG_CTX_ENCODER); + spng_set_option(ctx, SPNG_ENCODE_TO_BUFFER, 1); - ihdr.width = width; - ihdr.height = height; - ihdr.color_type = alpha ? SPNG_COLOR_TYPE_TRUECOLOR_ALPHA : SPNG_COLOR_TYPE_TRUECOLOR; - ihdr.bit_depth = 8; + ihdr.width = width; + ihdr.height = height; + ihdr.color_type = alpha ? SPNG_COLOR_TYPE_TRUECOLOR_ALPHA : SPNG_COLOR_TYPE_TRUECOLOR; + ihdr.bit_depth = 8; - spng_set_ihdr(ctx, &ihdr); - fmt = SPNG_FMT_PNG; - ret = spng_encode_image(ctx, data, (size_t)width * (size_t)height * pixsize , fmt, SPNG_ENCODE_FINALIZE); - if (ret != SPNG_SUCCESS) { - printf("spng_encode_image() error: %s\n", spng_strerror(ret)); - fflush(stdout); - spng_ctx_free(ctx); - return ret; - } + spng_set_ihdr(ctx, &ihdr); + fmt = SPNG_FMT_PNG; + ret = spng_encode_image(ctx, data, (size_t)width * (size_t)height * pixsize , fmt, SPNG_ENCODE_FINALIZE); + if (ret != SPNG_SUCCESS) { + logger.error() << "spng_encode_image() error: " << spng_strerror(ret); + spng_ctx_free(ctx); + return ret; + } - size_t png_size; - void* png_buf = spng_get_png_buffer(ctx, &png_size, &ret); + size_t png_size; + void* png_buf = spng_get_png_buffer(ctx, &png_size, &ret); - if (png_buf == nullptr) { - printf("spng_get_png_buffer() error: %s\n", spng_strerror(ret)); - } - else { - files::write_bytes(filename, (const unsigned char*)png_buf, png_size); - } - fflush(stdout); - spng_ctx_free(ctx); - return ret; + if (png_buf == nullptr) { + logger.error() << "spng_get_png_buffer() error: " << spng_strerror(ret); + } + else { + files::write_bytes(filename, (const unsigned char*)png_buf, png_size); + } + spng_ctx_free(ctx); + return ret; } -ImageData* _png_load(const char* file){ - int r = 0; - FILE *png = nullptr; - char *pngbuf = nullptr; - spng_ctx *ctx = nullptr; - unsigned char *out = nullptr; +std::unique_ptr _png_load(const char* file){ + int r = 0; + FILE *png = nullptr; + char *pngbuf = nullptr; + spng_ctx *ctx = nullptr; + unsigned char *out = nullptr; - png = fopen(file, "rb"); - if (png == nullptr){ - std::cerr << "could not to open file " << file << std::endl; - return nullptr; - } + png = fopen(file, "rb"); + if (png == nullptr){ + logger.error() << "could not to open file " << file; + return nullptr; + } - fseek(png, 0, SEEK_END); - long siz_pngbuf = ftell(png); - rewind(png); - if(siz_pngbuf < 1) { - fclose(png); - std::cerr << "could not to read file " << file << std::endl; - return nullptr; - } - pngbuf = new char[siz_pngbuf]; - if(fread(pngbuf, siz_pngbuf, 1, png) != 1){ //check of read elements count - fclose(png); - delete[] pngbuf; - std::cerr << "fread() failed" << std::endl; - return nullptr; - } - fclose(png); // <- finally closing file - ctx = spng_ctx_new(0); - if (ctx == nullptr){ - delete[] pngbuf; - std::cerr << "spng_ctx_new() failed" << std::endl; - return nullptr; - } - r = spng_set_crc_action(ctx, SPNG_CRC_USE, SPNG_CRC_USE); - if (r != SPNG_SUCCESS){ - delete[] pngbuf; - spng_ctx_free(ctx); - std::cerr << "spng_set_crc_action() error: " << spng_strerror(r) << std::endl; - return nullptr; - } - r = spng_set_png_buffer(ctx, pngbuf, siz_pngbuf); - if (r != SPNG_SUCCESS){ - delete[] pngbuf; - spng_ctx_free(ctx); - std::cerr << "spng_set_png_buffer() error: " << spng_strerror(r) << std::endl; - return nullptr; - } + fseek(png, 0, SEEK_END); + long siz_pngbuf = ftell(png); + rewind(png); + if(siz_pngbuf < 1) { + fclose(png); + logger.error() << "could not to read file " << file; + return nullptr; + } + pngbuf = new char[siz_pngbuf]; + if(fread(pngbuf, siz_pngbuf, 1, png) != 1){ //check of read elements count + fclose(png); + delete[] pngbuf; + logger.error() << "fread() failed: " << file; + return nullptr; + } + fclose(png); // <- finally closing file + ctx = spng_ctx_new(0); + if (ctx == nullptr){ + delete[] pngbuf; + logger.error() << "spng_ctx_new() failed"; + return nullptr; + } + r = spng_set_crc_action(ctx, SPNG_CRC_USE, SPNG_CRC_USE); + if (r != SPNG_SUCCESS){ + delete[] pngbuf; + spng_ctx_free(ctx); + logger.error() << "spng_set_crc_action(): " << spng_strerror(r); + return nullptr; + } + r = spng_set_png_buffer(ctx, pngbuf, siz_pngbuf); + if (r != SPNG_SUCCESS){ + delete[] pngbuf; + spng_ctx_free(ctx); + logger.error() << "spng_set_png_buffer(): " << spng_strerror(r); + return nullptr; + } - spng_ihdr ihdr; - r = spng_get_ihdr(ctx, &ihdr); - if (r != SPNG_SUCCESS){ - delete[] pngbuf; - spng_ctx_free(ctx); - std::cerr << "spng_get_ihdr() error: " << spng_strerror(r) << std::endl; - return nullptr; - } - //// Unused "something" - //const char *clr_type_str; - //if(ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE) - // clr_type_str = "grayscale"; - //else if(ihdr.color_type == SPNG_COLOR_TYPE_TRUECOLOR) - // clr_type_str = "truecolor"; - //else if(ihdr.color_type == SPNG_COLOR_TYPE_INDEXED) - // clr_type_str = "indexed color"; - //else if(ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE_ALPHA) - // clr_type_str = "grayscale with alpha"; - //else - // clr_type_str = "truecolor with alpha"; + spng_ihdr ihdr; + r = spng_get_ihdr(ctx, &ihdr); + if (r != SPNG_SUCCESS){ + delete[] pngbuf; + spng_ctx_free(ctx); + logger.error() << "spng_get_ihdr(): " << spng_strerror(r); + return nullptr; + } - size_t out_size; - r = spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &out_size); - if (r != SPNG_SUCCESS){ - delete[] pngbuf; - spng_ctx_free(ctx); - std::cerr << "spng_decoded_image_size() error: " << spng_strerror(r) << std::endl; - return nullptr; - } - out = new unsigned char[out_size]; - r = spng_decode_image(ctx, out, out_size, SPNG_FMT_RGBA8, 0); - if (r != SPNG_SUCCESS){ - delete[] out; - delete[] pngbuf; - spng_ctx_free(ctx); - std::cerr << "spng_decode_image() error: " << spng_strerror(r) << std::endl; - return nullptr; - } + size_t out_size; + r = spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &out_size); + if (r != SPNG_SUCCESS){ + delete[] pngbuf; + spng_ctx_free(ctx); + logger.error() << "spng_decoded_image_size(): " << spng_strerror(r); + return nullptr; + } + out = new unsigned char[out_size]; + r = spng_decode_image(ctx, out, out_size, SPNG_FMT_RGBA8, 0); + if (r != SPNG_SUCCESS){ + delete[] out; + delete[] pngbuf; + spng_ctx_free(ctx); + logger.error() << "spng_decode_image(): " << spng_strerror(r); + return nullptr; + } - unsigned char* flipped = new unsigned char[out_size]; + unsigned char* flipped = new unsigned char[out_size]; - for (size_t i = 0; i < ihdr.height; i+=1){ - size_t rowsize = ihdr.width*4; - for (size_t j = 0; j < rowsize; j++){ - flipped[(ihdr.height-i-1)*rowsize+j] = out[i*rowsize+j]; - } - } - delete[] out; // <- finally delete out // no, delete spng usage + for (size_t i = 0; i < ihdr.height; i+=1){ + size_t rowsize = ihdr.width*4; + for (size_t j = 0; j < rowsize; j++){ + flipped[(ihdr.height-i-1)*rowsize+j] = out[i*rowsize+j]; + } + } + delete[] out; // <- finally delete out // no, delete spng usage - ImageData* image = new ImageData(ImageFormat::rgba8888, ihdr.width, ihdr.height, (void*)flipped); + auto image = std::make_unique(ImageFormat::rgba8888, ihdr.width, ihdr.height, (void*)flipped); - delete[] pngbuf; - spng_ctx_free(ctx); + delete[] pngbuf; + spng_ctx_free(ctx); return image; } #endif -ImageData* png::load_image(const std::string& filename) { - ImageData* image (_png_load(filename.c_str())); - if (image == nullptr) { - throw std::runtime_error("could not load image "+filename); - } +std::unique_ptr png::load_image(const std::string& filename) { + auto image = _png_load(filename.c_str()); + if (image == nullptr) { + throw std::runtime_error("could not load image "+filename); + } return image; } -Texture* png::load_texture(const std::string& filename) { - std::unique_ptr image (load_image(filename)); - auto texture = Texture::from(image.get()); +std::unique_ptr png::load_texture(const std::string& filename) { + auto image = load_image(filename); + auto texture = Texture::from(image.get()); texture->setNearestFilter(); return texture; } void png::write_image(const std::string& filename, const ImageData* image) { - _png_write(filename.c_str(), image->getWidth(), image->getHeight(), (const ubyte*)image->getData(), image->getFormat() == ImageFormat::rgba8888); + _png_write( + filename.c_str(), + image->getWidth(), + image->getHeight(), + (const ubyte*)image->getData(), + image->getFormat() == ImageFormat::rgba8888 + ); } diff --git a/src/coders/png.h b/src/coders/png.h deleted file mode 100644 index 07680d32..00000000 --- a/src/coders/png.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CODERS_PNG_H_ -#define CODERS_PNG_H_ - -#include -#include "../typedefs.h" - -class Texture; -class ImageData; - -namespace png { - extern ImageData* load_image(const std::string& filename); - extern void write_image(const std::string& filename, const ImageData* image); - extern Texture* load_texture(const std::string& filename); -} - -#endif /* CODERS_PNG_H_ */ diff --git a/src/coders/png.hpp b/src/coders/png.hpp new file mode 100644 index 00000000..59af39e5 --- /dev/null +++ b/src/coders/png.hpp @@ -0,0 +1,16 @@ +#ifndef CODERS_PNG_HPP_ +#define CODERS_PNG_HPP_ + +#include +#include + +class Texture; +class ImageData; + +namespace png { + std::unique_ptr load_image(const std::string& filename); + void write_image(const std::string& filename, const ImageData* image); + std::unique_ptr load_texture(const std::string& filename); +} + +#endif // CODERS_PNG_HPP_ diff --git a/src/frontend/debug_panel.cpp b/src/frontend/debug_panel.cpp index 9590f379..a284a15a 100644 --- a/src/frontend/debug_panel.cpp +++ b/src/frontend/debug_panel.cpp @@ -98,6 +98,7 @@ std::shared_ptr create_debug_panel( // Coord input auto box = std::make_shared(L""); + auto boxRef = box.get(); box->setTextSupplier([=]() { Hitbox* hitbox = player->hitbox.get(); return util::to_wstring(hitbox->position[ax], 2); @@ -113,7 +114,7 @@ std::shared_ptr create_debug_panel( }); box->setOnEditStart([=](){ Hitbox* hitbox = player->hitbox.get(); - box->setText(std::to_wstring(int(hitbox->position[ax]))); + boxRef->setText(std::to_wstring(int(hitbox->position[ax]))); }); box->setSize(glm::vec2(230, 27)); diff --git a/src/graphics/core/Atlas.cpp b/src/graphics/core/Atlas.cpp index fdf725c4..8b62d0f3 100644 --- a/src/graphics/core/Atlas.cpp +++ b/src/graphics/core/Atlas.cpp @@ -22,7 +22,7 @@ Atlas::~Atlas() { } void Atlas::prepare() { - texture.reset(Texture::from(image.get())); + texture = Texture::from(image.get()); } bool Atlas::has(const std::string& name) const { diff --git a/src/graphics/core/Texture.cpp b/src/graphics/core/Texture.cpp index ad4733ca..eb91d206 100644 --- a/src/graphics/core/Texture.cpp +++ b/src/graphics/core/Texture.cpp @@ -64,11 +64,11 @@ void Texture::setNearestFilter() { glBindTexture(GL_TEXTURE_2D, 0); } -Texture* Texture::from(const ImageData* image) { +std::unique_ptr Texture::from(const ImageData* image) { uint width = image->getWidth(); uint height = image->getHeight(); const void* data = image->getData(); - return new Texture((ubyte*)data, width, height, image->getFormat()); + return std::make_unique((ubyte*)data, width, height, image->getFormat()); } uint Texture::getWidth() const { diff --git a/src/graphics/core/Texture.hpp b/src/graphics/core/Texture.hpp index 13771c8b..0fac97bb 100644 --- a/src/graphics/core/Texture.hpp +++ b/src/graphics/core/Texture.hpp @@ -31,7 +31,7 @@ public: virtual uint getId() const; - static Texture* from(const ImageData* image); + static std::unique_ptr from(const ImageData* image); }; #endif // GRAPHICS_CORE_TEXTURE_HPP_