@@ -17,67 +17,106 @@ internal partial class LutABCalculator : IVector4Calculator
1717 private MatrixCalculator matrixCalculator ;
1818 private ClutCalculator clutCalculator ;
1919
20+ /// <summary>
21+ /// Initializes a new instance of the <see cref="LutABCalculator"/> class for an ICC <c>mAB</c> transform.
22+ /// </summary>
23+ /// <param name="entry">The parsed A-to-B LUT entry.</param>
2024 public LutABCalculator ( IccLutAToBTagDataEntry entry )
2125 {
2226 Guard . NotNull ( entry , nameof ( entry ) ) ;
2327 this . Init ( entry . CurveA , entry . CurveB , entry . CurveM , entry . Matrix3x1 , entry . Matrix3x3 , entry . ClutValues ) ;
24- this . type | = CalculationType . AtoB ;
28+ this . type = CalculationType . AtoB ;
2529 }
2630
31+ /// <summary>
32+ /// Initializes a new instance of the <see cref="LutABCalculator"/> class for an ICC <c>mBA</c> transform.
33+ /// </summary>
34+ /// <param name="entry">The parsed B-to-A LUT entry.</param>
2735 public LutABCalculator ( IccLutBToATagDataEntry entry )
2836 {
2937 Guard . NotNull ( entry , nameof ( entry ) ) ;
3038 this . Init ( entry . CurveA , entry . CurveB , entry . CurveM , entry . Matrix3x1 , entry . Matrix3x3 , entry . ClutValues ) ;
31- this . type | = CalculationType . BtoA ;
39+ this . type = CalculationType . BtoA ;
3240 }
3341
42+ /// <summary>
43+ /// Calculates the transformed value by applying the configured ICC LUT stages in specification order.
44+ /// </summary>
45+ /// <param name="value">The input value.</param>
46+ /// <returns>The transformed value.</returns>
3447 public Vector4 Calculate ( Vector4 value )
3548 {
3649 switch ( this . type )
3750 {
38- case CalculationType . Full | CalculationType . AtoB :
39- value = this . curveACalculator . Calculate ( value ) ;
40- value = this . clutCalculator . Calculate ( value ) ;
41- value = this . curveMCalculator . Calculate ( value ) ;
42- value = this . matrixCalculator . Calculate ( value ) ;
43- return this . curveBCalculator . Calculate ( value ) ;
44-
45- case CalculationType . Full | CalculationType . BtoA :
46- value = this . curveBCalculator . Calculate ( value ) ;
47- value = this . matrixCalculator . Calculate ( value ) ;
48- value = this . curveMCalculator . Calculate ( value ) ;
49- value = this . clutCalculator . Calculate ( value ) ;
50- return this . curveACalculator . Calculate ( value ) ;
51-
52- case CalculationType . CurveClut | CalculationType . AtoB :
53- value = this . curveACalculator . Calculate ( value ) ;
54- value = this . clutCalculator . Calculate ( value ) ;
55- return this . curveBCalculator . Calculate ( value ) ;
56-
57- case CalculationType . CurveClut | CalculationType . BtoA :
58- value = this . curveBCalculator . Calculate ( value ) ;
59- value = this . clutCalculator . Calculate ( value ) ;
60- return this . curveACalculator . Calculate ( value ) ;
61-
62- case CalculationType . CurveMatrix | CalculationType . AtoB :
63- value = this . curveMCalculator . Calculate ( value ) ;
64- value = this . matrixCalculator . Calculate ( value ) ;
65- return this . curveBCalculator . Calculate ( value ) ;
66-
67- case CalculationType . CurveMatrix | CalculationType . BtoA :
68- value = this . curveBCalculator . Calculate ( value ) ;
69- value = this . matrixCalculator . Calculate ( value ) ;
70- return this . curveMCalculator . Calculate ( value ) ;
71-
72- case CalculationType . SingleCurve | CalculationType . AtoB :
73- case CalculationType . SingleCurve | CalculationType . BtoA :
74- return this . curveBCalculator . Calculate ( value ) ;
51+ case CalculationType . AtoB :
52+ // ICC mAB order: A, CLUT, M, Matrix, B.
53+ if ( this . curveACalculator != null )
54+ {
55+ value = this . curveACalculator . Calculate ( value ) ;
56+ }
57+
58+ if ( this . clutCalculator != null )
59+ {
60+ value = this . clutCalculator . Calculate ( value ) ;
61+ }
62+
63+ if ( this . curveMCalculator != null )
64+ {
65+ value = this . curveMCalculator . Calculate ( value ) ;
66+ }
67+
68+ if ( this . matrixCalculator != null )
69+ {
70+ value = this . matrixCalculator . Calculate ( value ) ;
71+ }
72+
73+ if ( this . curveBCalculator != null )
74+ {
75+ value = this . curveBCalculator . Calculate ( value ) ;
76+ }
77+
78+ return value ;
79+
80+ case CalculationType . BtoA :
81+ // ICC mBA order: B, Matrix, M, CLUT, A.
82+ if ( this . curveBCalculator != null )
83+ {
84+ value = this . curveBCalculator . Calculate ( value ) ;
85+ }
86+
87+ if ( this . matrixCalculator != null )
88+ {
89+ value = this . matrixCalculator . Calculate ( value ) ;
90+ }
91+
92+ if ( this . curveMCalculator != null )
93+ {
94+ value = this . curveMCalculator . Calculate ( value ) ;
95+ }
96+
97+ if ( this . clutCalculator != null )
98+ {
99+ value = this . clutCalculator . Calculate ( value ) ;
100+ }
101+
102+ if ( this . curveACalculator != null )
103+ {
104+ value = this . curveACalculator . Calculate ( value ) ;
105+ }
106+
107+ return value ;
75108
76109 default :
77110 throw new InvalidOperationException ( "Invalid calculation type" ) ;
78111 }
79112 }
80113
114+ /// <summary>
115+ /// Creates calculators for the processing stages present in the LUT entry.
116+ /// </summary>
117+ /// <remarks>
118+ /// The tag entry classes already validate channel continuity, so this method only materializes the available stages.
119+ /// </remarks>
81120 private void Init ( IccTagDataEntry [ ] curveA , IccTagDataEntry [ ] curveB , IccTagDataEntry [ ] curveM , Vector3 ? matrix3x1 , Matrix4x4 ? matrix3x3 , IccClut clut )
82121 {
83122 bool hasACurve = curveA != null ;
@@ -86,26 +125,10 @@ private void Init(IccTagDataEntry[] curveA, IccTagDataEntry[] curveB, IccTagData
86125 bool hasMatrix = matrix3x1 != null && matrix3x3 != null ;
87126 bool hasClut = clut != null ;
88127
89- if ( hasBCurve && hasMatrix && hasMCurve && hasClut && hasACurve )
90- {
91- this . type = CalculationType . Full ;
92- }
93- else if ( hasBCurve && hasClut && hasACurve )
94- {
95- this . type = CalculationType . CurveClut ;
96- }
97- else if ( hasBCurve && hasMatrix && hasMCurve )
98- {
99- this . type = CalculationType . CurveMatrix ;
100- }
101- else if ( hasBCurve )
102- {
103- this . type = CalculationType . SingleCurve ;
104- }
105- else
106- {
107- throw new InvalidIccProfileException ( "AToB or BToA tag has an invalid configuration" ) ;
108- }
128+ Guard . IsTrue (
129+ hasACurve || hasBCurve || hasMCurve || hasMatrix || hasClut ,
130+ "entry" ,
131+ "AToB or BToA tag must contain at least one processing element" ) ;
109132
110133 if ( hasACurve )
111134 {
0 commit comments