Add rec2020 and rec2020-linear
These are wide-gamut SDR colorstates and can be useful as compoisting color states.
This commit is contained in:
@@ -142,6 +142,32 @@ gdk_color_state_get_oklch (void)
|
||||
return GDK_COLOR_STATE_OKLCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_get_rec2020:
|
||||
*
|
||||
* Returns the color state object representing the rec2020 color space.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_color_state_get_rec2020 (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_REC2020;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_get_rec2020_linear:
|
||||
*
|
||||
* Returns the color state object representing the linear rec2020 color space.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_color_state_get_rec2020_linear (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_REC2020_LINEAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_equal:
|
||||
* @self: a `GdkColorState`
|
||||
@@ -415,6 +441,53 @@ gdk_default_xyz_to_oklab (GdkColorState *self,
|
||||
}
|
||||
}
|
||||
|
||||
static inline float
|
||||
rec2020_eotf (float v)
|
||||
{
|
||||
float alpha = 1.09929682680944;
|
||||
float beta = 0.018053968510807;
|
||||
|
||||
int sign = v < 0 ? -1 : 1;
|
||||
float abs = fabsf (v);
|
||||
|
||||
if (abs < beta * 4.5 )
|
||||
return v/ 4.5;
|
||||
else
|
||||
return sign * powf ((abs + alpha - 1) / alpha, 1.0 / 0.45);
|
||||
}
|
||||
|
||||
static inline float
|
||||
rec2020_oetf (float v)
|
||||
{
|
||||
float alpha = 1.09929682680944;
|
||||
float beta = 0.018053968510807;
|
||||
int sign = v < 0 ? -1 : 1;
|
||||
float abs = fabsf (v);
|
||||
|
||||
if (abs > beta)
|
||||
return sign * (alpha * powf (abs, 0.45) - (alpha - 1));
|
||||
else
|
||||
return 4.5 * v;
|
||||
}
|
||||
|
||||
COORDINATE_TRANSFORM(gdk_default_rec2020_to_rec2020_linear, rec2020_eotf)
|
||||
COORDINATE_TRANSFORM(gdk_default_rec2020_linear_to_rec2020, rec2020_oetf)
|
||||
|
||||
static const float rec2020_linear_to_xyz[3][3] = {
|
||||
{ (63426534.0 / 99577255.0), (20160776.0 / 139408157.0), (47086771.0 / 278816314.0) },
|
||||
{ (26158966.0 / 99577255.0), (472592308.0 / 697040785.0), (8267143.0 / 139408157.0) },
|
||||
{ ( 0 / 1), (19567812.0 / 697040785.0), (295819943.0 / 278816314.0) },
|
||||
};
|
||||
|
||||
static const float xyz_to_rec2020_linear[3][3] = {
|
||||
{ (30757411.0 / 17917100.0), - (6372589.0 / 17917100.0), - (4539589.0 / 17917100.0) },
|
||||
{ - (19765991.0 / 29648200.0), (47925759.0 / 29648200.0), (467509.0 / 29648200.0) },
|
||||
{ (792561.0 / 44930125.0), - (1921689.0 / 44930125.0), (42328811.0 / 44930125.0) },
|
||||
};
|
||||
|
||||
LINEAR_TRANSFORM(gdk_default_rec2020_linear_to_xyz, rec2020_linear_to_xyz)
|
||||
LINEAR_TRANSFORM(gdk_default_xyz_to_rec2020_linear, xyz_to_rec2020_linear)
|
||||
|
||||
#define CONCAT(name, f1, f2) \
|
||||
static void \
|
||||
name (GdkColorState *self, \
|
||||
@@ -429,6 +502,8 @@ CONCAT(gdk_default_xyz_to_srgb, gdk_default_xyz_to_srgb_linear, gdk_default_srgb
|
||||
CONCAT(gdk_default_srgb_to_xyz, gdk_default_srgb_to_srgb_linear, gdk_default_srgb_linear_to_xyz);
|
||||
CONCAT(gdk_default_oklch_to_xyz, gdk_default_oklch_to_oklab, gdk_default_oklab_to_xyz);
|
||||
CONCAT(gdk_default_xyz_to_oklch, gdk_default_xyz_to_oklab, gdk_default_oklab_to_oklch);
|
||||
CONCAT(gdk_default_rec2020_to_xyz, gdk_default_rec2020_to_rec2020_linear, gdk_default_rec2020_linear_to_xyz);
|
||||
CONCAT(gdk_default_xyz_to_rec2020, gdk_default_xyz_to_rec2020_linear, gdk_default_rec2020_linear_to_rec2020);
|
||||
|
||||
/* }}} */
|
||||
|
||||
@@ -484,6 +559,8 @@ GdkDefaultColorState gdk_default_color_states[] = {
|
||||
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = gdk_default_xyz_to_srgb_linear,
|
||||
[GDK_COLOR_STATE_ID_OKLAB] = gdk_default_xyz_to_oklab,
|
||||
[GDK_COLOR_STATE_ID_OKLCH] = gdk_default_xyz_to_oklch,
|
||||
[GDK_COLOR_STATE_ID_REC2020] = gdk_default_xyz_to_rec2020,
|
||||
[GDK_COLOR_STATE_ID_REC2020_LINEAR] = gdk_default_xyz_to_rec2020_linear,
|
||||
},
|
||||
},
|
||||
[GDK_COLOR_STATE_ID_OKLAB] = {
|
||||
@@ -512,6 +589,32 @@ GdkDefaultColorState gdk_default_color_states[] = {
|
||||
[GDK_COLOR_STATE_ID_XYZ] = gdk_default_oklch_to_xyz,
|
||||
},
|
||||
},
|
||||
[GDK_COLOR_STATE_ID_REC2020] = {
|
||||
.parent = {
|
||||
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
|
||||
.ref_count = 0,
|
||||
.depth = GDK_MEMORY_FLOAT16,
|
||||
.rendering_color_state = GDK_COLOR_STATE_REC2020_LINEAR,
|
||||
},
|
||||
.name = "rec2020",
|
||||
.no_srgb = NULL,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_XYZ] = gdk_default_rec2020_to_xyz,
|
||||
},
|
||||
},
|
||||
[GDK_COLOR_STATE_ID_REC2020_LINEAR] = {
|
||||
.parent = {
|
||||
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
|
||||
.ref_count = 0,
|
||||
.depth = GDK_MEMORY_FLOAT16,
|
||||
.rendering_color_state = GDK_COLOR_STATE_REC2020_LINEAR,
|
||||
},
|
||||
.name = "rec2020-linear",
|
||||
.no_srgb = NULL,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_XYZ] = gdk_default_rec2020_linear_to_xyz,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
|
||||
@@ -52,6 +52,12 @@ GdkColorState * gdk_color_state_get_oklab (void);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_oklch (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_rec2020 (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_rec2020_linear (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_state_equal (GdkColorState *self,
|
||||
GdkColorState *other);
|
||||
|
||||
@@ -13,6 +13,8 @@ typedef enum
|
||||
GDK_COLOR_STATE_ID_XYZ,
|
||||
GDK_COLOR_STATE_ID_OKLAB,
|
||||
GDK_COLOR_STATE_ID_OKLCH,
|
||||
GDK_COLOR_STATE_ID_REC2020,
|
||||
GDK_COLOR_STATE_ID_REC2020_LINEAR,
|
||||
|
||||
GDK_COLOR_STATE_N_IDS
|
||||
} GdkColorStateId;
|
||||
@@ -56,11 +58,13 @@ struct _GdkDefaultColorState
|
||||
|
||||
extern GdkDefaultColorState gdk_default_color_states[GDK_COLOR_STATE_N_IDS];
|
||||
|
||||
#define GDK_COLOR_STATE_SRGB ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_SRGB])
|
||||
#define GDK_COLOR_STATE_SRGB_LINEAR ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_SRGB_LINEAR])
|
||||
#define GDK_COLOR_STATE_XYZ ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_XYZ])
|
||||
#define GDK_COLOR_STATE_OKLAB ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_OKLAB])
|
||||
#define GDK_COLOR_STATE_OKLCH ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_OKLCH])
|
||||
#define GDK_COLOR_STATE_SRGB ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_SRGB])
|
||||
#define GDK_COLOR_STATE_SRGB_LINEAR ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_SRGB_LINEAR])
|
||||
#define GDK_COLOR_STATE_XYZ ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_XYZ])
|
||||
#define GDK_COLOR_STATE_OKLAB ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_OKLAB])
|
||||
#define GDK_COLOR_STATE_OKLCH ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_OKLCH])
|
||||
#define GDK_COLOR_STATE_REC2020 ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_REC2020])
|
||||
#define GDK_COLOR_STATE_REC2020_LINEAR ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_REC2020_LINEAR])
|
||||
|
||||
#define GDK_IS_DEFAULT_COLOR_STATE(c) ((GdkDefaultColorState *) (c) >= &gdk_default_color_states[0] && \
|
||||
(GdkDefaultColorState *) (c) < &gdk_default_color_states[GDK_COLOR_STATE_N_IDS])
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
#define GDK_COLOR_STATE_ID_XYZ 2u
|
||||
#define GDK_COLOR_STATE_ID_OKLAB 3u
|
||||
#define GDK_COLOR_STATE_ID_OKLCH 4u
|
||||
#define GDK_COLOR_STATE_ID_REC2020 5u
|
||||
#define GDK_COLOR_STATE_ID_REC2020_LINEAR 6u
|
||||
|
||||
#define TOP 0u
|
||||
#define RIGHT 1u
|
||||
|
||||
@@ -153,12 +153,81 @@ xyz_to_oklab (vec4 color)
|
||||
return vec4 (lab, color.a);
|
||||
}
|
||||
|
||||
float
|
||||
rec2020_eotf (float v)
|
||||
{
|
||||
float alpha = 1.09929682680944;
|
||||
float beta = 0.018053968510807;
|
||||
|
||||
float sign = v < 0.0 ? -1.0 : 1.0;
|
||||
float vabs = abs (v);
|
||||
|
||||
if (vabs < beta * 4.5)
|
||||
return v / 4.5;
|
||||
else
|
||||
return sign * pow ((vabs + alpha - 1.0) / alpha, 1.0 / 0.45);
|
||||
}
|
||||
|
||||
float
|
||||
rec2020_oetf (float v)
|
||||
{
|
||||
float alpha = 1.09929682680944;
|
||||
float beta = 0.018053968510807;
|
||||
float sign = v < 0.0 ? -1.0 : 1.0;
|
||||
float vabs = abs (v);
|
||||
|
||||
if (vabs > beta)
|
||||
return sign * (alpha * pow (vabs, 0.45) - (alpha - 1.0));
|
||||
else
|
||||
return 4.5 * v;
|
||||
}
|
||||
|
||||
vec4
|
||||
rec2020_to_rec2020_linear (vec4 color)
|
||||
{
|
||||
return vec4 (rec2020_eotf (color.r),
|
||||
rec2020_eotf (color.g),
|
||||
rec2020_eotf (color.b),
|
||||
color.a);
|
||||
}
|
||||
|
||||
vec4
|
||||
rec2020_linear_to_rec2020 (vec4 color)
|
||||
{
|
||||
return vec4 (rec2020_oetf (color.r),
|
||||
rec2020_oetf (color.g),
|
||||
rec2020_oetf (color.b),
|
||||
color.a);
|
||||
}
|
||||
|
||||
vec4
|
||||
rec2020_linear_to_xyz (vec4 color)
|
||||
{
|
||||
mat3 m = mat3 (63426534.0 / 99577255.0, 20160776.0 / 139408157.0, 47086771.0 / 278816314.0,
|
||||
26158966.0 / 99577255.0, 472592308.0 / 697040785.0, 8267143.0 / 139408157.0,
|
||||
0.0, 19567812.0 / 697040785.0, 295819943.0 / 278816314.0);
|
||||
|
||||
return vec4 (color.rgb * m, color.a);
|
||||
}
|
||||
|
||||
vec4
|
||||
xyz_to_rec2020_linear (vec4 color)
|
||||
{
|
||||
mat3 m = mat3 ( 30757411.0 / 17917100.0, -6372589.0 / 17917100.0, -4539589.0 / 17917100.0,
|
||||
-19765991.0 / 29648200.0, 47925759.0 / 29648200.0, 467509.0 / 29648200.0,
|
||||
792561.0 / 44930125.0, -1921689.0 / 44930125.0, 42328811.0 / 44930125.0);
|
||||
|
||||
return vec4 (color.xyz * m, color.z);
|
||||
}
|
||||
|
||||
#define CONCAT(f, f1, f2) vec4 f(vec4 color) { return f2(f1(color)); }
|
||||
|
||||
CONCAT(srgb_to_xyz, srgb_to_srgb_linear, srgb_linear_to_xyz)
|
||||
CONCAT(xyz_to_srgb, xyz_to_srgb_linear, srgb_linear_to_srgb)
|
||||
CONCAT(oklch_to_xyz, oklch_to_oklab, oklab_to_xyz)
|
||||
CONCAT(xyz_to_oklch, xyz_to_oklab, oklab_to_oklch)
|
||||
CONCAT(rec2020_to_xyz, rec2020_to_rec2020_linear, rec2020_linear_to_xyz)
|
||||
CONCAT(xyz_to_rec2020, xyz_to_rec2020_linear, rec2020_linear_to_rec2020)
|
||||
|
||||
#define PAIR(_from_cs, _to_cs) ((_from_cs) << 16 | (_to_cs))
|
||||
|
||||
@@ -188,6 +257,12 @@ do_conversion (vec4 color,
|
||||
case PAIR (GDK_COLOR_STATE_ID_OKLCH, GDK_COLOR_STATE_ID_XYZ):
|
||||
result = oklch_to_xyz (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_REC2020, GDK_COLOR_STATE_ID_XYZ):
|
||||
result = rec2020_to_xyz (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_REC2020_LINEAR, GDK_COLOR_STATE_ID_XYZ):
|
||||
result = rec2020_linear_to_xyz (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_SRGB_LINEAR):
|
||||
result = xyz_to_srgb_linear (color);
|
||||
break;
|
||||
@@ -200,6 +275,12 @@ do_conversion (vec4 color,
|
||||
case PAIR (GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_OKLCH):
|
||||
result = xyz_to_oklch (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_REC2020):
|
||||
result = xyz_to_rec2020 (color);
|
||||
break;
|
||||
case PAIR (GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_REC2020_LINEAR):
|
||||
result = xyz_to_rec2020_linear (color);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -50,7 +50,7 @@ image_distance (const guchar *data,
|
||||
static void
|
||||
test_convert (gconstpointer testdata)
|
||||
{
|
||||
GdkColorState *cs;
|
||||
GdkColorState *cs = (GdkColorState *) testdata;
|
||||
char *path;
|
||||
GdkTexture *texture;
|
||||
GdkTextureDownloader *downloader;
|
||||
@@ -62,8 +62,6 @@ test_convert (gconstpointer testdata)
|
||||
gsize size;
|
||||
gsize stride;
|
||||
|
||||
cs = gdk_color_state_get_by_id ((GdkColorStateId) GPOINTER_TO_UINT (testdata));
|
||||
|
||||
path = g_test_build_filename (G_TEST_DIST, "image-data", "image.png", NULL);
|
||||
|
||||
texture = gdk_texture_new_from_filename (path, &error);
|
||||
@@ -110,10 +108,12 @@ main (int argc, char *argv[])
|
||||
(g_test_init) (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/colorstate/srgb", test_srgb);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->srgb-linear", GUINT_TO_POINTER (GDK_COLOR_STATE_ID_SRGB_LINEAR), test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->xyz", GUINT_TO_POINTER (GDK_COLOR_STATE_ID_XYZ), test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->oklab", GUINT_TO_POINTER (GDK_COLOR_STATE_ID_OKLAB), test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->oklch", GUINT_TO_POINTER (GDK_COLOR_STATE_ID_OKLCH), test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->srgb-linear", GDK_COLOR_STATE_SRGB_LINEAR, test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->xyz", GDK_COLOR_STATE_XYZ, test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->oklab", GDK_COLOR_STATE_OKLAB, test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->oklch", GDK_COLOR_STATE_OKLCH, test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->rec2020", GDK_COLOR_STATE_REC2020, test_convert);
|
||||
g_test_add_data_func ("/colorstate/convert/srgb<->rec2020-linear", GDK_COLOR_STATE_REC2020_LINEAR, test_convert);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user