Haio 0.2.X
Homebrew Asset IO/CDN
Loading...
Searching...
No Matches
rgba8888.cpp
Go to the documentation of this file.
2
3namespace Haio::Codecs {
4
5/**
6 * jfif colour, which is full range bt.601 and not the studio range video uses. a
7 * decoder written against the video coefficients produces a picture that is visibly
8 * washed out rather than obviously wrong, which is the sort of mistake that ships.
9 *
10 * the two chroma planes are half size in both directions, so each of their samples
11 * covers a two by two block of luma.
12 */
13template <>
14Result<void> Move<Color::YUV420, Color::RGBA8888>(Bytes src, std::span<uint8_t> dst, Size size) {
15 if (size.width % 2 != 0 || size.height % 2 != 0) {
16 HAIO_FAIL(InvalidInput, "yuv420 needs even width and height");
17 }
18
19 const auto width = static_cast<size_t>(size.width);
20 const auto height = static_cast<size_t>(size.height);
21 const auto pixels = width * height;
22 const auto half = width / 2;
23 const auto chroma = half * (height / 2);
24
25 if (src.size() < pixels + chroma * 2 || dst.size() < pixels * 4) {
26 HAIO_FAIL(InvalidInput, "yuv420 to rgba8888 got a buffer that is too small");
27 }
28
29 const auto* luma = src.data();
30 const auto* blue = luma + pixels;
31 const auto* red = blue + chroma;
32
33 const auto clamp = [](int value) {
34 return static_cast<uint8_t>(value < 0 ? 0 : value > 255 ? 255 : value);
35 };
36
37 for (size_t y = 0; y < height; y++) {
38 const auto chromaRow = (y / 2) * half;
39 for (size_t x = 0; x < width; x++) {
40 const int Y = luma[y * width + x];
41 const int Cb = blue[chromaRow + x / 2] - 128;
42 const int Cr = red[chromaRow + x / 2] - 128;
43
44 // the coefficients are the jfif ones, scaled by 1024 to stay in integers
45 const auto at = (y * width + x) * 4;
46 dst[at + 0] = clamp(Y + ((1436 * Cr) >> 10));
47 dst[at + 1] = clamp(Y - ((352 * Cb + 731 * Cr) >> 10));
48 dst[at + 2] = clamp(Y + ((1815 * Cb) >> 10));
49 dst[at + 3] = 0xFF;
50 }
51 }
52 return {};
53}
54
55template <>
57 return convertVia<Color::YUV420, Color::RGBA8888>(std::move(src));
58}
59
60}
#define HAIO_FAIL(why, message)
Result< Image< To > > convertVia(Image< From > src)
Result< Image< Color::RGBA8888 > > Convert< Color::YUV420, Color::RGBA8888 >(Image< Color::YUV420 > src)
Definition rgba8888.cpp:56
Result< void > Move< Color::YUV420, Color::RGBA8888 >(Bytes src, std::span< uint8_t > dst, Size size)
Definition rgba8888.cpp:14
std::expected< T, Error > Result
std::span< const uint8_t > Bytes