Haio
0.2.X
Homebrew Asset IO/CDN
Toggle main menu visibility
Loading...
Searching...
No Matches
decode.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
7
#include <memory>
8
9
namespace
{
10
11
/** the handle owns a decompressor, and there is no path out of here that leaks it */
12
struct
Handle {
13
tjhandle raw =
nullptr
;
14
~Handle() {
if
(raw) tj3Destroy(raw); }
15
};
16
17
}
18
19
namespace
Haio::Codecs
{
20
21
/**
22
* straight to yuv planes, which is what the file already holds.
23
*
24
* a jpeg is yuv all the way down, so a decoder that hands back rgb has both thrown
25
* away the chroma layout and spent the work doing it. asking for the planes means the
26
* picture arrives as it was stored, and whoever wants rgb converts once, visibly.
27
*
28
* only 4:2:0 is read. it is what cameras and ad creatives produce, and reading 4:4:4
29
* or 4:2:2 into a buffer sized for 4:2:0 would quietly truncate the chroma rather
30
* than fail, so those are refused instead.
31
*/
32
template
<>
33
Result<Image<Color::YUV420>
>
Decode<Format::JPEG, Color::YUV420>
(
const
Blob& blob) {
34
Handle handle{tj3Init(TJINIT_DECOMPRESS)};
35
if
(!handle.raw)
HAIO_FAIL
(Internal,
"cannot start the jpeg decoder"
);
36
37
if
(tj3DecompressHeader(handle.raw, blob.data.data(), blob.data.size()) != 0) {
38
HAIO_FAIL
(InvalidInput,
"this is not a jpeg haio can read"
);
39
}
40
41
const
int
width = tj3Get(handle.raw, TJPARAM_JPEGWIDTH);
42
const
int
height = tj3Get(handle.raw, TJPARAM_JPEGHEIGHT);
43
const
int
sampling = tj3Get(handle.raw, TJPARAM_SUBSAMP);
44
45
if
(width <= 0 || height <= 0)
HAIO_FAIL
(InvalidInput,
"the jpeg has no area"
);
46
if
(sampling != TJSAMP_420) {
47
HAIO_FAIL
(UnsupportedFormat,
"haio reads 4:2:0 jpegs, and this one is not"
);
48
}
49
if
(width % 2 != 0 || height % 2 != 0) {
50
// 4:2:0 stores chroma for whole two by two blocks, so an odd side means the
51
// file's own planes are padded and would not line up with ours
52
HAIO_FAIL
(UnsupportedFormat,
"haio reads 4:2:0 jpegs with even sides, and this one is odd"
);
53
}
54
55
HAIO_TRY
(bytes,
sizeOf
(
Color::YUV420
, Size{width, height}));
56
std::vector<uint8_t> planes(bytes);
57
58
// align 1 means the planes sit back to back with no padding, which is the layout
59
// Color::YUV420 is defined as
60
if
(tj3DecompressToYUV8(handle.raw, blob.data.data(), blob.data.size(), planes.data(), 1) != 0) {
61
HAIO_FAIL
(InvalidInput,
"the jpeg could not be decoded"
);
62
}
63
return
Image<Color::YUV420>{width, height, std::move(planes)};
64
}
65
66
}
haio_codec.hpp
HAIO_TRY
#define HAIO_TRY(name, expr)
Definition
haio_codec.hpp:246
HAIO_FAIL
#define HAIO_FAIL(why, message)
Definition
haio_codec.hpp:258
haio_convert.hpp
Haio::Codecs
Definition
haio_codec.hpp:136
Haio::Codecs::Decode< Format::JPEG, Color::YUV420 >
Result< Image< Color::YUV420 > > Decode< Format::JPEG, Color::YUV420 >(const Blob &blob)
Definition
decode.cpp:33
Haio::Color::YUV420
@ YUV420
Definition
haio_formats.hpp:139
Haio::Result
std::expected< T, Error > Result
Definition
haio_codec.hpp:32
Haio::sizeOf
Result< size_t > sizeOf(Color color, Size size)
Definition
sizes.cpp:6
library
backend
codecs
container
jpeg
decode.cpp
Generated by
1.18.0