Add SaveImageResource implementation for libpng

pull/241/head
kevle 4 years ago
parent 7bdeb96649
commit 84cedb4fed
  1. 96
      olcPixelGameEngine.h

@ -4255,6 +4255,102 @@ namespace olc
olc::rcode SaveImageResource(const olc::Sprite* spr, const std::string& sImageFile) override
{
if (spr == nullptr)
return olc::rcode::FAIL;
// RAII wrapper for FILE pointer
struct FileWrapper
{
FILE* f = nullptr;
FileWrapper(const std::string& sImageFile)
{
f = fopen(sImageFile.c_str(), "wb");
}
FileWrapper(const FileWrapper&) = delete;
FileWrapper(FileWrapper&&) = delete;
FileWrapper& operator=(const FileWrapper&) = delete;
FileWrapper& operator=(FileWrapper&&) = delete;
~FileWrapper()
{
if (f != nullptr)
fclose(f);
}
bool Good() const
{
return f != nullptr;
}
};
// RAII wrapper for png_struct and png_info pointers
struct PNGStructWrapper
{
struct PNGError
{};
png_structp png_ptr = nullptr;
png_infop info_ptr = nullptr;
PNGStructWrapper()
{
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, PNGStructWrapper::user_error_handling_func, PNGStructWrapper::user_warn_func);
if (png_ptr != nullptr)
info_ptr = png_create_info_struct(png_ptr);
}
PNGStructWrapper(const PNGStructWrapper&) = delete;
PNGStructWrapper(PNGStructWrapper&&) = delete;
PNGStructWrapper& operator=(const PNGStructWrapper&) = delete;
PNGStructWrapper& operator=(PNGStructWrapper&&) = delete;
~PNGStructWrapper()
{
png_destroy_write_struct(&png_ptr, &info_ptr);
}
bool Good() const
{
return png_ptr != nullptr && info_ptr != nullptr;
}
static void user_error_handling_func(png_structp, png_const_charp error_msg) {
fprintf(stderr, "%s\n", error_msg);
throw PNGError{}; // Function must not return control to caller
}
static void user_warn_func(png_structp, png_const_charp warning_msg) {
fprintf(stderr, "%s\n", warning_msg);
}
};
try
{
FileWrapper file(sImageFile);
if (!file.Good())
{
return olc::rcode::FAIL;
}
PNGStructWrapper png;
if (!png.Good())
{
return olc::rcode::FAIL;
}
png_init_io(png.png_ptr, file.f);
png_set_IHDR(png.png_ptr, png.info_ptr, spr->width, spr->height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
std::unique_ptr<png_bytep[]> png_rows = std::make_unique<png_bytep[]>(spr->height);
for (int y = 0; y < spr->height; y++)
png_rows[y] = (png_bytep)(spr->pColData.data() + std::ptrdiff_t(y) * spr->width);
png_set_rows(png.png_ptr, png.info_ptr, png_rows.get());
png_write_png(png.png_ptr, png.info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
}
catch (PNGStructWrapper::PNGError&)
{
return olc::rcode::FAIL;
}
return olc::rcode::OK;
}
};

Loading…
Cancel
Save