Haio 0.2.X
Homebrew Asset IO/CDN
Loading...
Searching...
No Matches
encode.cpp
Go to the documentation of this file.
1#include <haio_codec.hpp>
2
3#include <spng.h>
4
5#include <cstdlib>
6#include <cstring>
7#include <memory>
8#include <optional>
9#include <string_view>
10
11namespace {
12
13std::optional<Haio::Error> checkSpng(int err, std::string_view message) {
14 if (!err) return std::nullopt;
15 return Haio::Error{Haio::ErrorCode::InvalidInput, std::string(message) + ": " + spng_strerror(err)};
16}
17
18}
19
20namespace Haio::Codecs {
21/**
22 * @addtogroup encode
23 * @{
24 */
25/**
26 * @name Convert
27 * @{
28 */
29template <>
30Result<Blob> Encode<Format::PNG, Color::RGBA8888>(Image<Color::RGBA8888> img) {
31 const auto expected = static_cast<size_t>(img.width) * static_cast<size_t>(img.height) * 4;
32 if (img.width <= 0 || img.height <= 0 || img.data.size() != expected) {
33 HAIO_FAIL(InvalidInput, "invalid rgba8888 image for png encode");
34 }
35
36 std::unique_ptr<spng_ctx, decltype(&spng_ctx_free)> ctx(spng_ctx_new(SPNG_CTX_ENCODER), spng_ctx_free);
37 if (!ctx) HAIO_FAIL(InvalidInput, "failed to create png writer");
38
39 HAIO_CHECK(checkSpng(spng_set_option(ctx.get(), SPNG_ENCODE_TO_BUFFER, 1), "failed to configure png writer"));
40
41 spng_ihdr ihdr{};
42 ihdr.width = static_cast<uint32_t>(img.width);
43 ihdr.height = static_cast<uint32_t>(img.height);
44 ihdr.bit_depth = 8;
45 ihdr.color_type = SPNG_COLOR_TYPE_TRUECOLOR_ALPHA;
46 ihdr.compression_method = 0;
47 ihdr.filter_method = 0;
48 ihdr.interlace_method = SPNG_INTERLACE_NONE;
49
50 HAIO_CHECK(checkSpng(spng_set_ihdr(ctx.get(), &ihdr), "failed to set png header"));
51 HAIO_CHECK(checkSpng(spng_encode_image(ctx.get(), img.data.data(), img.data.size(), SPNG_FMT_PNG, SPNG_ENCODE_FINALIZE), "failed to encode png"));
52
53 size_t size = 0;
54 int err = 0;
55 std::unique_ptr<void, decltype(&std::free)> bytes(spng_get_png_buffer(ctx.get(), &size, &err), std::free);
56 HAIO_CHECK(checkSpng(err, "failed to read encoded png"));
57 if (!bytes) HAIO_FAIL(InvalidInput, "failed to read encoded png");
58
59 const auto* begin = static_cast<const uint8_t*>(bytes.get());
60 std::vector<uint8_t> buffer(begin, begin + size);
61 return Blob{Format::PNG, Color::RGBA8888, "image/png", {}, std::move(buffer)};
62}
63/** @} */
64/**
65 @}
66 */
67}
Result< Blob > Encode< Format::PNG, Color::RGBA8888 >(Image< Color::RGBA8888 > img)
Definition encode.cpp:30
#define HAIO_FAIL(why, message)
#define HAIO_CHECK(expr)
std::expected< T, Error > Result