Skip to content

Commit c5cc792

Browse files
Optimize several transforms
1 parent f55b3e4 commit c5cc792

10 files changed

Lines changed: 48 additions & 65 deletions

File tree

src/ImageSharp/ColorProfiles/CieXyz.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,8 @@ public CieXyz(Vector3 vector)
8080
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8181
public static bool operator !=(CieXyz left, CieXyz right) => !left.Equals(right);
8282

83-
/// <summary>
84-
/// Returns a new <see cref="Vector3"/> representing this instance.
85-
/// </summary>
86-
/// <returns>The <see cref="Vector3"/>.</returns>
8783
[MethodImpl(MethodImplOptions.AggressiveInlining)]
88-
public Vector3 ToVector3() => new(this.X, this.Y, this.Z);
84+
internal Vector3 ToVector3() => new(this.X, this.Y, this.Z);
8985

9086
[MethodImpl(MethodImplOptions.AggressiveInlining)]
9187
internal Vector4 ToVector4()
@@ -203,5 +199,5 @@ public static void ToProfileConnectionSpace(ColorConversionOptions options, Read
203199
public bool Equals(CieXyz other)
204200
=> this.AsVector3Unsafe() == other.AsVector3Unsafe();
205201

206-
private Vector3 AsVector3Unsafe() => Unsafe.As<CieXyz, Vector3>(ref Unsafe.AsRef(in this));
202+
internal Vector3 AsVector3Unsafe() => Unsafe.As<CieXyz, Vector3>(ref Unsafe.AsRef(in this));
207203
}

src/ImageSharp/ColorProfiles/ColorConversionOptions.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,16 @@ namespace SixLabors.ImageSharp.ColorProfiles;
1414
public class ColorConversionOptions
1515
{
1616
private Matrix4x4 adaptationMatrix;
17+
private YCbCrMatrix yCbCrMatrix;
1718

1819
/// <summary>
1920
/// Initializes a new instance of the <see cref="ColorConversionOptions"/> class.
2021
/// </summary>
21-
public ColorConversionOptions() => this.AdaptationMatrix = KnownChromaticAdaptationMatrices.Bradford;
22+
public ColorConversionOptions()
23+
{
24+
this.AdaptationMatrix = KnownChromaticAdaptationMatrices.Bradford;
25+
this.YCbCrMatrix = KnownYCbCrMatrices.BT601;
26+
}
2227

2328
/// <summary>
2429
/// Gets the memory allocator.
@@ -48,7 +53,15 @@ public class ColorConversionOptions
4853
/// <summary>
4954
/// Gets the YCbCr matrix to used to perform conversions from/to RGB.
5055
/// </summary>
51-
public YCbCrMatrix YCbCrMatrix { get; init; } = KnownYCbCrMatrices.BT601;
56+
public YCbCrMatrix YCbCrMatrix
57+
{
58+
get => this.yCbCrMatrix;
59+
init
60+
{
61+
this.yCbCrMatrix = value;
62+
this.TransposedYCbCrMatrix = value.Transpose();
63+
}
64+
}
5265

5366
/// <summary>
5467
/// Gets the source ICC profile.
@@ -70,10 +83,12 @@ public Matrix4x4 AdaptationMatrix
7083
init
7184
{
7285
this.adaptationMatrix = value;
73-
Matrix4x4.Invert(value, out Matrix4x4 inverted);
86+
_ = Matrix4x4.Invert(value, out Matrix4x4 inverted);
7487
this.InverseAdaptationMatrix = inverted;
7588
}
7689
}
7790

91+
internal YCbCrMatrix TransposedYCbCrMatrix { get; private set; }
92+
7893
internal Matrix4x4 InverseAdaptationMatrix { get; private set; }
7994
}

src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsIcc.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ private static Vector4 GetTargetPcsWithPerceptualAdjustment(
363363
if (targetParams.HasNoPerceptualHandling ||
364364
(oneProfileHasV2PerceptualAdjustment && targetParams.HasV2PerceptualHandling))
365365
{
366-
Vector3 vector = AdjustPcsToV2BlackPoint(xyz.ToVector3());
366+
Vector3 vector = AdjustPcsToV2BlackPoint(xyz.AsVector3Unsafe());
367367

368368
// when using XYZ PCS, negative values are clipped after PCS adjustment (in DemoIccMAX)
369369
if (targetParams.PcsType == IccColorSpaceType.CieXyz)

src/ImageSharp/ColorProfiles/Icc/Calculators/ColorTrcCalculator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public Vector4 Calculate(Vector4 value)
5858
// when data to PCS, upstream process provides scaled XYZ
5959
// but input to calculator is descaled XYZ
6060
// (see DemoMaxICC IccCmm.cpp : CIccXformMatrixTRC::Apply)
61-
xyz = new(CieXyz.FromScaledVector4(xyz).ToVector3(), 1);
61+
xyz = new(CieXyz.FromScaledVector4(xyz).AsVector3Unsafe(), 1);
6262
return this.curveCalculator.Calculate(xyz);
6363
}
6464
}

src/ImageSharp/ColorProfiles/Lms.cs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,6 @@ public Lms(Vector3 vector)
8282
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8383
public static bool operator !=(Lms left, Lms right) => !left.Equals(right);
8484

85-
/// <summary>
86-
/// Returns a new <see cref="Vector3"/> representing this instance.
87-
/// </summary>
88-
/// <returns>The <see cref="Vector3"/>.</returns>
89-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
90-
public Vector3 ToVector3() => new(this.L, this.M, this.S);
91-
9285
/// <inheritdoc/>
9386
public Vector4 ToScaledVector4()
9487
{
@@ -134,10 +127,7 @@ public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<Lms> des
134127

135128
/// <inheritdoc/>
136129
public static Lms FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
137-
{
138-
Vector3 vector = Vector3.Transform(source.ToVector3(), options.AdaptationMatrix);
139-
return new Lms(vector);
140-
}
130+
=> new(Vector3.Transform(source.AsVector3Unsafe(), options.AdaptationMatrix));
141131

142132
/// <inheritdoc/>
143133
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<CieXyz> source, Span<Lms> destination)
@@ -153,10 +143,7 @@ public static void FromProfileConnectionSpace(ColorConversionOptions options, Re
153143

154144
/// <inheritdoc/>
155145
public CieXyz ToProfileConnectingSpace(ColorConversionOptions options)
156-
{
157-
Vector3 vector = Vector3.Transform(this.ToVector3(), options.InverseAdaptationMatrix);
158-
return new CieXyz(vector);
159-
}
146+
=> new(Vector3.Transform(this.AsVector3Unsafe(), options.InverseAdaptationMatrix));
160147

161148
/// <inheritdoc/>
162149
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Lms> source, Span<CieXyz> destination)

src/ImageSharp/ColorProfiles/Rgb.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<Rgb> des
128128
public static Rgb FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
129129
{
130130
// Convert to linear rgb then compress.
131-
Rgb linear = new(Vector3.Transform(source.ToVector3(), GetCieXyzToRgbMatrix(options.TargetRgbWorkingSpace)));
131+
Rgb linear = new(Vector3.Transform(source.AsVector3Unsafe(), GetCieXyzToRgbMatrix(options.TargetRgbWorkingSpace)));
132132
return FromScaledVector4(options.TargetRgbWorkingSpace.Compress(linear.ToScaledVector4()));
133133
}
134134

@@ -141,7 +141,7 @@ public static void FromProfileConnectionSpace(ColorConversionOptions options, Re
141141
for (int i = 0; i < source.Length; i++)
142142
{
143143
// Convert to linear rgb then compress.
144-
Rgb linear = new(Vector3.Transform(source[i].ToVector3(), matrix));
144+
Rgb linear = new(Vector3.Transform(source[i].AsVector3Unsafe(), matrix));
145145
Vector4 nonlinear = options.TargetRgbWorkingSpace.Compress(linear.ToScaledVector4());
146146
destination[i] = FromScaledVector4(nonlinear);
147147
}
@@ -271,7 +271,7 @@ private static Matrix4x4 GetRgbToCieXyzMatrix(RgbWorkingSpace workingSpace)
271271

272272
Matrix4x4.Invert(xyzMatrix, out Matrix4x4 inverseXyzMatrix);
273273

274-
Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.ToVector3(), inverseXyzMatrix);
274+
Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.AsVector3Unsafe(), inverseXyzMatrix);
275275

276276
// Use transposed Rows/Columns
277277
return new Matrix4x4

src/ImageSharp/ColorProfiles/VonKriesChromaticAdaptation.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ public static CieXyz Transform(in CieXyz source, (CieXyz From, CieXyz To) whiteP
3434
return new(source.X, source.Y, source.Z);
3535
}
3636

37-
Vector3 sourceColorLms = Vector3.Transform(source.ToVector3(), matrix);
38-
Vector3 sourceWhitePointLms = Vector3.Transform(from.ToVector3(), matrix);
39-
Vector3 targetWhitePointLms = Vector3.Transform(to.ToVector3(), matrix);
37+
Vector3 sourceColorLms = Vector3.Transform(source.AsVector3Unsafe(), matrix);
38+
Vector3 sourceWhitePointLms = Vector3.Transform(from.AsVector3Unsafe(), matrix);
39+
Vector3 targetWhitePointLms = Vector3.Transform(to.AsVector3Unsafe(), matrix);
4040

4141
Vector3 vector = targetWhitePointLms / sourceWhitePointLms;
4242
Vector3 targetColorLms = Vector3.Multiply(vector, sourceColorLms);
@@ -76,8 +76,8 @@ public static void Transform(
7676
ref CieXyz sourceBase = ref MemoryMarshal.GetReference(source);
7777
ref CieXyz destinationBase = ref MemoryMarshal.GetReference(destination);
7878

79-
Vector3 sourceWhitePointLms = Vector3.Transform(from.ToVector3(), matrix);
80-
Vector3 targetWhitePointLms = Vector3.Transform(to.ToVector3(), matrix);
79+
Vector3 sourceWhitePointLms = Vector3.Transform(from.AsVector3Unsafe(), matrix);
80+
Vector3 targetWhitePointLms = Vector3.Transform(to.AsVector3Unsafe(), matrix);
8181

8282
Vector3 vector = targetWhitePointLms / sourceWhitePointLms;
8383

@@ -86,7 +86,7 @@ public static void Transform(
8686
ref CieXyz sp = ref Unsafe.Add(ref sourceBase, i);
8787
ref CieXyz dp = ref Unsafe.Add(ref destinationBase, i);
8888

89-
Vector3 sourceColorLms = Vector3.Transform(sp.ToVector3(), matrix);
89+
Vector3 sourceColorLms = Vector3.Transform(sp.AsVector3Unsafe(), matrix);
9090

9191
Vector3 targetColorLms = Vector3.Multiply(vector, sourceColorLms);
9292
dp = new CieXyz(Vector3.Transform(targetColorLms, inverseMatrix));

src/ImageSharp/ColorProfiles/YCbCr.cs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,10 @@ public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<YCbCr> d
130130
public static YCbCr FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source)
131131
{
132132
Vector3 rgb = source.AsVector3Unsafe();
133-
Matrix4x4 m = options.YCbCrMatrix.Forward;
134-
Vector3 offset = options.YCbCrMatrix.Offset;
133+
Matrix4x4 m = options.TransposedYCbCrMatrix.Forward;
134+
Vector3 offset = options.TransposedYCbCrMatrix.Offset;
135135

136-
float y = Vector3.Dot(rgb, new Vector3(m.M11, m.M12, m.M13));
137-
float cb = Vector3.Dot(rgb, new Vector3(m.M21, m.M22, m.M23));
138-
float cr = Vector3.Dot(rgb, new Vector3(m.M31, m.M32, m.M33));
139-
140-
return new YCbCr(new Vector3(y, cb, cr) + offset, true);
136+
return new YCbCr(Vector3.Transform(rgb, m) + offset, true);
141137
}
142138

143139
/// <inheritdoc/>
@@ -156,15 +152,11 @@ public static void FromProfileConnectionSpace(ColorConversionOptions options, Re
156152
/// <inheritdoc/>
157153
public Rgb ToProfileConnectingSpace(ColorConversionOptions options)
158154
{
159-
Matrix4x4 m = options.YCbCrMatrix.Inverse;
160-
Vector3 offset = options.YCbCrMatrix.Offset;
155+
Matrix4x4 m = options.TransposedYCbCrMatrix.Inverse;
156+
Vector3 offset = options.TransposedYCbCrMatrix.Offset;
161157
Vector3 normalized = this.AsVector3Unsafe() - offset;
162158

163-
float r = Vector3.Dot(normalized, new Vector3(m.M11, m.M12, m.M13));
164-
float g = Vector3.Dot(normalized, new Vector3(m.M21, m.M22, m.M23));
165-
float b = Vector3.Dot(normalized, new Vector3(m.M31, m.M32, m.M33));
166-
167-
return Rgb.FromScaledVector3(new Vector3(r, g, b));
159+
return Rgb.FromScaledVector3(Vector3.Transform(normalized, m));
168160
}
169161

170162
/// <inheritdoc/>

src/ImageSharp/ColorProfiles/YcbCrMatrix.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,7 @@ public YCbCrMatrix(Matrix4x4 forward, Matrix4x4 inverse, Vector3 offset)
5555
/// Gets the chrominance offset vector to apply during encoding (add) or decoding (subtract).
5656
/// </summary>
5757
public Vector3 Offset { get; }
58+
59+
internal YCbCrMatrix Transpose()
60+
=> new(Matrix4x4.Transpose(this.Forward), Matrix4x4.Transpose(this.Inverse), this.Offset);
5861
}

src/ImageSharp/ColorProfiles/YccK.cs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -131,23 +131,18 @@ public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<YccK> de
131131
/// <inheritdoc/>
132132
public Rgb ToProfileConnectingSpace(ColorConversionOptions options)
133133
{
134-
Matrix4x4 m = options.YCbCrMatrix.Inverse;
135-
Vector3 offset = options.YCbCrMatrix.Offset;
134+
Matrix4x4 m = options.TransposedYCbCrMatrix.Inverse;
135+
Vector3 offset = options.TransposedYCbCrMatrix.Offset;
136136
Vector3 normalized = this.AsVector3Unsafe() - offset;
137137

138-
float r = Vector3.Dot(normalized, new Vector3(m.M11, m.M12, m.M13));
139-
float g = Vector3.Dot(normalized, new Vector3(m.M21, m.M22, m.M23));
140-
float b = Vector3.Dot(normalized, new Vector3(m.M31, m.M32, m.M33));
141-
142-
Vector3 rgb = new Vector3(r, g, b) * (1F - this.K);
143-
return Rgb.FromScaledVector3(rgb);
138+
return Rgb.FromScaledVector3(Vector3.Transform(normalized, m) * (1F - this.K));
144139
}
145140

146141
/// <inheritdoc/>
147142
public static YccK FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source)
148143
{
149-
Matrix4x4 m = options.YCbCrMatrix.Forward;
150-
Vector3 offset = options.YCbCrMatrix.Offset;
144+
Matrix4x4 m = options.TransposedYCbCrMatrix.Forward;
145+
Vector3 offset = options.TransposedYCbCrMatrix.Offset;
151146

152147
Vector3 rgb = source.AsVector3Unsafe();
153148
float k = 1F - MathF.Max(rgb.X, MathF.Max(rgb.Y, rgb.Z));
@@ -158,12 +153,7 @@ public static YccK FromProfileConnectingSpace(ColorConversionOptions options, in
158153
}
159154

160155
rgb /= 1F - k;
161-
162-
float y = Vector3.Dot(rgb, new Vector3(m.M11, m.M12, m.M13));
163-
float cb = Vector3.Dot(rgb, new Vector3(m.M21, m.M22, m.M23));
164-
float cr = Vector3.Dot(rgb, new Vector3(m.M31, m.M32, m.M33));
165-
166-
return new YccK(new Vector4(y, cb, cr, k) + new Vector4(offset, 0F));
156+
return new YccK(new Vector4(Vector3.Transform(rgb, m), k) + new Vector4(offset, 0F));
167157
}
168158

169159
/// <inheritdoc/>

0 commit comments

Comments
 (0)