diff options
Diffstat (limited to 'gfx/qcms/src/transform.rs')
-rw-r--r-- | gfx/qcms/src/transform.rs | 179 |
1 files changed, 83 insertions, 96 deletions
diff --git a/gfx/qcms/src/transform.rs b/gfx/qcms/src/transform.rs index b0c8b60b18..54f89864eb 100644 --- a/gfx/qcms/src/transform.rs +++ b/gfx/qcms/src/transform.rs @@ -73,13 +73,17 @@ pub struct PrecacheOuput { * improve startup performance and reduce memory usage. ColorSync on * 10.5 uses 4097 which is perhaps because they use a fixed point * representation where 1. is represented by 0x1000. */ - pub data: [u8; PRECACHE_OUTPUT_SIZE], + pub lut_r: [u8; PRECACHE_OUTPUT_SIZE], + pub lut_g: [u8; PRECACHE_OUTPUT_SIZE], + pub lut_b: [u8; PRECACHE_OUTPUT_SIZE], } impl Default for PrecacheOuput { fn default() -> PrecacheOuput { PrecacheOuput { - data: [0; PRECACHE_OUTPUT_SIZE], + lut_r: [0; PRECACHE_OUTPUT_SIZE], + lut_g: [0; PRECACHE_OUTPUT_SIZE], + lut_b: [0; PRECACHE_OUTPUT_SIZE], } } } @@ -113,9 +117,7 @@ pub struct qcms_transform { pub output_gamma_lut_g_length: usize, pub output_gamma_lut_b_length: usize, pub output_gamma_lut_gray_length: usize, - pub output_table_r: Option<Arc<PrecacheOuput>>, - pub output_table_g: Option<Arc<PrecacheOuput>>, - pub output_table_b: Option<Arc<PrecacheOuput>>, + pub precache_output: Option<Arc<PrecacheOuput>>, pub transform_fn: transform_fn_t, } @@ -414,15 +416,15 @@ unsafe extern "C" fn qcms_transform_data_gray_template_lut<I: GrayFormat, F: For let out_device_r: f32 = lut_interp_linear( linear as f64, - &(*transform).output_gamma_lut_r.as_ref().unwrap(), + &transform.output_gamma_lut_r.as_ref().unwrap(), ); let out_device_g: f32 = lut_interp_linear( linear as f64, - &(*transform).output_gamma_lut_g.as_ref().unwrap(), + &transform.output_gamma_lut_g.as_ref().unwrap(), ); let out_device_b: f32 = lut_interp_linear( linear as f64, - &(*transform).output_gamma_lut_b.as_ref().unwrap(), + &transform.output_gamma_lut_b.as_ref().unwrap(), ); *dest.add(F::kRIndex) = clamp_u8(out_device_r * 255f32); *dest.add(F::kGIndex) = clamp_u8(out_device_g * 255f32); @@ -475,17 +477,18 @@ unsafe fn qcms_transform_data_graya_bgra_out_lut( qcms_transform_data_gray_template_lut::<GrayAlpha, BGRA>(transform, src, dest, length); } unsafe fn qcms_transform_data_gray_template_precache<I: GrayFormat, F: Format>( - transform: *const qcms_transform, + transform: &qcms_transform, mut src: *const u8, mut dest: *mut u8, length: usize, ) { let components: u32 = if F::kAIndex == 0xff { 3 } else { 4 } as u32; - let output_table_r = ((*transform).output_table_r).as_deref().unwrap(); - let output_table_g = ((*transform).output_table_g).as_deref().unwrap(); - let output_table_b = ((*transform).output_table_b).as_deref().unwrap(); + let precache_output = transform.precache_output.as_deref().unwrap(); + let output_r = &precache_output.lut_r; + let output_g = &precache_output.lut_g; + let output_b = &precache_output.lut_b; - let input_gamma_table_gray = (*transform) + let input_gamma_table_gray = transform .input_gamma_table_gray .as_ref() .unwrap() @@ -506,9 +509,9 @@ unsafe fn qcms_transform_data_gray_template_precache<I: GrayFormat, F: Format>( let linear: f32 = *input_gamma_table_gray.offset(device as isize); /* we could round here... */ let gray: u16 = (linear * PRECACHE_OUTPUT_MAX as f32) as u16; - *dest.add(F::kRIndex) = (output_table_r).data[gray as usize]; - *dest.add(F::kGIndex) = (output_table_g).data[gray as usize]; - *dest.add(F::kBIndex) = (output_table_b).data[gray as usize]; + *dest.add(F::kRIndex) = output_r[gray as usize]; + *dest.add(F::kGIndex) = output_g[gray as usize]; + *dest.add(F::kBIndex) = output_b[gray as usize]; if F::kAIndex != 0xff { *dest.add(F::kAIndex) = alpha } @@ -563,12 +566,12 @@ unsafe fn qcms_transform_data_template_lut_precache<F: Format>( length: usize, ) { let components: u32 = if F::kAIndex == 0xff { 3 } else { 4 } as u32; - let output_table_r = ((*transform).output_table_r).as_deref().unwrap(); - let output_table_g = ((*transform).output_table_g).as_deref().unwrap(); - let output_table_b = ((*transform).output_table_b).as_deref().unwrap(); - let input_gamma_table_r = (*transform).input_gamma_table_r.as_ref().unwrap().as_ptr(); - let input_gamma_table_g = (*transform).input_gamma_table_g.as_ref().unwrap().as_ptr(); - let input_gamma_table_b = (*transform).input_gamma_table_b.as_ref().unwrap().as_ptr(); + let output_table_r = &transform.precache_output.as_deref().unwrap().lut_r; + let output_table_g = &transform.precache_output.as_deref().unwrap().lut_g; + let output_table_b = &transform.precache_output.as_deref().unwrap().lut_b; + let input_gamma_table_r = transform.input_gamma_table_r.as_ref().unwrap().as_ptr(); + let input_gamma_table_g = transform.input_gamma_table_g.as_ref().unwrap().as_ptr(); + let input_gamma_table_b = transform.input_gamma_table_b.as_ref().unwrap().as_ptr(); let mat = &transform.matrix; let mut i: u32 = 0; @@ -596,9 +599,9 @@ unsafe fn qcms_transform_data_template_lut_precache<F: Format>( let r: u16 = (out_linear_r * PRECACHE_OUTPUT_MAX as f32) as u16; let g: u16 = (out_linear_g * PRECACHE_OUTPUT_MAX as f32) as u16; let b: u16 = (out_linear_b * PRECACHE_OUTPUT_MAX as f32) as u16; - *dest.add(F::kRIndex) = (output_table_r).data[r as usize]; - *dest.add(F::kGIndex) = (output_table_g).data[g as usize]; - *dest.add(F::kBIndex) = (output_table_b).data[b as usize]; + *dest.add(F::kRIndex) = output_table_r[r as usize]; + *dest.add(F::kGIndex) = output_table_g[g as usize]; + *dest.add(F::kBIndex) = output_table_b[b as usize]; if F::kAIndex != 0xff { *dest.add(F::kAIndex) = alpha } @@ -695,7 +698,7 @@ fn int_div_ceil(value: i32, div: i32) -> i32 { } // Using lcms' tetra interpolation algorithm. unsafe extern "C" fn qcms_transform_data_tetra_clut_template<F: Format>( - transform: *const qcms_transform, + transform: &qcms_transform, mut src: *const u8, mut dest: *mut u8, length: usize, @@ -703,9 +706,9 @@ unsafe extern "C" fn qcms_transform_data_tetra_clut_template<F: Format>( let components: u32 = if F::kAIndex == 0xff { 3 } else { 4 } as u32; let xy_len: i32 = 1; - let x_len: i32 = (*transform).grid_size as i32; + let x_len: i32 = transform.grid_size as i32; let len: i32 = x_len * x_len; - let table = (*transform).clut.as_ref().unwrap().as_ptr(); + let table = transform.clut.as_ref().unwrap().as_ptr(); let r_table: *const f32 = table; let g_table: *const f32 = table.offset(1); let b_table: *const f32 = table.offset(2); @@ -735,15 +738,15 @@ unsafe extern "C" fn qcms_transform_data_tetra_clut_template<F: Format>( let linear_r: f32 = in_r as i32 as f32 / 255.0; let linear_g: f32 = in_g as i32 as f32 / 255.0; let linear_b: f32 = in_b as i32 as f32 / 255.0; - let x: i32 = in_r as i32 * ((*transform).grid_size as i32 - 1) / 255; - let y: i32 = in_g as i32 * ((*transform).grid_size as i32 - 1) / 255; - let z: i32 = in_b as i32 * ((*transform).grid_size as i32 - 1) / 255; - let x_n: i32 = int_div_ceil(in_r as i32 * ((*transform).grid_size as i32 - 1), 255); - let y_n: i32 = int_div_ceil(in_g as i32 * ((*transform).grid_size as i32 - 1), 255); - let z_n: i32 = int_div_ceil(in_b as i32 * ((*transform).grid_size as i32 - 1), 255); - let rx: f32 = linear_r * ((*transform).grid_size as i32 - 1) as f32 - x as f32; - let ry: f32 = linear_g * ((*transform).grid_size as i32 - 1) as f32 - y as f32; - let rz: f32 = linear_b * ((*transform).grid_size as i32 - 1) as f32 - z as f32; + let x: i32 = in_r as i32 * (transform.grid_size as i32 - 1) / 255; + let y: i32 = in_g as i32 * (transform.grid_size as i32 - 1) / 255; + let z: i32 = in_b as i32 * (transform.grid_size as i32 - 1) / 255; + let x_n: i32 = int_div_ceil(in_r as i32 * (transform.grid_size as i32 - 1), 255); + let y_n: i32 = int_div_ceil(in_g as i32 * (transform.grid_size as i32 - 1), 255); + let z_n: i32 = int_div_ceil(in_b as i32 * (transform.grid_size as i32 - 1), 255); + let rx: f32 = linear_r * (transform.grid_size as i32 - 1) as f32 - x as f32; + let ry: f32 = linear_g * (transform.grid_size as i32 - 1) as f32 - y as f32; + let rz: f32 = linear_b * (transform.grid_size as i32 - 1) as f32 - z as f32; let CLU = |table: *const f32, x, y, z| { *table.offset(((x * len + y * x_len + z * xy_len) * 3) as isize) }; @@ -848,17 +851,17 @@ unsafe fn tetra( let linear_g: f32 = in_g as i32 as f32 / 255.0; let linear_b: f32 = in_b as i32 as f32 / 255.0; let xy_len: i32 = 1; - let x_len: i32 = (*transform).grid_size as i32; + let x_len: i32 = transform.grid_size as i32; let len: i32 = x_len * x_len; - let x: i32 = in_r as i32 * ((*transform).grid_size as i32 - 1) / 255; - let y: i32 = in_g as i32 * ((*transform).grid_size as i32 - 1) / 255; - let z: i32 = in_b as i32 * ((*transform).grid_size as i32 - 1) / 255; - let x_n: i32 = int_div_ceil(in_r as i32 * ((*transform).grid_size as i32 - 1), 255); - let y_n: i32 = int_div_ceil(in_g as i32 * ((*transform).grid_size as i32 - 1), 255); - let z_n: i32 = int_div_ceil(in_b as i32 * ((*transform).grid_size as i32 - 1), 255); - let rx: f32 = linear_r * ((*transform).grid_size as i32 - 1) as f32 - x as f32; - let ry: f32 = linear_g * ((*transform).grid_size as i32 - 1) as f32 - y as f32; - let rz: f32 = linear_b * ((*transform).grid_size as i32 - 1) as f32 - z as f32; + let x: i32 = in_r as i32 * (transform.grid_size as i32 - 1) / 255; + let y: i32 = in_g as i32 * (transform.grid_size as i32 - 1) / 255; + let z: i32 = in_b as i32 * (transform.grid_size as i32 - 1) / 255; + let x_n: i32 = int_div_ceil(in_r as i32 * (transform.grid_size as i32 - 1), 255); + let y_n: i32 = int_div_ceil(in_g as i32 * (transform.grid_size as i32 - 1), 255); + let z_n: i32 = int_div_ceil(in_b as i32 * (transform.grid_size as i32 - 1), 255); + let rx: f32 = linear_r * (transform.grid_size as i32 - 1) as f32 - x as f32; + let ry: f32 = linear_g * (transform.grid_size as i32 - 1) as f32 - y as f32; + let rz: f32 = linear_b * (transform.grid_size as i32 - 1) as f32 - z as f32; let CLU = |table: *const f32, x, y, z| { *table.offset(((x * len + y * x_len + z * xy_len) * 3) as isize) }; @@ -966,9 +969,9 @@ unsafe fn qcms_transform_data_tetra_clut_cmyk( mut dest: *mut u8, length: usize, ) { - let table = (*transform).clut.as_ref().unwrap().as_ptr(); + let table = transform.clut.as_ref().unwrap().as_ptr(); assert!( - (*transform).clut.as_ref().unwrap().len() + transform.clut.as_ref().unwrap().len() >= ((transform.grid_size as i32).pow(4) * 3) as usize ); for _ in 0..length { @@ -978,10 +981,10 @@ unsafe fn qcms_transform_data_tetra_clut_cmyk( let k: u8 = *src.add(3); src = src.offset(4); let linear_k: f32 = k as i32 as f32 / 255.0; - let grid_size = (*transform).grid_size as i32; - let w: i32 = k as i32 * ((*transform).grid_size as i32 - 1) / 255; - let w_n: i32 = int_div_ceil(k as i32 * ((*transform).grid_size as i32 - 1), 255); - let t: f32 = linear_k * ((*transform).grid_size as i32 - 1) as f32 - w as f32; + let grid_size = transform.grid_size as i32; + let w: i32 = k as i32 * (transform.grid_size as i32 - 1) / 255; + let w_n: i32 = int_div_ceil(k as i32 * (transform.grid_size as i32 - 1), 255); + let t: f32 = linear_k * (transform.grid_size as i32 - 1) as f32 - w as f32; let table1 = table.offset((w * grid_size * grid_size * grid_size * 3) as isize); let table2 = table.offset((w_n * grid_size * grid_size * grid_size * 3) as isize); @@ -1032,9 +1035,9 @@ unsafe fn qcms_transform_data_template_lut<F: Format>( let mat = &transform.matrix; let mut i: u32 = 0; - let input_gamma_table_r = (*transform).input_gamma_table_r.as_ref().unwrap().as_ptr(); - let input_gamma_table_g = (*transform).input_gamma_table_g.as_ref().unwrap().as_ptr(); - let input_gamma_table_b = (*transform).input_gamma_table_b.as_ref().unwrap().as_ptr(); + let input_gamma_table_r = transform.input_gamma_table_r.as_ref().unwrap().as_ptr(); + let input_gamma_table_g = transform.input_gamma_table_g.as_ref().unwrap().as_ptr(); + let input_gamma_table_b = transform.input_gamma_table_b.as_ref().unwrap().as_ptr(); while (i as usize) < length { let device_r: u8 = *src.add(F::kRIndex); let device_g: u8 = *src.add(F::kGIndex); @@ -1057,15 +1060,15 @@ unsafe fn qcms_transform_data_template_lut<F: Format>( let out_device_r: f32 = lut_interp_linear( out_linear_r as f64, - &(*transform).output_gamma_lut_r.as_ref().unwrap(), + &transform.output_gamma_lut_r.as_ref().unwrap(), ); let out_device_g: f32 = lut_interp_linear( out_linear_g as f64, - (*transform).output_gamma_lut_g.as_ref().unwrap(), + transform.output_gamma_lut_g.as_ref().unwrap(), ); let out_device_b: f32 = lut_interp_linear( out_linear_b as f64, - (*transform).output_gamma_lut_b.as_ref().unwrap(), + transform.output_gamma_lut_b.as_ref().unwrap(), ); *dest.add(F::kRIndex) = clamp_u8(out_device_r * 255f32); *dest.add(F::kGIndex) = clamp_u8(out_device_g * 255f32); @@ -1172,33 +1175,22 @@ pub extern "C" fn qcms_profile_precache_output_transform(profile: &mut Profile) if profile.redTRC.is_none() || profile.greenTRC.is_none() || profile.blueTRC.is_none() { return; } - if profile.output_table_r.is_none() { - let mut output_table_r = precache_create(); - if compute_precache( + if profile.precache_output.is_none() { + let mut precache = precache_create(); + compute_precache( profile.redTRC.as_deref().unwrap(), - &mut Arc::get_mut(&mut output_table_r).unwrap().data, - ) { - profile.output_table_r = Some(output_table_r); - } - } - if profile.output_table_g.is_none() { - let mut output_table_g = precache_create(); - if compute_precache( + &mut Arc::get_mut(&mut precache).unwrap().lut_r, + ); + compute_precache( profile.greenTRC.as_deref().unwrap(), - &mut Arc::get_mut(&mut output_table_g).unwrap().data, - ) { - profile.output_table_g = Some(output_table_g); - } - } - if profile.output_table_b.is_none() { - let mut output_table_b = precache_create(); - if compute_precache( + &mut Arc::get_mut(&mut precache).unwrap().lut_g, + ); + compute_precache( profile.blueTRC.as_deref().unwrap(), - &mut Arc::get_mut(&mut output_table_b).unwrap().data, - ) { - profile.output_table_b = Some(output_table_b); - } - }; + &mut Arc::get_mut(&mut precache).unwrap().lut_b, + ); + profile.precache_output = Some(precache); + } } /* Replace the current transformation with a LUT transformation using a given number of sample points */ fn transform_precacheLUT_float( @@ -1225,16 +1217,16 @@ fn transform_precacheLUT_float( } let lut = chain_transform(input, output, src, dest, lutSize as usize); if let Some(lut) = lut { - (*transform).clut = Some(lut); - (*transform).grid_size = samples as u16; + transform.clut = Some(lut); + transform.grid_size = samples as u16; if in_type == RGBA8 { - (*transform).transform_fn = Some(qcms_transform_data_tetra_clut_rgba) + transform.transform_fn = Some(qcms_transform_data_tetra_clut_rgba) } else if in_type == BGRA8 { - (*transform).transform_fn = Some(qcms_transform_data_tetra_clut_bgra) + transform.transform_fn = Some(qcms_transform_data_tetra_clut_bgra) } else if in_type == RGB8 { - (*transform).transform_fn = Some(qcms_transform_data_tetra_clut_rgb) + transform.transform_fn = Some(qcms_transform_data_tetra_clut_rgb) } - debug_assert!((*transform).transform_fn.is_some()); + debug_assert!(transform.transform_fn.is_some()); } else { return None; } @@ -1303,10 +1295,7 @@ pub fn transform_create( } let mut transform: Box<qcms_transform> = Box::new(Default::default()); let mut precache: bool = false; - if output.output_table_r.is_some() - && output.output_table_g.is_some() - && output.output_table_b.is_some() - { + if output.precache_output.is_some() { precache = true } // This precache assumes RGB_SIGNATURE (fails on GRAY_SIGNATURE, for instance) @@ -1330,9 +1319,7 @@ pub fn transform_create( return result; } if precache { - transform.output_table_r = Some(Arc::clone(output.output_table_r.as_ref().unwrap())); - transform.output_table_g = Some(Arc::clone(output.output_table_g.as_ref().unwrap())); - transform.output_table_b = Some(Arc::clone(output.output_table_b.as_ref().unwrap())); + transform.precache_output = Some(Arc::clone(output.precache_output.as_ref().unwrap())); } else { if output.redTRC.is_none() || output.greenTRC.is_none() || output.blueTRC.is_none() { return None; |