Implement writing png pixmaps
This commit is contained in:
parent
769b5786ae
commit
93e5691d8a
2 changed files with 109 additions and 55 deletions
|
|
@ -27,6 +27,8 @@ namespace psemek::gfx
|
||||||
pixmap_rgba read_png(io::istream && is);
|
pixmap_rgba read_png(io::istream && is);
|
||||||
pixmap_monochrome read_png_monochrome(io::istream && is);
|
pixmap_monochrome read_png_monochrome(io::istream && is);
|
||||||
|
|
||||||
|
void write_png(pixmap_rgba const & p, io::ostream && os);
|
||||||
|
|
||||||
template <typename Pixel, std::size_t N>
|
template <typename Pixel, std::size_t N>
|
||||||
auto to_srgb(util::array<Pixel, N> pm, float g = 1.f / 2.2f)
|
auto to_srgb(util::array<Pixel, N> pm, float g = 1.f / 2.2f)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename Pixel>
|
template <typename Pixel>
|
||||||
|
|
@ -80,6 +83,50 @@ namespace psemek::gfx
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_png_impl(pixmap_rgba const & p, io::ostream & os)
|
||||||
|
{
|
||||||
|
png_error_ptr error = [](png_structp, png_const_charp str)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(str);
|
||||||
|
};
|
||||||
|
|
||||||
|
png_error_ptr warn = [](png_structp, png_const_charp str)
|
||||||
|
{
|
||||||
|
log::warning() << str;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, error, warn);
|
||||||
|
if (!png) throw std::runtime_error("png_create_write_struct returned null");
|
||||||
|
|
||||||
|
png_set_error_fn(png, nullptr, error, warn);
|
||||||
|
|
||||||
|
png_infop info = nullptr;
|
||||||
|
|
||||||
|
[[maybe_unused]] auto png_dtor = util::at_scope_exit([&]{
|
||||||
|
png_destroy_write_struct(&png, &info);
|
||||||
|
});
|
||||||
|
|
||||||
|
info = png_create_info_struct(png);
|
||||||
|
if (!info) throw std::runtime_error("png_create_info_struct returned null");
|
||||||
|
|
||||||
|
png_rw_ptr write = [](png_structp png, png_bytep ptr, size_t count){
|
||||||
|
reinterpret_cast<io::ostream *>(png_get_io_ptr(png))->write(reinterpret_cast<char const *>(ptr), count);
|
||||||
|
};
|
||||||
|
png_flush_ptr flush = [](png_structp png){
|
||||||
|
reinterpret_cast<io::ostream *>(png_get_io_ptr(png))->flush();
|
||||||
|
};
|
||||||
|
png_set_write_fn(png, &os, write, flush);
|
||||||
|
|
||||||
|
png_set_IHDR(png, info, p.width(), p.height(), 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
|
png_write_info(png, info);
|
||||||
|
|
||||||
|
for (std::uint32_t i = 0; i < p.height(); ++i)
|
||||||
|
png_write_row(png, reinterpret_cast<png_byte const *>(p.data() + p.width() * i));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
pixmap_rgba read_png(io::istream && is)
|
pixmap_rgba read_png(io::istream && is)
|
||||||
{
|
{
|
||||||
return read_png_impl<color_rgba>(is, false);
|
return read_png_impl<color_rgba>(is, false);
|
||||||
|
|
@ -90,4 +137,9 @@ namespace psemek::gfx
|
||||||
return read_png_impl<std::uint8_t>(is, true);
|
return read_png_impl<std::uint8_t>(is, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_png(pixmap_rgba const & p, io::ostream && os)
|
||||||
|
{
|
||||||
|
write_png_impl(p, os);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue