Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Colorspace Transforms #664

Merged
merged 78 commits into from
Oct 10, 2018
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
6c29cee
Normalize namespace
JimBobSquarePants Nov 26, 2017
b1f3aad
Cleanup + obvious perf improvements
JimBobSquarePants Nov 26, 2017
dc242b0
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Dec 20, 2017
59d1f13
Use SIMD for CMYK->RGB and vice versa
JimBobSquarePants Dec 20, 2017
35d623a
More cleanup
JimBobSquarePants Dec 20, 2017
ce4d4bf
Update Colorful and add Pow benchmark
JimBobSquarePants Dec 20, 2017
3b86080
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Dec 21, 2017
2eed8a1
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Feb 6, 2018
8943a8f
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Feb 19, 2018
316d682
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Mar 1, 2018
881aac6
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Mar 1, 2018
2c3dc41
Faster Pow functions
JimBobSquarePants Mar 1, 2018
3cd9cff
Begin bulk conversion API
JimBobSquarePants Mar 1, 2018
01f2499
No point inlining a method containing an exception
JimBobSquarePants Mar 1, 2018
f4c0ffe
More bulk conversions. Pause now for new System.Memory
JimBobSquarePants Mar 2, 2018
aa30806
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Mar 3, 2018
be709df
Migrate span and fix up benchmarks project
JimBobSquarePants Mar 3, 2018
f5b8aba
Add bulk conversion to CieLuv
JimBobSquarePants Mar 3, 2018
e0dabf9
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Mar 14, 2018
168a724
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Mar 19, 2018
58a4297
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Mar 21, 2018
d50f61c
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Mar 28, 2018
215dedf
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Apr 17, 2018
00a70a4
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Apr 23, 2018
8e92dc1
Merge branch 'master' into colorspace-transforms
JimBobSquarePants May 24, 2018
9163f85
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Jun 8, 2018
7c5343a
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Jul 4, 2018
fb533f5
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Jul 9, 2018
daa06b6
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Jul 12, 2018
1223f78
Simplify structs, 5% perf increase.
JimBobSquarePants Jul 12, 2018
72b292a
Add bulk CieXyy transforms
JimBobSquarePants Jul 14, 2018
1f375b1
Add bulk ToCieXyz
JimBobSquarePants Jul 15, 2018
baa7ebe
Add bulk ToCmyk
JimBobSquarePants Jul 15, 2018
babe6e4
Add bulk ToHsl, ToHsv
JimBobSquarePants Jul 15, 2018
e77ddd2
Fix tests
JimBobSquarePants Jul 15, 2018
e972a5d
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Jul 18, 2018
5cc0e8b
Add bulk ToHunterLab, ToLinearRgb, and ToLms
JimBobSquarePants Jul 23, 2018
de253da
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Jul 25, 2018
71bd4c9
Begin colorspace test cleanup.
JimBobSquarePants Jul 26, 2018
8966e7d
Bulk colorspace conversion tests
JimBobSquarePants Jul 27, 2018
f04b1e7
Make colorspaces public
JimBobSquarePants Jul 27, 2018
6bd974f
Add companding tests
JimBobSquarePants Jul 27, 2018
7f3cdc8
Cleanup ToString() and remove unused operator
JimBobSquarePants Jul 28, 2018
0d27887
Make ColorSpaceConverter immutable.
JimBobSquarePants Jul 29, 2018
a5ec503
Remove per-pixel allocation
JimBobSquarePants Jul 30, 2018
b3c1ef7
Notes
JimBobSquarePants Jul 30, 2018
1bcdb31
Remove interface.
JimBobSquarePants Jul 30, 2018
e516dfe
Add Rgb specific tests
JimBobSquarePants Jul 30, 2018
ba040d7
Calculate bool once in constructor.
JimBobSquarePants Aug 1, 2018
ff17b2a
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Aug 4, 2018
fbb1318
use ImageSharp Guard / DebugGuard
antonfirsov Aug 5, 2018
fb119f9
Merge branch 'colorspace-transforms' of https://github.com/SixLabors/…
antonfirsov Aug 5, 2018
064133d
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Aug 7, 2018
c48a6d2
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Aug 21, 2018
aef49c9
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Aug 23, 2018
391fbea
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Aug 31, 2018
d0d9851
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Sep 11, 2018
10458ee
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Sep 18, 2018
2bc0c17
Begin ToString() formatting.
JimBobSquarePants Sep 18, 2018
5c589f6
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Oct 2, 2018
e609a3a
Remove duplicate Adaption checks and reduce allocations.
JimBobSquarePants Oct 2, 2018
346147a
Fix colorspace string representation tests.
JimBobSquarePants Oct 2, 2018
7845e86
Add clamping and more struct tests
JimBobSquarePants Oct 2, 2018
fd0ac3e
Upate rgb test format
JimBobSquarePants Oct 2, 2018
321e439
Fix accidentally replaced test image
JimBobSquarePants Oct 2, 2018
a31dfab
Added bulk adaptation method plus more tests
JimBobSquarePants Oct 2, 2018
5a75939
source should be ReadOnlySpan<T> for all bulk-conversion methods + in…
antonfirsov Oct 3, 2018
762c743
Normalise inlining, remove flaky test.
JimBobSquarePants Oct 3, 2018
3af4fb1
Add CieLab tests
JimBobSquarePants Oct 3, 2018
54d45d5
CieLuv tests
JimBobSquarePants Oct 3, 2018
eb04ca6
CieXyy tests
JimBobSquarePants Oct 3, 2018
4d9c427
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Oct 6, 2018
a673869
Add additional tests
JimBobSquarePants Oct 6, 2018
a7cafa7
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Oct 6, 2018
17ae98d
Add some Cmyk tests
JimBobSquarePants Oct 7, 2018
b2411b6
Merge branch 'master' into colorspace-transforms
JimBobSquarePants Oct 10, 2018
dc2792b
Replace ICompanding with static methods.
JimBobSquarePants Oct 10, 2018
b82ea98
Unify sRGB companding
JimBobSquarePants Oct 10, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 48 additions & 95 deletions src/ImageSharp/ColorSpaces/CieLab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.

using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;

Expand All @@ -12,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents a CIE L*a*b* 1976 color.
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space"/>
/// </summary>
internal readonly struct CieLab : IColorVector, IEquatable<CieLab>, IAlmostEquatable<CieLab, float>
public readonly struct CieLab : IEquatable<CieLab>
{
/// <summary>
/// D50 standard illuminant.
Expand All @@ -21,9 +20,27 @@ namespace SixLabors.ImageSharp.ColorSpaces
public static readonly CieXyz DefaultWhitePoint = Illuminants.D50;

/// <summary>
/// The backing vector for SIMD support.
/// Gets the lightness dimension.
/// <remarks>A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L;

/// <summary>
/// Gets the a color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is green, positive magenta.</remarks>
/// </summary>
public readonly float A;

/// <summary>
/// Gets the b color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
/// </summary>
public readonly float B;

/// <summary>
/// Gets the reference white point of this color
/// </summary>
private readonly Vector3 backingVector;
public readonly CieXyz WhitePoint;

/// <summary>
/// Initializes a new instance of the <see cref="CieLab"/> struct.
Expand All @@ -32,9 +49,9 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <param name="a">The a (green - magenta) component.</param>
/// <param name="b">The b (blue - yellow) component.</param>
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public CieLab(float l, float a, float b)
: this(new Vector3(l, a, b), DefaultWhitePoint)
: this(l, a, b, DefaultWhitePoint)
{
}

Expand All @@ -45,7 +62,7 @@ public CieLab(float l, float a, float b)
/// <param name="a">The a (green - magenta) component.</param>
/// <param name="b">The b (blue - yellow) component.</param>
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public CieLab(float l, float a, float b, CieXyz whitePoint)
: this(new Vector3(l, a, b), whitePoint)
{
Expand All @@ -56,7 +73,7 @@ public CieLab(float l, float a, float b, CieXyz whitePoint)
/// </summary>
/// <param name="vector">The vector representing the l, a, b components.</param>
/// <remarks>Uses <see cref="DefaultWhitePoint"/> as white point.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public CieLab(Vector3 vector)
: this(vector, DefaultWhitePoint)
{
Expand All @@ -67,126 +84,62 @@ public CieLab(Vector3 vector)
/// </summary>
/// <param name="vector">The vector representing the l, a, b components.</param>
/// <param name="whitePoint">The reference white point. <see cref="Illuminants"/></param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public CieLab(Vector3 vector, CieXyz whitePoint)
: this()
{
this.backingVector = vector;
// Not clamping as documentation about this space seems to indicate "usual" ranges
this.L = vector.X;
this.A = vector.Y;
this.B = vector.Z;
this.WhitePoint = whitePoint;
}

/// <summary>
/// Gets the reference white point of this color
/// </summary>
public CieXyz WhitePoint { get; }

/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public float L
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.backingVector.X;
}

/// <summary>
/// Gets the a color component.
/// <remarks>A value ranging from -100 to 100. Negative is green, positive magenta.</remarks>
/// </summary>
public float A
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.backingVector.Y;
}

/// <summary>
/// Gets the b color component.
/// <remarks>A value ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
/// </summary>
public float B
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.backingVector.Z;
}

/// <inheritdoc />
public Vector3 Vector => this.backingVector;

/// <summary>
/// Compares two <see cref="CieLab"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="CieLab"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="CieLab"/> on the right side of the operand.
/// </param>
/// <param name="left">The <see cref="CieLab"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="CieLab"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(CieLab left, CieLab right)
{
return left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(CieLab left, CieLab right) => left.Equals(right);

/// <summary>
/// Compares two <see cref="CieLab"/> objects for inequality
/// </summary>
/// <param name="left">
/// The <see cref="CieLab"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="CieLab"/> on the right side of the operand.
/// </param>
/// <param name="left">The <see cref="CieLab"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="CieLab"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(CieLab left, CieLab right)
{
return !left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(CieLab left, CieLab right) => !left.Equals(right);

/// <inheritdoc/>
public override int GetHashCode()
{
return HashHelpers.Combine(this.WhitePoint.GetHashCode(), this.backingVector.GetHashCode());
int hash = this.L.GetHashCode();
hash = HashHelpers.Combine(hash, this.A.GetHashCode());
hash = HashHelpers.Combine(hash, this.B.GetHashCode());
return HashHelpers.Combine(hash, this.WhitePoint.GetHashCode());
}

/// <inheritdoc/>
public override string ToString()
{
return this.Equals(default)
? "CieLab [Empty]"
: $"CieLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]";
}
public override string ToString() => $"CieLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})";

/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is CieLab other && this.Equals(other);
}
public override bool Equals(object obj) => obj is CieLab other && this.Equals(other);

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieLab other)
{
return this.backingVector.Equals(other.backingVector)
return this.L.Equals(other.L)
&& this.A.Equals(other.A)
&& this.B.Equals(other.B)
&& this.WhitePoint.Equals(other.WhitePoint);
}

/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool AlmostEquals(CieLab other, float precision)
{
var result = Vector3.Abs(this.backingVector - other.backingVector);

return this.WhitePoint.Equals(other.WhitePoint)
&& result.X <= precision
&& result.Y <= precision
&& result.Z <= precision;
}
}
}
Loading