Browse Source

Optimize color transforms

Former-commit-id: 1a4e60efcbbd808458de430eb0c9c97c3c43d3e3
Former-commit-id: 873233f36b1496b8d4dfa05785db88e63eff7bf7
Former-commit-id: 6958707f80b777c1daa04047b14480da56d1d73c
af/merge-core
James Jackson-South 10 years ago
parent
commit
af3ad14a11
  1. 20
      src/ImageProcessor/Colors/ColorTransforms.cs
  2. 9
      src/ImageProcessor/Colors/Colorspaces/Bgra32.cs
  3. 36
      src/ImageProcessor/Colors/Colorspaces/CieLab.cs
  4. 6
      src/ImageProcessor/Colors/Colorspaces/CieXyz.cs
  5. 27
      src/ImageProcessor/Colors/Colorspaces/Cmyk.cs
  6. 4
      src/ImageProcessor/Colors/Colorspaces/Hsl.cs
  7. 4
      src/ImageProcessor/Colors/Colorspaces/Hsv.cs
  8. 12
      src/ImageProcessor/Colors/Colorspaces/YCbCr.cs

20
src/ImageProcessor/Colors/ColorTransforms.cs

@ -186,9 +186,9 @@ namespace ImageProcessor
float temp2 = (l < 0.5f) ? l * (1f + s) : l + s - (l * s);
float temp1 = (2f * l) - temp2;
r = GetColorComponent(temp1, temp2, rangedH + (1 / 3f));
r = GetColorComponent(temp1, temp2, rangedH + 0.3333333F);
g = GetColorComponent(temp1, temp2, rangedH);
b = GetColorComponent(temp1, temp2, rangedH - (1 / 3f));
b = GetColorComponent(temp1, temp2, rangedH - 0.3333333F);
}
}
@ -207,16 +207,16 @@ namespace ImageProcessor
{
// First convert back to XYZ...
float y = (cieLabColor.L + 16F) / 116F;
float x = cieLabColor.A / 500F + y;
float z = y - cieLabColor.B / 200F;
float x = (cieLabColor.A / 500F) + y;
float z = y - (cieLabColor.B / 200F);
float x3 = x * x * x;
float y3 = y * y * y;
float z3 = z * z * z;
x = x3 > 0.008856F ? x3 : (x - 16F / 116F) / 7.787F;
y = (cieLabColor.L > 0.008856F * 903.3F) ? y3 : (cieLabColor.L / 903.3F);
z = (z3 > 0.008856F) ? z3 : (z - 16F / 116F) / 7.787F;
x = x3 > 0.008856F ? x3 : (x - 0.137931F) / 7.787F;
y = (cieLabColor.L > 7.999625F) ? y3 : (cieLabColor.L / 903.3F);
z = (z3 > 0.008856F) ? z3 : (z - 0.137931F) / 7.787F;
x *= 0.95047F;
z *= 1.08883F;
@ -241,7 +241,7 @@ namespace ImageProcessor
private static float GetColorComponent(float first, float second, float third)
{
third = MoveIntoRange(third);
if (third < 1.0 / 6.0)
if (third < 0.1666667F)
{
return first + ((second - first) * 6.0f * third);
}
@ -251,9 +251,9 @@ namespace ImageProcessor
return second;
}
if (third < 2.0 / 3.0)
if (third < 0.6666667F)
{
return first + ((second - first) * ((2.0f / 3.0f) - third) * 6.0f);
return first + ((second - first) * (0.6666667F - third) * 6.0f);
}
return first;

9
src/ImageProcessor/Colors/Colorspaces/Bgra32.cs

@ -45,10 +45,7 @@ namespace ImageProcessor
public Bgra32(byte b, byte g, byte r, byte a)
: this()
{
this.backingVector.X = b.Clamp(0, 255);
this.backingVector.Y = g.Clamp(0, 255);
this.backingVector.Z = r.Clamp(0, 255);
this.backingVector.W = a.Clamp(0, 255);
this.backingVector = Vector4.Clamp(new Vector4(b, g, r, a), Vector4.Zero, new Vector4(255));
}
/// <summary>
@ -94,8 +91,8 @@ namespace ImageProcessor
/// </returns>
public static implicit operator Bgra32(Color color)
{
color = color.Limited;
return new Bgra32((255f * color.B).ToByte(), (255f * color.G).ToByte(), (255f * color.R).ToByte(), (255f * color.A).ToByte());
color = color.Limited * 255f;
return new Bgra32((byte)color.B, (byte)color.G, (byte)color.R, (byte)color.A);
}
/// <summary>

36
src/ImageProcessor/Colors/Colorspaces/CieLab.cs

@ -39,9 +39,7 @@ namespace ImageProcessor
public CieLab(float l, float a, float b)
: this()
{
this.backingVector.X = ClampL(l);
this.backingVector.Y = ClampAB(a);
this.backingVector.Z = ClampAB(b);
this.backingVector = Vector3.Clamp(new Vector3(l, a, b), new Vector3(0, -100, -100), new Vector3(100));
}
/// <summary>
@ -81,7 +79,7 @@ namespace ImageProcessor
public static implicit operator CieLab(Color color)
{
// First convert to CIE XYZ
color = Color.Expand(color.Limited);
color = Color.Expand(color);
float x = (color.R * 0.4124F) + (color.G * 0.3576F) + (color.B * 0.1805F);
float y = (color.R * 0.2126F) + (color.G * 0.7152F) + (color.B * 0.0722F);
@ -92,9 +90,9 @@ namespace ImageProcessor
//y /= 1F;
z /= 1.08883F;
x = x > 0.008856F ? (float)Math.Pow(x, 1F / 3F) : (903.3F * x + 16F) / 116F;
y = y > 0.008856F ? (float)Math.Pow(y, 1F / 3F) : (903.3F * y + 16F) / 116F;
z = z > 0.008856F ? (float)Math.Pow(z, 1F / 3F) : (903.3F * z + 16F) / 116F;
x = x > 0.008856F ? (float)Math.Pow(x, 0.3333333F) : (903.3F * x + 16F) / 116F;
y = y > 0.008856F ? (float)Math.Pow(y, 0.3333333F) : (903.3F * y + 16F) / 116F;
z = z > 0.008856F ? (float)Math.Pow(z, 0.3333333F) : (903.3F * z + 16F) / 116F;
float l = Math.Max(0, (116F * y) - 16F);
float a = 500F * (x - y);
@ -179,30 +177,6 @@ namespace ImageProcessor
&& Math.Abs(this.B - other.B) < precision;
}
/// <summary>
/// Checks the range for lightness.
/// </summary>
/// <param name="value">The value to check.</param>
/// <returns>
/// The sanitized <see cref="float"/>.
/// </returns>
private static float ClampL(float value)
{
return value.Clamp(0, 100);
}
/// <summary>
/// Checks the range for components A or B.
/// </summary>
/// <param name="value">The value to check.</param>
/// <returns>
/// The sanitized <see cref="float"/>.
/// </returns>
private static float ClampAB(float value)
{
return value.Clamp(-100, 100);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>

6
src/ImageProcessor/Colors/Colorspaces/CieXyz.cs

@ -40,9 +40,7 @@ namespace ImageProcessor
: this()
{
// Not clamping as documentation about this space seems to indicate "usual" ranges
this.backingVector.X = x;
this.backingVector.Y = y;
this.backingVector.Z = z;
this.backingVector = new Vector3(x, y, z);
}
/// <summary>
@ -81,7 +79,7 @@ namespace ImageProcessor
/// </returns>
public static implicit operator CieXyz(Color color)
{
color = Color.Expand(color.Limited);
color = Color.Expand(color);
float x = (color.R * 0.4124F) + (color.G * 0.3576F) + (color.B * 0.1805F);
float y = (color.R * 0.2126F) + (color.G * 0.7152F) + (color.B * 0.0722F);

27
src/ImageProcessor/Colors/Colorspaces/Cmyk.cs

@ -32,17 +32,14 @@ namespace ImageProcessor
/// <summary>
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
/// </summary>
/// <param name="cyan">The cyan component.</param>
/// <param name="magenta">The magenta component.</param>
/// <param name="yellow">The yellow component.</param>
/// <param name="keyline">The keyline black component.</param>
public Cmyk(float cyan, float magenta, float yellow, float keyline)
/// <param name="c">The cyan component.</param>
/// <param name="m">The magenta component.</param>
/// <param name="y">The yellow component.</param>
/// <param name="k">The keyline black component.</param>
public Cmyk(float c, float m, float y, float k)
: this()
{
this.backingVector.X = Clamp(cyan);
this.backingVector.Y = Clamp(magenta);
this.backingVector.Z = Clamp(yellow);
this.backingVector.W = Clamp(keyline);
this.backingVector = Vector4.Clamp(new Vector4(c, m, y, k), Vector4.Zero, Vector4.One);
}
/// <summary>
@ -184,18 +181,6 @@ namespace ImageProcessor
&& Math.Abs(this.K - other.K) < precision;
}
/// <summary>
/// Checks the range of the given value to ensure that it remains within the acceptable boundaries.
/// </summary>
/// <param name="value">The value to check.</param>
/// <returns>
/// The sanitized <see cref="float"/>.
/// </returns>
private static float Clamp(float value)
{
return value.Clamp(0, 1);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>

4
src/ImageProcessor/Colors/Colorspaces/Hsl.cs

@ -37,9 +37,7 @@ namespace ImageProcessor
/// <param name="l">The l value (lightness) component.</param>
public Hsl(float h, float s, float l)
{
this.backingVector.X = h.Clamp(0, 360);
this.backingVector.Y = s.Clamp(0, 1);
this.backingVector.Z = l.Clamp(0, 1);
this.backingVector = Vector3.Clamp(new Vector3(h, s, l), Vector3.Zero, new Vector3(360, 1, 1));
}
/// <summary>

4
src/ImageProcessor/Colors/Colorspaces/Hsv.cs

@ -37,9 +37,7 @@ namespace ImageProcessor
/// <param name="v">The v value (brightness) component.</param>
public Hsv(float h, float s, float v)
{
this.backingVector.X = h.Clamp(0, 360);
this.backingVector.Y = s.Clamp(0, 1);
this.backingVector.Z = v.Clamp(0, 1);
this.backingVector = Vector3.Clamp(new Vector3(h, s, v), Vector3.Zero, new Vector3(360, 1, 1));
}
/// <summary>

12
src/ImageProcessor/Colors/Colorspaces/YCbCr.cs

@ -40,9 +40,7 @@ namespace ImageProcessor
public YCbCr(float y, float cb, float cr)
: this()
{
this.backingVector.X = y.Clamp(0, 255);
this.backingVector.Y = cb.Clamp(0, 255);
this.backingVector.Z = cr.Clamp(0, 255);
this.backingVector = Vector3.Clamp(new Vector3(y, cb, cr), Vector3.Zero, new Vector3(255));
}
/// <summary>
@ -81,10 +79,10 @@ namespace ImageProcessor
/// </returns>
public static implicit operator YCbCr(Color color)
{
color = Color.ToNonPremultiplied(color.Limited);
float r = color.R * 255f;
float g = color.G * 255f;
float b = color.B * 255f;
color = Color.ToNonPremultiplied(color.Limited) * 255f;
float r = color.R;
float g = color.G;
float b = color.B;
float y = (float)((0.299 * r) + (0.587 * g) + (0.114 * b));
float cb = 128 + (float)((-0.168736 * r) - (0.331264 * g) + (0.5 * b));

Loading…
Cancel
Save