summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Image.cpp
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2020-12-19 17:21:58 +0100
committerAdmiral H. Curtiss <pikachu025@gmail.com>2020-12-20 03:30:17 +0100
commit5bbd5fce2f1c0287e0d28b1334f0ccfe216cc969 (patch)
tree27261d7dc704a115678586da193d53d83474b485 /Source/Core/Common/Image.cpp
parenteb6fd56c1d820924a2b455084e689515b5e2bc66 (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.cpp24
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