diff options
| author | Admiral H. Curtiss <pikachu025@gmail.com> | 2020-12-19 17:21:58 +0100 |
|---|---|---|
| committer | Admiral H. Curtiss <pikachu025@gmail.com> | 2020-12-20 03:30:17 +0100 |
| commit | 5bbd5fce2f1c0287e0d28b1334f0ccfe216cc969 (patch) | |
| tree | 27261d7dc704a115678586da193d53d83474b485 /Source/Core/Common/Image.cpp | |
| parent | eb6fd56c1d820924a2b455084e689515b5e2bc66 (diff) | |
Common: Write PNGs in two steps to allow Unicode target paths.
Diffstat (limited to 'Source/Core/Common/Image.cpp')
| -rw-r--r-- | Source/Core/Common/Image.cpp | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/Source/Core/Common/Image.cpp b/Source/Core/Common/Image.cpp index 678a64db8c..478d4b42ab 100644 --- a/Source/Core/Common/Image.cpp +++ b/Source/Core/Common/Image.cpp @@ -10,6 +10,7 @@ #include <png.h> #include "Common/CommonTypes.h" +#include "Common/File.h" namespace Common { @@ -47,22 +48,39 @@ bool SavePNG(const std::string& path, const u8* input, ImageByteFormat format, u png.width = width; png.height = height; + size_t byte_per_pixel; switch (format) { case ImageByteFormat::RGB: png.format = PNG_FORMAT_RGB; + byte_per_pixel = 3; break; case ImageByteFormat::RGBA: png.format = PNG_FORMAT_RGBA; + byte_per_pixel = 4; break; default: return false; } - png_image_write_to_file(&png, path.c_str(), 0, input, stride, nullptr); - if (png.warning_or_error & PNG_IMAGE_ERROR) + // libpng doesn't handle non-ASCII characters in path, so write in two steps: + // first to memory, then to file + std::vector<u8> buffer(byte_per_pixel * width * height); + png_alloc_size_t size = buffer.size(); + int success = png_image_write_to_memory(&png, buffer.data(), &size, 0, input, stride, nullptr); + if (!success && size > buffer.size()) + { + // initial buffer size guess was too small, set to the now-known size and retry + buffer.resize(size); + png.warning_or_error = 0; + success = png_image_write_to_memory(&png, buffer.data(), &size, 0, input, stride, nullptr); + } + if (!success || (png.warning_or_error & PNG_IMAGE_ERROR) != 0) return false; - return true; + File::IOFile outfile(path, "wb"); + if (!outfile) + return false; + return outfile.WriteBytes(buffer.data(), size); } } // namespace Common |
