mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-10-30 21:35:06 +00:00
32 lines
1.2 KiB
C++
32 lines
1.2 KiB
C++
#include "png_codec.h"
|
|
|
|
#include <png.h>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
namespace raven {
|
|
|
|
Pixels decode_png(std::span<const uint8_t> bytes)
|
|
{
|
|
if (bytes.size() < 8 || bytes.size() > 16 * 1024 * 1024 || png_sig_cmp(bytes.data(), 0, 8))
|
|
throw std::runtime_error("invalid PNG input or compressed-size policy limit");
|
|
struct Image {
|
|
png_image value{};
|
|
~Image() { png_image_free(&value); }
|
|
} image;
|
|
image.value.version = PNG_IMAGE_VERSION;
|
|
if (!png_image_begin_read_from_memory(&image.value, bytes.data(), bytes.size()))
|
|
throw std::runtime_error("PNG header decoding failed: " + std::string(image.value.message));
|
|
const uint32_t width = image.value.width;
|
|
const uint32_t height = image.value.height;
|
|
if (!width || !height || width > 8192 || height > 8192 || uint64_t(width) * height > 16 * 1024 * 1024)
|
|
throw std::runtime_error("PNG dimensions exceed pixel policy limit");
|
|
Pixels pixels{width, height, std::vector<uint8_t>(size_t(width) * height * 4)};
|
|
image.value.format = PNG_FORMAT_RGBA;
|
|
if (!png_image_finish_read(&image.value, nullptr, pixels.rgba.data(), 0, nullptr))
|
|
throw std::runtime_error("PNG pixel decoding failed: " + std::string(image.value.message));
|
|
return pixels;
|
|
}
|
|
|
|
}
|