UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
color.h
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2022 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef COLOR_H_CD26B745_C30E_4DA3_8280_C9492B6BFF25
39#define COLOR_H_CD26B745_C30E_4DA3_8280_C9492B6BFF25
40
41#ifdef __cplusplus
42#include <cstdint>
43#else
44#include <assert.h>
45#include <stdint.h>
46#endif
47
48#include "utils/macros.h" // CLAMP
49
50/* @brief Color space coedfficients - RGB full range to YCbCr bt. 709 limited range
51 *
52 * RGB should use SDI full range [1<<(depth-8)..255<<(depth-8)-1], see [limits]
53 *
54 * Scaled by 1<<COMP_BASE, footroom 16/255, headroom 235/255 (luma), 240/255 (chroma); limits [2^(depth-8)..255*2^(depth-8)-1]
55 * matrix Y = [ 0.182586, 0.614231, 0.062007; -0.100643, -0.338572, 0.4392157; 0.4392157, -0.398942, -0.040274 ]
56 * * [coefficients]: https://gist.github.com/yohhoy/dafa5a47dade85d8b40625261af3776a "Rec. 709 coefficients"
57 * * [limits]: https://tech.ebu.ch/docs/r/r103.pdf "SDI limits"
58 *
59 * @ingroup lavc_video_conversions
60 *
61 * @todo
62 * Use this transformations in all conversions.
63 * @{
64 */
65typedef int32_t comp_type_t; // int32_t provides much better performance than int_fast32_t
66#define COMP_BASE (sizeof(comp_type_t) == 4 ? 14 : 18) // computation will be less precise when comp_type_t is 32 bit
67static_assert(sizeof(comp_type_t) * 8 >= COMP_BASE + 18, "comp_type_t not wide enough (we are computing in up to 16 bits!)");
68
69#define KG(kr,kb) (1.-kr-kb)
70#ifdef YCBCR_FULL
71#define C_EPS 0 // prevent under/overflows when there is no clip
72#define Y_LIMIT(out_depth) 1.0
73#define CBCR_LIMIT(out_depth) 1.0
74#else
75#define C_EPS 0.5
76#define Y_LIMIT(out_depth) \
77 (219. * (1 << ((out_depth) - 8)) / ((1 << (out_depth)) - 1))
78#define CBCR_LIMIT(out_depth) \
79 (224. * (1 << ((out_depth) - 8)) / ((1 << (out_depth)) - 1))
80#endif // !defined YCBCR_FULL
81
82#define KR_709 .212639
83#define KB_709 .072192
84#define KR_2020 .262700
85#define KB_2020 .059302
86#define KR_P3 .228975
87#define KB_P3 .079287
88
89#define KG_709 KG(KR_709,KB_709)
90#define D (2.*(KR_709+KG_709))
91#define E (2.*(1.-KR_709))
92
93#define Y_R(out_depth) \
94 ((comp_type_t) (((KR_709 * Y_LIMIT(out_depth)) * (1 << COMP_BASE)) + \
95 C_EPS))
96#define Y_G(out_depth) \
97 ((comp_type_t) (((KG_709 * Y_LIMIT(out_depth)) * (1 << COMP_BASE)) + \
98 C_EPS))
99#define Y_B(out_depth) \
100 ((comp_type_t) (((KB_709 * Y_LIMIT(out_depth)) * (1 << COMP_BASE)) + \
101 C_EPS))
102#define CB_R(out_depth) \
103 ((comp_type_t) (((-KR_709 / D * CBCR_LIMIT(out_depth)) * \
104 (1 << COMP_BASE)) - C_EPS))
105#define CB_G(out_depth) \
106 ((comp_type_t) (((-KG_709 / D * CBCR_LIMIT(out_depth)) * \
107 (1 << COMP_BASE)) - C_EPS))
108#define CB_B(out_depth) \
109 ((comp_type_t) ((((1 - KB_709) / D * CBCR_LIMIT(out_depth)) * \
110 (1 << COMP_BASE)) + C_EPS))
111#define CR_R(out_depth) \
112 ((comp_type_t) ((((1 - KR_709) / E * CBCR_LIMIT(out_depth)) * \
113 (1 << COMP_BASE)) - C_EPS))
114#define CR_G(out_depth) \
115 ((comp_type_t) (((-KG_709 / E * CBCR_LIMIT(out_depth)) * \
116 (1 << COMP_BASE)) - C_EPS))
117#define CR_B(out_depth) \
118 ((comp_type_t) (((-KB_709 / E * CBCR_LIMIT(out_depth)) * \
119 (1 << COMP_BASE)) + C_EPS))
120#define RGB_TO_Y_709_SCALED(out_depth, r, g, b) \
121 ((r) * Y_R(out_depth) + (g) * Y_G(out_depth) + (b) * Y_B(out_depth))
122#define RGB_TO_CB_709_SCALED(out_depth, r, g, b) \
123 ((r) * CB_R(out_depth) + (g) * CB_G(out_depth) + (b) * CB_B(out_depth))
124#define RGB_TO_CR_709_SCALED(out_depth, r, g, b) \
125 ((r) * CR_R(out_depth) + (g) * CR_G(out_depth) + (b) * CR_B(out_depth))
126#ifdef YCBCR_FULL
127#define LIMIT_LO(depth) 0
128#define LIMIT_HI_Y(depth) ((1<<(depth))-1)
129#define LIMIT_HI_CBCR(depth) ((1<<(depth))-1)
130#else
131#define LIMIT_LO(depth) (1<<((depth)-4))
132#define LIMIT_HI_Y(depth) (235 * (1<<((depth)-8)))
133#define LIMIT_HI_CBCR(depth) (240 * (1<<((depth)-8)))
134#endif
135// TODO: remove
136#define CLAMP_LIMITED_Y(val, depth) (val)
137#define CLAMP_LIMITED_CBCR(val, depth) (val)
138
139#define C_SIGN(x) ((x) > 0 ? 1. : -1.)
140#define SCALED(x) ((comp_type_t) (((x) * (1<<COMP_BASE)) + C_SIGN(x) * C_EPS))
141#define R_CR(in_depth, kr, kb) ((2. * (1. - (kr))) / CBCR_LIMIT(in_depth))
142#define G_CB(in_depth, kr, kb) \
143 ((-(kb) * (2. * ((kr) + KG(kr, kb))) / KG(kr, kb)) / \
144 CBCR_LIMIT(in_depth))
145#define G_CR(in_depth, kr, kb) \
146 ((-(kr) * (2. * (1. - (kr))) / KG(kr, kb)) / CBCR_LIMIT(in_depth))
147#define B_CB(in_depth, kr, kb) \
148 ((2. * ((kr) + KG(kr, kb))) / CBCR_LIMIT(in_depth))
149
150#define Y_LIMIT_INV(in_depth) (1./Y_LIMIT(in_depth))
151#define Y_SCALE(in_depth) \
152 SCALED(Y_LIMIT_INV(in_depth)) // precomputed value, Y multiplier is same
153 // for all channels
154#define YCBCR_TO_R_709_SCALED(in_depth, y, cb, cr) \
155 ((y) /* * r_y */ + (cr) * SCALED(R_CR(in_depth, KR_709, KB_709)))
156#define YCBCR_TO_G_709_SCALED(in_depth, y, cb, cr) \
157 ((y) /* * g_y */ + (cb) * SCALED(G_CB(in_depth, KR_709, KB_709)) + \
158 (cr) * SCALED(G_CR(in_depth, KR_709, KB_709)))
159#define YCBCR_TO_B_709_SCALED(in_depth, y, cb, cr) \
160 ((y) /* * b_y */ + (cb) * SCALED(B_CB(in_depth, KR_709, KB_709)))
161#define FULL_FOOT(depth) (1 << ((depth) - 8))
162#define FULL_HEAD(depth) ((255<<((depth)-8))-1)
163#define CLAMP_FULL(val, depth) CLAMP((val), FULL_FOOT(depth), FULL_HEAD(depth))
164
165// new API
167 short y_r, y_g, y_b;
168 short cb_r, cb_g, cb_b;
169 short cr_r, cr_g, cr_b;
170
171 short r_cr, g_cb, g_cr;
172 int b_cb; // b_cb is 34712 so doesn't fit to 16-bit short
173};
174const struct color_coeffs *get_color_coeffs(int ycbcr_bit_depth);
175#define RGB_TO_Y(t, r, g, b) ((r) * (t)->y_r + (g) * (t)->y_g + (b) * (t)->y_b)
176#define RGB_TO_CB(t, r, g, b) \
177 ((r) * (t)->cb_r + (g) * (t)->cb_g + (b) * (t)->cb_b)
178#define RGB_TO_CR(t, r, g, b) \
179 ((r) * (t)->cr_r + (g) * (t)->cr_g + (b) * (t)->cr_b)
181#define YCBCR_TO_R(t, y_scaled, cb, cr) ((y) + (cr) * (t)->r_cr)
182#define YCBCR_TO_G(t, y_scaled, cb, cr) \
183 ((y) + (cb) * (t)->g_cb + (cr) * (t)->g_cr)
184#define YCBCR_TO_B(t, y_scaled, cb, cr) ((y) + (cb) * (t)->b_cb)
185
189#define FORMAT_RGBA(r, g, b, rshift, gshift, bshift, alpha_mask, depth) \
190 ((alpha_mask) | (CLAMP_FULL((r), (depth)) << (rshift) | \
191 CLAMP_FULL((g), (depth)) << (gshift) | \
192 CLAMP_FULL((b), (depth)) << (bshift)))
194
195#define MK_MONOCHROME(val) \
196 FORMAT_RGBA((val), (val), (val), 0, 8, 16, 0xFF000000, 8)
197#define RGBA_BLACK MK_MONOCHROME(0x00)
198#define RGBA_GRAY MK_MONOCHROME(0x80)
199#define RGBA_WHITE MK_MONOCHROME(0xFF)
200
201#endif // !defined COLOR_H_CD26B745_C30E_4DA3_8280_C9492B6BFF25
int32_t comp_type_t
Definition color.h:65
#define COMP_BASE
Definition color.h:66
const struct color_coeffs * get_color_coeffs(int ycbcr_bit_depth)
Definition color.c:58
short y_g
Definition color.h:167
short y_b
Definition color.h:167
short cr_b
Definition color.h:169
short cr_r
Definition color.h:169
short g_cr
Definition color.h:171
short r_cr
Definition color.h:171
short y_r
Definition color.h:167
short cr_g
Definition color.h:169
short g_cb
Definition color.h:171
short cb_b
Definition color.h:168
short cb_g
Definition color.h:168
short cb_r
Definition color.h:168