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#include <haio_codecs.hpp>
3#include <haio_convert.hpp>
4
5#include <turbojpeg.h>
6
7namespace {
8
9struct Handle {
10 tjhandle raw = nullptr;
11 ~Handle() { if (raw) tj3Destroy(raw); }
12};
13
14/** what turbojpeg allocates is freed by turbojpeg, whatever happens in between */
15struct Owned {
16 uint8_t* raw = nullptr;
17 ~Owned() { if (raw) tj3Free(raw); }
18};
19
20}
21
22namespace Haio::Codecs {
23
24/**
25 * from yuv planes, which is what a jpeg wants.
26 *
27 * anything else converts first, and does so where the caller can see it: an encoder
28 * that quietly accepted rgb would hide a colour conversion inside what looks like a
29 * container change.
30 */
31template <>
32Result<Blob> Encode<Format::JPEG, Color::YUV420>(Image<Color::YUV420> img) {
33 const Size size{img.width, img.height};
34 HAIO_TRY(expected, sizeOf(Color::YUV420, size));
35 if (img.data.size() != expected) HAIO_FAIL(InvalidInput, "invalid yuv420 image for jpeg encode");
36
37 Handle handle{tj3Init(TJINIT_COMPRESS)};
38 if (!handle.raw) HAIO_FAIL(Internal, "cannot start the jpeg encoder");
39
40 tj3Set(handle.raw, TJPARAM_SUBSAMP, TJSAMP_420);
41 tj3Set(handle.raw, TJPARAM_QUALITY, 90);
42
43 Owned out;
44 size_t written = 0;
45 if (tj3CompressFromYUV8(handle.raw, img.data.data(), img.width, 1, img.height, &out.raw, &written) != 0) {
46 HAIO_FAIL(Internal, "the jpeg could not be encoded");
47 }
48
49 return Blob{Format::JPEG, Color::YUV420, "image/jpeg", {},
50 std::vector<uint8_t>(out.raw, out.raw + written)};
51}
52
53}
#define HAIO_TRY(name, expr)
#define HAIO_FAIL(why, message)
Result< Blob > Encode< Format::JPEG, Color::YUV420 >(Image< Color::YUV420 > img)
Definition encode.cpp:32
std::expected< T, Error > Result
Result< size_t > sizeOf(Color color, Size size)
Definition sizes.cpp:6