7 std::span<const std::uint8_t>
pixels, std::uint64_t maximumBytes) {
11 {},
"asset.image.png"));
15 pixels.size() > std::numeric_limits<uLong>::max() - std::uint64_t(
height))
17 const std::uint64_t row = std::uint64_t(
width) * 4, total =
pixels.size() + std::uint64_t(
height);
18 if (total > maximumBytes || total > std::numeric_limits<uLong>::max())
return fail();
19 uLongf bound = compressBound(
static_cast<uLong
>(total));
20 if (bound > maximumBytes || maximumBytes - bound < 57 || bound > UINT32_MAX - 4)
return fail();
21 std::vector<std::uint8_t> scanlines;
22 scanlines.reserve(std::size_t(total));
23 for (std::size_t
y = 0;
y <
height; ++
y) {
24 scanlines.push_back(0);
25 scanlines.insert(scanlines.end(),
pixels.begin() +
y * row,
pixels.begin() + (
y + 1) * row);
27 std::vector<std::uint8_t> compressed(bound);
28 if (compress2(compressed.data(), &bound, scanlines.data(),
static_cast<uLong
>(total), 6) != Z_OK)
return fail();
29 compressed.resize(bound);
30 std::vector<std::uint8_t> result{137, 80, 78, 71, 13, 10, 26, 10};
31 auto put = [](
auto& out, std::uint32_t
v) {
32 for (
int shift = 24; shift >= 0; shift -= 8) out.push_back(std::uint8_t(
v >> shift));
34 auto chunk = [&](
const char*
type, std::span<const std::uint8_t>
payload) {
35 put(result, std::uint32_t(
payload.size()));
36 const auto at = result.size();
37 result.insert(result.end(),
type,
type + 4);
39 put(result, crc32(0, result.data() +
at,
static_cast<uInt
>(
payload.size() + 4)));
41 std::vector<std::uint8_t> header;
44 header.insert(header.end(), {8, 6, 0, 0, 0});
45 chunk(
"IHDR", header);
46 chunk(
"IDAT", compressed);
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Result< std::vector< std::uint8_t > > encodeSourcePng(std::uint32_t width, std::uint32_t height, std::span< const std::uint8_t > pixels, std::uint64_t maximumBytes)
Encode top-down RGBA8 source pixels without transfer conversion.