43#include <ufo/io/png.hpp>
58bool readPNG(std::FILE* fp,
void* image, std::size_t
length,
int fmt)
60 std::unique_ptr<spng_ctx,
decltype(&spng_ctx_free)> ctx{spng_ctx_new(0), spng_ctx_free};
62 std::println(stderr,
"[UFO | Read PNG] Failed to create PNG context");
67 spng_set_crc_action(ctx.get(), SPNG_CRC_USE, SPNG_CRC_USE);
71 constexpr std::size_t limit = 64uz * 1024 * 1024;
72 spng_set_chunk_limits(ctx.get(), limit, limit);
75 spng_set_png_file(ctx.get(), fp);
78 if (
int const ret = spng_get_ihdr(ctx.get(), &ihdr); ret) {
79 std::println(stderr,
"[UFO | Read PNG] Get PNG IHDR error: {}", spng_strerror(ret));
84 std::size_t image_size{};
85 if (
int const ret = spng_decoded_image_size(ctx.get(), fmt, &image_size); ret) {
86 std::println(stderr,
"[UFO | Read PNG] Get PNG image size error: {}",
91 if (image_size !=
length) {
92 std::println(stderr,
"[UFO | Read PNG] Incorrect image size, expected {} was {}",
98 if (SPNG_FMT_GA8 == fmt || SPNG_FMT_GA16 == fmt || SPNG_FMT_RGBA8 == fmt ||
99 SPNG_FMT_RGBA16 == fmt) {
100 flags |= SPNG_DECODE_TRNS;
104 if (
int const ret = spng_decode_image(ctx.get(), image, image_size, fmt, flags); ret) {
105 std::println(stderr,
"[UFO | Read PNG] Decode PNG image error: {}",
113bool writePNG(std::FILE* fp,
void const* image, std::size_t
length, std::uint32_t width,
114 std::uint32_t height,
int color_type,
int bit_depth)
116 std::unique_ptr<spng_ctx,
decltype(&spng_ctx_free)> ctx{spng_ctx_new(SPNG_CTX_ENCODER),
119 std::println(stderr,
"[UFO | Write PNG] Failed to create PNG context");
123 spng_set_png_file(ctx.get(), fp);
127 ihdr.height = height;
128 ihdr.bit_depth = bit_depth;
129 ihdr.color_type = color_type;
131 spng_set_ihdr(ctx.get(), &ihdr);
136 spng_encode_image(ctx.get(), image,
length, SPNG_FMT_PNG, SPNG_ENCODE_FINALIZE);
138 std::println(stderr,
"[UFO | Write PNG] Encode PNG image error: {}",
152 throw std::runtime_error(std::format(
153 "[UFO | Image Properties PNG] Failed to open file: {}", file.string()));
156 std::unique_ptr<spng_ctx,
decltype(&spng_ctx_free)> ctx{spng_ctx_new(0), spng_ctx_free};
158 throw std::runtime_error(
"[UFO | Image Properties PNG] Failed to create PNG context");
162 spng_set_crc_action(ctx.get(), SPNG_CRC_USE, SPNG_CRC_USE);
166 constexpr std::size_t limit = 64uz * 1024 * 1024;
167 spng_set_chunk_limits(ctx.get(), limit, limit);
170 spng_set_png_file(ctx.get(), fp.
get());
173 if (
int const ret = spng_get_ihdr(ctx.get(), &ihdr); ret) {
174 throw std::runtime_error(std::format(
175 "[UFO | Image Properties PNG] Get PNG IHDR error: {}", spng_strerror(ret)));
180 .height = ihdr.height,
181 .bit_depth = ihdr.bit_depth,
182 .alpha = SPNG_COLOR_TYPE_TRUECOLOR_ALPHA == ihdr.color_type ||
183 SPNG_COLOR_TYPE_GRAYSCALE_ALPHA == ihdr.color_type,
184 .grayscale = SPNG_COLOR_TYPE_GRAYSCALE == ihdr.color_type ||
185 SPNG_COLOR_TYPE_GRAYSCALE_ALPHA == ihdr.color_type,
RAII wrapper around a C std::FILE* handle.
std::FILE * get() const noexcept
Returns the underlying FILE*.
All vision-related classes and functions.
constexpr T length(Vec< Dim, T > const &v) noexcept
Computes the Euclidean length (magnitude) of a vector.
ImageProperties imagePropertiesPNG(std::filesystem::path const &file)
Reads the metadata of a PNG file without decoding pixel data.
Metadata describing the pixel layout of an image file.