mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-21 17:40:23 +00:00
color.c: generalize the macros
do not assume just BT.709 coefficients
This commit is contained in:
88
src/color.c
88
src/color.c
@@ -42,53 +42,63 @@
|
||||
|
||||
#include "types.h" // for depth
|
||||
|
||||
#define KG_709 KG(KR_709,KB_709)
|
||||
#define D (2.*(KR_709+KG_709))
|
||||
#define E (2.*(1.-KR_709))
|
||||
#define D(kr, kb) (2. * ((kr) + KG(kr, kb)))
|
||||
#define E(kr) (2. * (1. - (kr)))
|
||||
|
||||
#define Y_R(out_depth) \
|
||||
((comp_type_t) (((KR_709 * Y_LIMIT(out_depth)) * (1 << COMP_BASE)) + \
|
||||
#define Y_R(out_depth, kr, kb) \
|
||||
((comp_type_t) (((kr * Y_LIMIT(out_depth)) * (1 << COMP_BASE)) + C_EPS))
|
||||
#define Y_G(out_depth, kr, kb) \
|
||||
((comp_type_t) (((KG(kr, kb) * Y_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) + \
|
||||
C_EPS))
|
||||
#define Y_G(out_depth) \
|
||||
((comp_type_t) (((KG_709 * Y_LIMIT(out_depth)) * (1 << COMP_BASE)) + \
|
||||
#define Y_B(out_depth, kr, kb) \
|
||||
((comp_type_t) ((((kb) * Y_LIMIT(out_depth)) * (1 << COMP_BASE)) + \
|
||||
C_EPS))
|
||||
#define Y_B(out_depth) \
|
||||
((comp_type_t) (((KB_709 * Y_LIMIT(out_depth)) * (1 << COMP_BASE)) + \
|
||||
#define CB_R(out_depth, kr, kb) \
|
||||
((comp_type_t) (((-(kr) / D(kr, kb) * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) - \
|
||||
C_EPS))
|
||||
#define CB_G(out_depth, kr, kb) \
|
||||
((comp_type_t) (((-KG(kr, kb) / D(kr, kb) * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) - \
|
||||
C_EPS))
|
||||
#define CB_B(out_depth, kr, kb) \
|
||||
((comp_type_t) ((((1 - (kb)) / D(kr, kb) * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) + \
|
||||
C_EPS))
|
||||
#define CR_R(out_depth, kr, kb) \
|
||||
((comp_type_t) ((((1 - (kr)) / E(kr) * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) - \
|
||||
C_EPS))
|
||||
#define CR_G(out_depth, kr, kb) \
|
||||
((comp_type_t) (((-KG(kr, kb) / E(kr) * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) - \
|
||||
C_EPS))
|
||||
#define CR_B(out_depth, kr, kb) \
|
||||
((comp_type_t) (((-(kb) / E(kr) * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) + \
|
||||
C_EPS))
|
||||
#define CB_R(out_depth) \
|
||||
((comp_type_t) (((-KR_709 / D * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) - C_EPS))
|
||||
#define CB_G(out_depth) \
|
||||
((comp_type_t) (((-KG_709 / D * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) - C_EPS))
|
||||
#define CB_B(out_depth) \
|
||||
((comp_type_t) ((((1 - KB_709) / D * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) + C_EPS))
|
||||
#define CR_R(out_depth) \
|
||||
((comp_type_t) ((((1 - KR_709) / E * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) - C_EPS))
|
||||
#define CR_G(out_depth) \
|
||||
((comp_type_t) (((-KG_709 / E * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) - C_EPS))
|
||||
#define CR_B(out_depth) \
|
||||
((comp_type_t) (((-KB_709 / E * CBCR_LIMIT(out_depth)) * \
|
||||
(1 << COMP_BASE)) + C_EPS))
|
||||
|
||||
#define COEFFS(depth) \
|
||||
#define COEFFS(depth, kr, kb) \
|
||||
{ \
|
||||
Y_R(depth), Y_G(depth), Y_B(depth),\
|
||||
CB_R(depth), CB_G(depth), CB_B(depth),\
|
||||
CR_R(depth), CR_G(depth), CR_B(depth),\
|
||||
Y_R(depth, kr, kb), Y_G(depth, kr, kb), Y_B(depth, kr, kb),\
|
||||
CB_R(depth, kr, kb), CB_G(depth, kr, kb), CB_B(depth, kr, kb),\
|
||||
CR_R(depth, kr, kb), CR_G(depth, kr, kb), CR_B(depth, kr, kb),\
|
||||
\
|
||||
SCALED(R_CR(depth, KR_709, KB_709)), \
|
||||
SCALED(G_CB(depth, KR_709, KB_709)), \
|
||||
SCALED(G_CR(depth, KR_709, KB_709)), \
|
||||
SCALED(B_CB(depth, KR_709, KB_709)), \
|
||||
SCALED(R_CR(depth, kr, kb)), \
|
||||
SCALED(G_CB(depth, kr, kb)), \
|
||||
SCALED(G_CR(depth, kr, kb)), \
|
||||
SCALED(B_CB(depth, kr, kb)), \
|
||||
}
|
||||
|
||||
#define COEFFS_709(depth) COEFFS(depth, KR_709, KB_709)
|
||||
|
||||
/**
|
||||
* @brief returns color coefficient for RGB<-YCbCr conversion
|
||||
*
|
||||
* Using BT.709 by default.
|
||||
*
|
||||
*
|
||||
* @note
|
||||
* It is suggested to copy the result to a struct (not using the returned ptr
|
||||
* directly) when passing to RGB_TO_*() or YCBCR_TO_*(). The compiler may not
|
||||
@@ -99,10 +109,10 @@
|
||||
const struct color_coeffs *
|
||||
get_color_coeffs(int ycbcr_bit_depth)
|
||||
{
|
||||
static const struct color_coeffs col_cfs_8 = COEFFS(DEPTH8);
|
||||
static const struct color_coeffs col_cfs_10 = COEFFS(DEPTH10);
|
||||
static const struct color_coeffs col_cfs_12 = COEFFS(DEPTH12);
|
||||
static const struct color_coeffs col_cfs_16 = COEFFS(DEPTH16);
|
||||
static const struct color_coeffs col_cfs_8 = COEFFS_709(DEPTH8);
|
||||
static const struct color_coeffs col_cfs_10 = COEFFS_709(DEPTH10);
|
||||
static const struct color_coeffs col_cfs_12 = COEFFS_709(DEPTH12);
|
||||
static const struct color_coeffs col_cfs_16 = COEFFS_709(DEPTH16);
|
||||
switch ((enum depth) ycbcr_bit_depth) {
|
||||
case DEPTH8:
|
||||
return &col_cfs_8;
|
||||
|
||||
18
src/color.h
18
src/color.h
@@ -47,20 +47,25 @@
|
||||
|
||||
#include "utils/macros.h" // CLAMP
|
||||
|
||||
/* @brief Color space coedfficients - RGB full range to YCbCr bt. 709 limited range
|
||||
/**
|
||||
* @file
|
||||
* @brief Color space coedfficients and limits
|
||||
*
|
||||
* RGB should use SDI full range [1<<(depth-8)..255<<(depth-8)-1], see [limits]
|
||||
* RGB should use SDI full range [1<<(depth-8)..255<<(depth-8)-1], YCbCr
|
||||
* limited, see [limits].
|
||||
*
|
||||
* The coefficients are scaled by 1<<COMP_BASE.
|
||||
*
|
||||
* limited footroom is (1<<(limited_depth - 4)), headroom 235*(limited_depth-8)
|
||||
* /luma/, 240*(limited_depth-8)/255 /chroma/; full-range limits
|
||||
* [2^(depth-8)..255*2^(depth-8)-1] (excludes vals with 0x00 and 0xFF MSB).
|
||||
*
|
||||
* Scaled by 1<<COMP_BASE, footroom 16/255, headroom 235/255 (luma), 240/255 (chroma); limits [2^(depth-8)..255*2^(depth-8)-1]
|
||||
* matrix Y = [ 0.182586, 0.614231, 0.062007; -0.100643, -0.338572, 0.4392157; 0.4392157, -0.398942, -0.040274 ]
|
||||
* * [coefficients]: https://gist.github.com/yohhoy/dafa5a47dade85d8b40625261af3776a "Rec. 709 coefficients"
|
||||
* * [limits]: https://tech.ebu.ch/docs/r/r103.pdf "SDI limits"
|
||||
*
|
||||
* @ingroup lavc_video_conversions
|
||||
*
|
||||
* @todo
|
||||
* Use this transformations in all conversions.
|
||||
* @{
|
||||
*/
|
||||
typedef int32_t comp_type_t; // int32_t provides much better performance than int_fast32_t
|
||||
#define COMP_BASE (sizeof(comp_type_t) == 4 ? 14 : 18) // computation will be less precise when comp_type_t is 32 bit
|
||||
@@ -136,7 +141,6 @@ static_assert(sizeof(comp_type_t) * 8 >= COMP_BASE + 18, "comp_type_t not wide e
|
||||
((alpha_mask) | (CLAMP_FULL((r), (depth)) << (rshift) | \
|
||||
CLAMP_FULL((g), (depth)) << (gshift) | \
|
||||
CLAMP_FULL((b), (depth)) << (bshift)))
|
||||
/// @}
|
||||
|
||||
#define MK_MONOCHROME(val) \
|
||||
FORMAT_RGBA((val), (val), (val), 0, 8, 16, 0xFF000000, 8)
|
||||
|
||||
Reference in New Issue
Block a user