moxcms/conversions/katana/
pcs_stages.rs1use crate::conversions::katana::KatanaIntermediateStage;
30use crate::conversions::katana::stages::BlackholeIntermediateStage;
31use crate::mlaf::mlaf;
32use crate::{CmsError, ColorProfile, DataColorSpace, Matrix3f, ProfileVersion};
33use std::marker::PhantomData;
34
35pub(crate) struct KatanaMatrixStage {
36 pub(crate) matrices: Vec<Matrix3f>,
37}
38
39impl KatanaMatrixStage {
40 pub(crate) fn new(matrix: Matrix3f) -> Self {
41 Self {
42 matrices: vec![matrix],
43 }
44 }
45}
46
47pub(crate) type KatanaDefaultIntermediate = dyn KatanaIntermediateStage<f32> + Send + Sync;
48
49impl KatanaIntermediateStage<f32> for KatanaMatrixStage {
50 fn stage(&self, input: &mut Vec<f32>) -> Result<Vec<f32>, CmsError> {
51 if input.len() % 3 != 0 {
52 return Err(CmsError::LaneMultipleOfChannels);
53 }
54
55 for m in self.matrices.iter() {
56 for dst in input.chunks_exact_mut(3) {
57 let x = dst[0];
58 let y = dst[1];
59 let z = dst[2];
60 dst[0] = mlaf(mlaf(x * m.v[0][0], y, m.v[0][1]), z, m.v[0][2]);
61 dst[1] = mlaf(mlaf(x * m.v[1][0], y, m.v[1][1]), z, m.v[1][2]);
62 dst[2] = mlaf(mlaf(x * m.v[2][0], y, m.v[2][1]), z, m.v[2][2]);
63 }
64 }
65
66 Ok(std::mem::take(input))
67 }
68}
69
70pub(crate) fn katana_pcs_lab_v4_to_v2(profile: &ColorProfile) -> Box<KatanaDefaultIntermediate> {
71 if profile.pcs == DataColorSpace::Lab && profile.version_internal <= ProfileVersion::V4_0 {
72 let v_mat = vec![Matrix3f {
73 v: [
74 [65280.0 / 65535.0, 0., 0.],
75 [0., 65280.0 / 65535.0, 0.],
76 [0., 0., 65280.0 / 65535.0],
77 ],
78 }];
79 return Box::new(KatanaMatrixStage { matrices: v_mat });
80 }
81 Box::new(BlackholeIntermediateStage {
82 _phantom: PhantomData,
83 })
84}
85
86pub(crate) fn katana_pcs_lab_v2_to_v4(profile: &ColorProfile) -> Box<KatanaDefaultIntermediate> {
87 if profile.pcs == DataColorSpace::Lab && profile.version_internal <= ProfileVersion::V4_0 {
88 let v_mat = vec![Matrix3f {
89 v: [
90 [65535.0 / 65280.0, 0., 0.],
91 [0., 65535.0 / 65280.0, 0.],
92 [0., 0., 65535.0 / 65280.0],
93 ],
94 }];
95 return Box::new(KatanaMatrixStage { matrices: v_mat });
96 }
97 Box::new(BlackholeIntermediateStage {
98 _phantom: PhantomData,
99 })
100}