1
0
Fork 0
forked from wry/wry

color-management: make (ext_)srgb aliases for gamma22

This commit is contained in:
Julian Orth 2025-09-05 12:43:23 +02:00
parent 48a36a9feb
commit 32db933242
21 changed files with 21 additions and 115 deletions

View file

@ -86,7 +86,7 @@ impl DamageTracking {
}
DamageTrackingCmd::SetColor(c) => {
let color = parse_color(&c.color);
let [r, g, b, a] = color.to_array(TransferFunction::Srgb);
let [r, g, b, a] = color.to_array(TransferFunction::Gamma22);
tc.send(SetVisualizerColor {
self_id: dt,
r,

View file

@ -63,7 +63,7 @@ impl ColorManager {
Some(NamedPrimaries::Srgb),
Primaries::SRGB,
Luminance::SRGB,
TransferFunction::Srgb,
TransferFunction::Gamma22,
Primaries::SRGB,
Luminance::SRGB.to_target(),
None,

View file

@ -2,14 +2,12 @@ use linearize::Linearize;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Linearize)]
pub enum TransferFunction {
Srgb,
Linear,
St2084Pq,
Bt1886,
Gamma22,
Gamma28,
St240,
ExtSrgb,
Log100,
Log316,
St428,

View file

@ -2365,7 +2365,7 @@ impl ConfigProxyHandler {
fn handle_get_color(&self, colorable: Colorable) -> Result<(), CphError> {
let color = self.get_color(colorable)?.get();
let [r, g, b, a] = color.to_array(TransferFunction::Srgb);
let [r, g, b, a] = color.to_array(TransferFunction::Gamma22);
let color = jay_config::theme::Color::new_f32_premultiplied(r, g, b, a);
self.respond(Response::GetColor { color });
Ok(())

View file

@ -309,7 +309,7 @@ fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) -> Option<SyncFile> {
}
fn fill_boxes3(ctx: &GlRenderContext, boxes: &[[f32; 2]], color: &Color) {
let [r, g, b, a] = color.to_array(TransferFunction::Srgb);
let [r, g, b, a] = color.to_array(TransferFunction::Gamma22);
let gles = ctx.ctx.dpy.gles;
unsafe {
(gles.glUseProgram)(ctx.fill_prog.prog);

View file

@ -82,7 +82,7 @@ impl Framebuffer {
(gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo);
(gles.glViewport)(0, 0, self.gl.width, self.gl.height);
if let Some(c) = clear {
let [r, g, b, a] = c.to_array(TransferFunction::Srgb);
let [r, g, b, a] = c.to_array(TransferFunction::Gamma22);
(gles.glClearColor)(r, g, b, a);
(gles.glClear)(GL_COLOR_BUFFER_BIT);
}

View file

@ -3,60 +3,16 @@
#include "frag_spec_const.glsl"
#define TF_SRGB 0
#define TF_LINEAR 1
#define TF_ST2084_PQ 2
#define TF_GAMMA24 3
#define TF_GAMMA22 4
#define TF_GAMMA28 5
#define TF_ST240 6
#define TF_EXT_SRGB 7
#define TF_LOG100 8
#define TF_LOG316 9
#define TF_ST428 10
vec3 eotf_srgb(vec3 c) {
return mix(
c * vec3(1.0 / 12.92),
pow((c + vec3(0.055)) / vec3(1.055), vec3(2.4)),
greaterThan(c, vec3(0.04045))
);
}
vec3 oetf_srgb(vec3 c) {
c = clamp(c, 0.0, 1.0);
return mix(
c * vec3(12.92),
vec3(1.055) * pow(c, vec3(1/2.4)) - vec3(0.055),
greaterThan(c, vec3(0.0031308))
);
}
vec3 eotf_ext_srgb(vec3 c) {
return mix(
-pow((c - vec3(0.055)) / vec3(-1.055), vec3(2.4)),
mix(
c * vec3(1.0 / 12.92),
pow((c + vec3(0.055)) / vec3(1.055), vec3(2.4)),
greaterThan(c, vec3(0.04045))
),
greaterThan(c, vec3(-0.04045))
);
}
vec3 oetf_ext_srgb(vec3 c) {
c = clamp(c, -0.6038, 7.5913);
return mix(
vec3(-1.055) * pow(-c, vec3(1/2.4)) + vec3(0.055),
mix(
c * vec3(12.92),
vec3(1.055) * pow(c, vec3(1/2.4)) - vec3(0.055),
greaterThan(c, vec3(0.0031308))
),
greaterThan(c, vec3(-0.0031308))
);
}
vec3 eotf_st2084_pq(vec3 c) {
c = clamp(c, 0.0, 1.0);
vec3 cp = pow(c, vec3(1.0 / 78.84375));
@ -126,14 +82,12 @@ vec3 oetf_st428(vec3 c) {
vec3 apply_eotf(vec3 c) {
switch (eotf) {
case TF_SRGB: return eotf_srgb(c);
case TF_LINEAR: return c;
case TF_ST2084_PQ: return eotf_st2084_pq(c);
case TF_GAMMA24: return sign(c) * pow(abs(c), vec3(2.4));
case TF_GAMMA22: return sign(c) * pow(abs(c), vec3(2.2));
case TF_GAMMA28: return sign(c) * pow(abs(c), vec3(2.8));
case TF_ST240: return eotf_st240(c);
case TF_EXT_SRGB: return eotf_ext_srgb(c);
case TF_LOG100: return eotf_log100(c);
case TF_LOG316: return eotf_log316(c);
case TF_ST428: return eotf_st428(c);
@ -143,14 +97,12 @@ vec3 apply_eotf(vec3 c) {
vec3 apply_oetf(vec3 c) {
switch (oetf) {
case TF_SRGB: return oetf_srgb(c);
case TF_LINEAR: return c;
case TF_ST2084_PQ: return oetf_st2084_pq(c);
case TF_GAMMA24: return sign(c) * pow(abs(c), vec3(1.0 / 2.4));
case TF_GAMMA22: return sign(c) * pow(abs(c), vec3(1.0 / 2.2));
case TF_GAMMA28: return sign(c) * pow(abs(c), vec3(1.0 / 2.8));
case TF_ST240: return oetf_st240(c);
case TF_EXT_SRGB: return oetf_ext_srgb(c);
case TF_LOG100: return oetf_log100(c);
case TF_LOG316: return oetf_log316(c);
case TF_ST428: return oetf_st428(c);

View file

@ -1,13 +1,11 @@
use crate::cmm::cmm_transfer_function::TransferFunction;
pub const TF_SRGB: u32 = 0;
pub const TF_LINEAR: u32 = 1;
pub const TF_ST2084_PQ: u32 = 2;
pub const TF_GAMMA24: u32 = 3;
pub const TF_GAMMA22: u32 = 4;
pub const TF_GAMMA28: u32 = 5;
pub const TF_ST240: u32 = 6;
pub const TF_EXT_SRGB: u32 = 7;
pub const TF_LOG100: u32 = 8;
pub const TF_LOG316: u32 = 9;
pub const TF_ST428: u32 = 10;
@ -19,14 +17,12 @@ pub trait TransferFunctionExt: Sized {
impl TransferFunctionExt for TransferFunction {
fn to_vulkan(self) -> u32 {
match self {
TransferFunction::Srgb => TF_SRGB,
TransferFunction::Linear => TF_LINEAR,
TransferFunction::St2084Pq => TF_ST2084_PQ,
TransferFunction::Bt1886 => TF_GAMMA24,
TransferFunction::Gamma22 => TF_GAMMA22,
TransferFunction::Gamma28 => TF_GAMMA28,
TransferFunction::St240 => TF_ST240,
TransferFunction::ExtSrgb => TF_EXT_SRGB,
TransferFunction::Log100 => TF_LOG100,
TransferFunction::Log316 => TF_LOG316,
TransferFunction::St428 => TF_ST428,

View file

@ -221,7 +221,7 @@ impl PathBuilderExt for PathBuilder {
impl From<crate::theme::Color> for Color {
fn from(v: crate::theme::Color) -> Self {
let [r, g, b, a] = v.to_array(TransferFunction::Srgb);
let [r, g, b, a] = v.to_array(TransferFunction::Gamma22);
let mut c = Self::TRANSPARENT;
c.set_red(r / a);
c.set_green(g / a);
@ -242,7 +242,7 @@ fn calculate_accents(srgb: crate::theme::Color) -> [Color; 2] {
}
fn srgb_to_lab(srgb: crate::theme::Color) -> [f32; 4] {
let [mut r, mut g, mut b, alpha] = srgb.to_array(TransferFunction::Srgb);
let [mut r, mut g, mut b, alpha] = srgb.to_array(TransferFunction::Gamma22);
if alpha < 1.0 {
r /= alpha;
g /= alpha;

View file

@ -109,8 +109,8 @@ impl WpImageDescriptionCreatorParamsV1RequestHandler for WpImageDescriptionCreat
TRANSFER_FUNCTION_EXT_LINEAR => TransferFunction::Linear,
TRANSFER_FUNCTION_LOG_100 => TransferFunction::Log100,
TRANSFER_FUNCTION_LOG_316 => TransferFunction::Log316,
TRANSFER_FUNCTION_SRGB => TransferFunction::Srgb,
TRANSFER_FUNCTION_EXT_SRGB => TransferFunction::ExtSrgb,
TRANSFER_FUNCTION_SRGB => TransferFunction::Gamma22,
TRANSFER_FUNCTION_EXT_SRGB => TransferFunction::Gamma22,
TRANSFER_FUNCTION_ST2084_PQ => TransferFunction::St2084Pq,
TRANSFER_FUNCTION_ST428 => TransferFunction::St428,
_ => {

View file

@ -8,11 +8,10 @@ use {
ifs::color_management::{
MIN_LUM_MUL, PRIMARIES_ADOBE_RGB, PRIMARIES_BT2020, PRIMARIES_CIE1931_XYZ,
PRIMARIES_DCI_P3, PRIMARIES_DISPLAY_P3, PRIMARIES_GENERIC_FILM, PRIMARIES_MUL,
PRIMARIES_NTSC, PRIMARIES_PAL, PRIMARIES_PAL_M, TRANSFER_FUNCTION_BT1886,
TRANSFER_FUNCTION_EXT_LINEAR, TRANSFER_FUNCTION_EXT_SRGB, TRANSFER_FUNCTION_GAMMA22,
PRIMARIES_NTSC, PRIMARIES_PAL, PRIMARIES_PAL_M, PRIMARIES_SRGB,
TRANSFER_FUNCTION_BT1886, TRANSFER_FUNCTION_EXT_LINEAR, TRANSFER_FUNCTION_GAMMA22,
TRANSFER_FUNCTION_GAMMA28, TRANSFER_FUNCTION_LOG_100, TRANSFER_FUNCTION_LOG_316,
TRANSFER_FUNCTION_ST240, TRANSFER_FUNCTION_ST428, TRANSFER_FUNCTION_ST2084_PQ,
consts::{PRIMARIES_SRGB, TRANSFER_FUNCTION_SRGB},
},
leaks::Tracker,
object::{Object, Version},
@ -33,14 +32,12 @@ pub struct WpImageDescriptionInfoV1 {
impl WpImageDescriptionInfoV1 {
pub fn send_description(&self, d: &ColorDescription) {
let tf = match d.transfer_function {
TransferFunction::Srgb => TRANSFER_FUNCTION_SRGB,
TransferFunction::Linear => TRANSFER_FUNCTION_EXT_LINEAR,
TransferFunction::St2084Pq => TRANSFER_FUNCTION_ST2084_PQ,
TransferFunction::Bt1886 => TRANSFER_FUNCTION_BT1886,
TransferFunction::Gamma22 => TRANSFER_FUNCTION_GAMMA22,
TransferFunction::Gamma28 => TRANSFER_FUNCTION_GAMMA28,
TransferFunction::St240 => TRANSFER_FUNCTION_ST240,
TransferFunction::ExtSrgb => TRANSFER_FUNCTION_EXT_SRGB,
TransferFunction::Log100 => TRANSFER_FUNCTION_LOG_100,
TransferFunction::Log316 => TRANSFER_FUNCTION_LOG_316,
TransferFunction::St428 => TRANSFER_FUNCTION_ST428,

View file

@ -97,7 +97,7 @@ impl JayDamageTrackingRequestHandler for JayDamageTracking {
req: SetVisualizerColor,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
let color = Color::new(TransferFunction::Srgb, req.r, req.g, req.b) * req.a;
let color = Color::new(TransferFunction::Gamma22, req.r, req.g, req.b) * req.a;
self.client.state.damage_visualizer.set_color(color);
Ok(())
}

View file

@ -353,7 +353,7 @@ impl WlOutputGlobal {
};
luminance.white.0 = luminance.max.0 * brightness / output_max;
}
TransferFunction::Srgb
TransferFunction::Gamma22
}
BackendTransferFunction::Pq => {
luminance = Luminance::ST2084_PQ;

View file

@ -32,7 +32,7 @@ impl TestSinglePixelBufferManager {
destroyed: Cell::new(false),
});
let map = |c: f32| (c as f64 * u32::MAX as f64) as u32;
let [r, g, b, a] = color.to_array(TransferFunction::Srgb);
let [r, g, b, a] = color.to_array(TransferFunction::Gamma22);
self.tran.send(CreateU32RgbaBuffer {
self_id: self.id,
id: obj.id,

View file

@ -79,7 +79,7 @@ pub fn render(
let data = create_data(font, width, height, scale)?;
data.layout.set_text(text);
let font_height = data.layout.pixel_size().1;
let [r, g, b, a] = color.to_array(TransferFunction::Srgb);
let [r, g, b, a] = color.to_array(TransferFunction::Gamma22);
data.cctx.set_operator(CAIRO_OPERATOR_SOURCE);
data.cctx.set_source_rgba(r as _, g as _, b as _, a as _);
let y = y.unwrap_or((height - font_height) / 2);

View file

@ -188,7 +188,7 @@ fn render(
data.layout.set_text(text);
}
let font_height = data.layout.pixel_size().1;
let [r, g, b, a] = color.to_array(TransferFunction::Srgb);
let [r, g, b, a] = color.to_array(TransferFunction::Gamma22);
data.cctx.set_operator(CAIRO_OPERATOR_SOURCE);
data.cctx.set_source_rgba(r as _, g as _, b as _, a as _);
let y = y.unwrap_or((height - font_height) / 2);

View file

@ -69,13 +69,6 @@ impl Color {
};
pub fn new(transfer_function: TransferFunction, mut r: f32, mut g: f32, mut b: f32) -> Self {
fn srgb(c: f32) -> f32 {
if c <= 0.04045 {
c / 12.92
} else {
((c + 0.055) / 1.055).powf(2.4)
}
}
#[inline(always)]
fn linear(c: f32) -> f32 {
c
@ -86,16 +79,6 @@ impl Color {
let den = 18.8515625 - 18.6875 * cp;
(num / den).powf(1.0 / 0.1593017578125)
}
fn ext_srgb(c: f32) -> f32 {
let c = c.clamp(-0.6038, 7.5913);
if c <= -0.0031308 {
-1.055 * (-c).powf(1.0 / 2.4) + 0.055
} else if c <= 0.0031308 {
c * 12.92
} else {
1.055 * c.powf(1.0 / 2.4) - 0.055
}
}
fn st240(c: f32) -> f32 {
if c < 0.0913 {
c / 4.0
@ -129,14 +112,12 @@ impl Color {
}};
}
match transfer_function {
TransferFunction::Srgb => convert!(srgb),
TransferFunction::Linear => convert!(linear),
TransferFunction::St2084Pq => convert!(st2084_pq),
TransferFunction::Bt1886 => convert!(gamma24),
TransferFunction::Gamma22 => convert!(gamma22),
TransferFunction::Gamma28 => convert!(gamma28),
TransferFunction::St240 => convert!(st240),
TransferFunction::ExtSrgb => convert!(ext_srgb),
TransferFunction::Log100 => convert!(log100),
TransferFunction::Log316 => convert!(log316),
TransferFunction::St428 => convert!(st428),
@ -175,12 +156,12 @@ impl Color {
}
pub fn from_srgb(r: u8, g: u8, b: u8) -> Self {
Self::new(TransferFunction::Srgb, to_f32(r), to_f32(g), to_f32(b))
Self::new(TransferFunction::Gamma22, to_f32(r), to_f32(g), to_f32(b))
}
pub fn from_srgba_premultiplied(r: u8, g: u8, b: u8, a: u8) -> Self {
Self::new_premultiplied(
TransferFunction::Srgb,
TransferFunction::Gamma22,
to_f32(r),
to_f32(g),
to_f32(b),
@ -208,7 +189,7 @@ impl Color {
}
pub fn from_srgba_straight(r: u8, g: u8, b: u8, a: u8) -> Self {
let mut c = Self::new(TransferFunction::Srgb, to_f32(r), to_f32(g), to_f32(b));
let mut c = Self::new(TransferFunction::Gamma22, to_f32(r), to_f32(g), to_f32(b));
if a < 255 {
c = c * to_f32(a);
}
@ -216,7 +197,7 @@ impl Color {
}
pub fn to_srgba_premultiplied(self) -> [u8; 4] {
let [r, g, b, a] = self.to_array(TransferFunction::Srgb);
let [r, g, b, a] = self.to_array(TransferFunction::Gamma22);
[to_u8(r), to_u8(g), to_u8(b), to_u8(a)]
}
@ -226,13 +207,6 @@ impl Color {
pub fn to_array2(self, transfer_function: TransferFunction, alpha: Option<f32>) -> [f32; 4] {
let mut res = [self.r, self.g, self.b, self.a];
fn srgb(c: f32) -> f32 {
if c <= 0.0031308 {
c * 12.92
} else {
1.055 * c.powf(1.0 / 2.4) - 0.055
}
}
fn linear(c: f32) -> f32 {
c
}
@ -242,15 +216,6 @@ impl Color {
let den = 1.0 + 18.6875 * c.powf(0.1593017578125);
(num / den).powf(78.84375)
}
fn ext_srgb(c: f32) -> f32 {
if c < -0.04045 {
-((c - 0.055) / -1.055).powf(2.4)
} else if c < 0.04045 {
c / 12.92
} else {
((c + 0.055) / 1.055).powf(2.4)
}
}
fn st240(c: f32) -> f32 {
if c < 0.0228 {
4.0 * c
@ -296,14 +261,12 @@ impl Color {
}
}
match transfer_function {
TransferFunction::Srgb => convert!(srgb),
TransferFunction::Linear => convert!(linear),
TransferFunction::St2084Pq => convert!(st2084_pq),
TransferFunction::Bt1886 => convert!(gamma24),
TransferFunction::Gamma22 => convert!(gamma22),
TransferFunction::Gamma28 => convert!(gamma28),
TransferFunction::St240 => convert!(st240),
TransferFunction::ExtSrgb => convert!(ext_srgb),
TransferFunction::Log100 => convert!(log100),
TransferFunction::Log316 => convert!(log316),
TransferFunction::St428 => convert!(st428),
@ -335,7 +298,7 @@ impl Color {
impl From<jay_config::theme::Color> for Color {
fn from(f: jay_config::theme::Color) -> Self {
let [r, g, b, a] = f.to_f32_premultiplied();
Self::new_premultiplied(TransferFunction::Srgb, r, g, b, a)
Self::new_premultiplied(TransferFunction::Gamma22, r, g, b, a)
}
}