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) => { DamageTrackingCmd::SetColor(c) => {
let color = parse_color(&c.color); 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 { tc.send(SetVisualizerColor {
self_id: dt, self_id: dt,
r, r,

View file

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

View file

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

View file

@ -2365,7 +2365,7 @@ impl ConfigProxyHandler {
fn handle_get_color(&self, colorable: Colorable) -> Result<(), CphError> { fn handle_get_color(&self, colorable: Colorable) -> Result<(), CphError> {
let color = self.get_color(colorable)?.get(); 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); let color = jay_config::theme::Color::new_f32_premultiplied(r, g, b, a);
self.respond(Response::GetColor { color }); self.respond(Response::GetColor { color });
Ok(()) 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) { 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; let gles = ctx.ctx.dpy.gles;
unsafe { unsafe {
(gles.glUseProgram)(ctx.fill_prog.prog); (gles.glUseProgram)(ctx.fill_prog.prog);

View file

@ -82,7 +82,7 @@ impl Framebuffer {
(gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo); (gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo);
(gles.glViewport)(0, 0, self.gl.width, self.gl.height); (gles.glViewport)(0, 0, self.gl.width, self.gl.height);
if let Some(c) = clear { 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.glClearColor)(r, g, b, a);
(gles.glClear)(GL_COLOR_BUFFER_BIT); (gles.glClear)(GL_COLOR_BUFFER_BIT);
} }

View file

@ -3,60 +3,16 @@
#include "frag_spec_const.glsl" #include "frag_spec_const.glsl"
#define TF_SRGB 0
#define TF_LINEAR 1 #define TF_LINEAR 1
#define TF_ST2084_PQ 2 #define TF_ST2084_PQ 2
#define TF_GAMMA24 3 #define TF_GAMMA24 3
#define TF_GAMMA22 4 #define TF_GAMMA22 4
#define TF_GAMMA28 5 #define TF_GAMMA28 5
#define TF_ST240 6 #define TF_ST240 6
#define TF_EXT_SRGB 7
#define TF_LOG100 8 #define TF_LOG100 8
#define TF_LOG316 9 #define TF_LOG316 9
#define TF_ST428 10 #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) { vec3 eotf_st2084_pq(vec3 c) {
c = clamp(c, 0.0, 1.0); c = clamp(c, 0.0, 1.0);
vec3 cp = pow(c, vec3(1.0 / 78.84375)); vec3 cp = pow(c, vec3(1.0 / 78.84375));
@ -126,14 +82,12 @@ vec3 oetf_st428(vec3 c) {
vec3 apply_eotf(vec3 c) { vec3 apply_eotf(vec3 c) {
switch (eotf) { switch (eotf) {
case TF_SRGB: return eotf_srgb(c);
case TF_LINEAR: return c; case TF_LINEAR: return c;
case TF_ST2084_PQ: return eotf_st2084_pq(c); case TF_ST2084_PQ: return eotf_st2084_pq(c);
case TF_GAMMA24: return sign(c) * pow(abs(c), vec3(2.4)); 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_GAMMA22: return sign(c) * pow(abs(c), vec3(2.2));
case TF_GAMMA28: return sign(c) * pow(abs(c), vec3(2.8)); case TF_GAMMA28: return sign(c) * pow(abs(c), vec3(2.8));
case TF_ST240: return eotf_st240(c); 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_LOG100: return eotf_log100(c);
case TF_LOG316: return eotf_log316(c); case TF_LOG316: return eotf_log316(c);
case TF_ST428: return eotf_st428(c); case TF_ST428: return eotf_st428(c);
@ -143,14 +97,12 @@ vec3 apply_eotf(vec3 c) {
vec3 apply_oetf(vec3 c) { vec3 apply_oetf(vec3 c) {
switch (oetf) { switch (oetf) {
case TF_SRGB: return oetf_srgb(c);
case TF_LINEAR: return c; case TF_LINEAR: return c;
case TF_ST2084_PQ: return oetf_st2084_pq(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_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_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_GAMMA28: return sign(c) * pow(abs(c), vec3(1.0 / 2.8));
case TF_ST240: return oetf_st240(c); 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_LOG100: return oetf_log100(c);
case TF_LOG316: return oetf_log316(c); case TF_LOG316: return oetf_log316(c);
case TF_ST428: return oetf_st428(c); case TF_ST428: return oetf_st428(c);

View file

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

View file

@ -221,7 +221,7 @@ impl PathBuilderExt for PathBuilder {
impl From<crate::theme::Color> for Color { impl From<crate::theme::Color> for Color {
fn from(v: crate::theme::Color) -> Self { 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; let mut c = Self::TRANSPARENT;
c.set_red(r / a); c.set_red(r / a);
c.set_green(g / 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] { 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 { if alpha < 1.0 {
r /= alpha; r /= alpha;
g /= alpha; g /= alpha;

View file

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

View file

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

View file

@ -97,7 +97,7 @@ impl JayDamageTrackingRequestHandler for JayDamageTracking {
req: SetVisualizerColor, req: SetVisualizerColor,
_slf: &Rc<Self>, _slf: &Rc<Self>,
) -> Result<(), Self::Error> { ) -> 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); self.client.state.damage_visualizer.set_color(color);
Ok(()) Ok(())
} }

View file

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

View file

@ -32,7 +32,7 @@ impl TestSinglePixelBufferManager {
destroyed: Cell::new(false), destroyed: Cell::new(false),
}); });
let map = |c: f32| (c as f64 * u32::MAX as f64) as u32; 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.tran.send(CreateU32RgbaBuffer {
self_id: self.id, self_id: self.id,
id: obj.id, id: obj.id,

View file

@ -79,7 +79,7 @@ pub fn render(
let data = create_data(font, width, height, scale)?; let data = create_data(font, width, height, scale)?;
data.layout.set_text(text); data.layout.set_text(text);
let font_height = data.layout.pixel_size().1; 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_operator(CAIRO_OPERATOR_SOURCE);
data.cctx.set_source_rgba(r as _, g as _, b as _, a as _); data.cctx.set_source_rgba(r as _, g as _, b as _, a as _);
let y = y.unwrap_or((height - font_height) / 2); let y = y.unwrap_or((height - font_height) / 2);

View file

@ -188,7 +188,7 @@ fn render(
data.layout.set_text(text); data.layout.set_text(text);
} }
let font_height = data.layout.pixel_size().1; 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_operator(CAIRO_OPERATOR_SOURCE);
data.cctx.set_source_rgba(r as _, g as _, b as _, a as _); data.cctx.set_source_rgba(r as _, g as _, b as _, a as _);
let y = y.unwrap_or((height - font_height) / 2); 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 { 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)] #[inline(always)]
fn linear(c: f32) -> f32 { fn linear(c: f32) -> f32 {
c c
@ -86,16 +79,6 @@ impl Color {
let den = 18.8515625 - 18.6875 * cp; let den = 18.8515625 - 18.6875 * cp;
(num / den).powf(1.0 / 0.1593017578125) (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 { fn st240(c: f32) -> f32 {
if c < 0.0913 { if c < 0.0913 {
c / 4.0 c / 4.0
@ -129,14 +112,12 @@ impl Color {
}}; }};
} }
match transfer_function { match transfer_function {
TransferFunction::Srgb => convert!(srgb),
TransferFunction::Linear => convert!(linear), TransferFunction::Linear => convert!(linear),
TransferFunction::St2084Pq => convert!(st2084_pq), TransferFunction::St2084Pq => convert!(st2084_pq),
TransferFunction::Bt1886 => convert!(gamma24), TransferFunction::Bt1886 => convert!(gamma24),
TransferFunction::Gamma22 => convert!(gamma22), TransferFunction::Gamma22 => convert!(gamma22),
TransferFunction::Gamma28 => convert!(gamma28), TransferFunction::Gamma28 => convert!(gamma28),
TransferFunction::St240 => convert!(st240), TransferFunction::St240 => convert!(st240),
TransferFunction::ExtSrgb => convert!(ext_srgb),
TransferFunction::Log100 => convert!(log100), TransferFunction::Log100 => convert!(log100),
TransferFunction::Log316 => convert!(log316), TransferFunction::Log316 => convert!(log316),
TransferFunction::St428 => convert!(st428), TransferFunction::St428 => convert!(st428),
@ -175,12 +156,12 @@ impl Color {
} }
pub fn from_srgb(r: u8, g: u8, b: u8) -> Self { 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 { pub fn from_srgba_premultiplied(r: u8, g: u8, b: u8, a: u8) -> Self {
Self::new_premultiplied( Self::new_premultiplied(
TransferFunction::Srgb, TransferFunction::Gamma22,
to_f32(r), to_f32(r),
to_f32(g), to_f32(g),
to_f32(b), to_f32(b),
@ -208,7 +189,7 @@ impl Color {
} }
pub fn from_srgba_straight(r: u8, g: u8, b: u8, a: u8) -> Self { 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 { if a < 255 {
c = c * to_f32(a); c = c * to_f32(a);
} }
@ -216,7 +197,7 @@ impl Color {
} }
pub fn to_srgba_premultiplied(self) -> [u8; 4] { 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)] [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] { pub fn to_array2(self, transfer_function: TransferFunction, alpha: Option<f32>) -> [f32; 4] {
let mut res = [self.r, self.g, self.b, self.a]; 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 { fn linear(c: f32) -> f32 {
c c
} }
@ -242,15 +216,6 @@ impl Color {
let den = 1.0 + 18.6875 * c.powf(0.1593017578125); let den = 1.0 + 18.6875 * c.powf(0.1593017578125);
(num / den).powf(78.84375) (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 { fn st240(c: f32) -> f32 {
if c < 0.0228 { if c < 0.0228 {
4.0 * c 4.0 * c
@ -296,14 +261,12 @@ impl Color {
} }
} }
match transfer_function { match transfer_function {
TransferFunction::Srgb => convert!(srgb),
TransferFunction::Linear => convert!(linear), TransferFunction::Linear => convert!(linear),
TransferFunction::St2084Pq => convert!(st2084_pq), TransferFunction::St2084Pq => convert!(st2084_pq),
TransferFunction::Bt1886 => convert!(gamma24), TransferFunction::Bt1886 => convert!(gamma24),
TransferFunction::Gamma22 => convert!(gamma22), TransferFunction::Gamma22 => convert!(gamma22),
TransferFunction::Gamma28 => convert!(gamma28), TransferFunction::Gamma28 => convert!(gamma28),
TransferFunction::St240 => convert!(st240), TransferFunction::St240 => convert!(st240),
TransferFunction::ExtSrgb => convert!(ext_srgb),
TransferFunction::Log100 => convert!(log100), TransferFunction::Log100 => convert!(log100),
TransferFunction::Log316 => convert!(log316), TransferFunction::Log316 => convert!(log316),
TransferFunction::St428 => convert!(st428), TransferFunction::St428 => convert!(st428),
@ -335,7 +298,7 @@ impl Color {
impl From<jay_config::theme::Color> for Color { impl From<jay_config::theme::Color> for Color {
fn from(f: jay_config::theme::Color) -> Self { fn from(f: jay_config::theme::Color) -> Self {
let [r, g, b, a] = f.to_f32_premultiplied(); 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)
} }
} }