From e98ff078aae8171b6500324fb655013d850acc07 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Mon, 26 Apr 2021 12:48:32 +0000 Subject: [PATCH] Bug 1555331. Add a Param struct. r=aosmond This makes our parsing of parametric transfer functions more clear because you can see exactly what output variables the input variables map to. Differential Revision: https://phabricator.services.mozilla.com/D113224 --- gfx/qcms/src/transform_util.rs | 93 +++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 14 deletions(-) diff --git a/gfx/qcms/src/transform_util.rs b/gfx/qcms/src/transform_util.rs index 17538609a011..cf3a9cd68a64 100644 --- a/gfx/qcms/src/transform_util.rs +++ b/gfx/qcms/src/transform_util.rs @@ -140,23 +140,11 @@ fn compute_curve_gamma_table_type2(table: &[u16]) -> Box<[f32; 256]> { gamma_table.into_boxed_slice().try_into().unwrap() } fn compute_curve_gamma_table_type_parametric(params: &[f32]) -> Box<[f32; 256]> { - let g: f32 = params[0]; - let (a, b, c, d, e, f) = match ¶ms[1..] { - [] => (1., 0., 0., -1., 0., 0.), - [a, b] => (*a, *b, 0., -b / a, 0., 0.), - [a, b, c] => (*a, *b, 0., -b / a, *c, *c), - [a, b, c, d] => (*a, *b, *c, *d, 0., 0.), - [a, b, c, d, e, f] => (*a, *b, *c, *d, *e, *f), - _ => panic!(), - }; + let params = Param::new(params); let mut gamma_table = Vec::with_capacity(256); for i in 0..256 { let X = i as f32 / 255.; - gamma_table.push(clamp_float(if X >= d { - (a * X + b).powf(g) + e - } else { - c * X + f - })) + gamma_table.push(clamp_float(params.eval(X))); } gamma_table.into_boxed_slice().try_into().unwrap() } @@ -199,6 +187,83 @@ pub fn build_colorant_matrix(p: &Profile) -> Matrix { result.invalid = false; result } + +/** Parametric representation of transfer function */ +#[derive(Debug)] +struct Param { + g: f32, + a: f32, + b: f32, + c: f32, + d: f32, + e: f32, + f: f32, +} + +impl Param { + fn new(params: &[f32]) -> Param { + // convert from the variable number of parameters + // contained in profiles to a unified representation. + let g: f32 = params[0]; + match params[1..] { + [] => Param { + g, + a: 1., + b: 0., + c: 0., + d: -1., + e: 0., + f: 0., + }, + [a, b] => Param { + g, + a, + b, + c: 0., + d: -b / a, + e: 0., + f: 0., + }, + [a, b, c] => Param { + g, + a, + b, + c: 0., + d: -b / a, + e: c, + f: c, + }, + [a, b, c, d] => Param { + g, + a, + b, + c, + d, + e: 0., + f: 0., + }, + [a, b, c, d, e, f] => Param { + g, + a, + b, + c, + d, + e, + f, + }, + _ => panic!(), + } + } + + fn eval(&self, x: f32) -> f32 { + if x < self.d { + self.c * x + self.f + } else { + (self.a * x + self.b).powf(self.g) + self.e + } + } +} + /* The following code is copied nearly directly from lcms. * I think it could be much better. For example, Argyll seems to have better code in * icmTable_lookup_bwd and icmTable_setup_bwd. However, for now this is a quick way