Browse Source

Fix HSV/BGRA conversions.

Former-commit-id: 15347486e210642b35e35e1c3220d86778897773
Former-commit-id: ce3d10d48dc5149cb84ac3c6fb2d442c98d0950a
Former-commit-id: ed21c57a33d1f5da11052bb97746f0ebeb63597e
af/merge-core
James Jackson-South 11 years ago
parent
commit
ef09899838
  1. 66
      src/ImageProcessor/Colors/Hsv.cs
  2. 56
      tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs

66
src/ImageProcessor/Colors/Hsv.cs

@ -52,7 +52,7 @@ namespace ImageProcessor
/// <remarks>A value ranging between 0 and 100.</remarks>
/// </summary>
public readonly float S;
/// <summary>
/// Gets the V value (brightness) component.
/// <remarks>A value ranging between 0 and 100.</remarks>
@ -117,30 +117,33 @@ namespace ImageProcessor
/// </returns>
public static implicit operator Hsv(Bgra color)
{
float max = Math.Max(color.R, Math.Max(color.G, color.B));
float min = Math.Min(color.R, Math.Min(color.G, color.B));
float delta = max - min;
if (Math.Abs(max) < Epsilon)
float r = color.R / 255f;
float g = color.G / 255f;
float b = color.B / 255f;
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
float chroma = max - min;
float h = 0;
float s = 0;
float v = max;
if (Math.Abs(chroma) < Epsilon)
{
return new Hsv(0, 0, 0);
return new Hsv(0, s * 100, v * 100);
}
float h = 0.0F;
float s;
float v;
if (Math.Abs(delta) < Epsilon) { h = 0; }
else if (Math.Abs(color.R - max) < Epsilon) { h = (color.G - color.B) / delta; }
else if (Math.Abs(color.G - max) < Epsilon) { h = 2 + (color.B - color.R) / delta; }
else if (Math.Abs(color.B - max) < Epsilon) { h = 4 + (color.R - color.G) / delta; }
if (Math.Abs(chroma) < Epsilon) { h = 0; }
else if (Math.Abs(r - max) < Epsilon) { h = (g - b) / chroma; }
else if (Math.Abs(g - max) < Epsilon) { h = 2 + (b - r) / chroma; }
else if (Math.Abs(b - max) < Epsilon) { h = 4 + (r - g) / chroma; }
h *= 60;
if (h < 0.0) { h += 360; }
s = delta / max;
v = max / 255F;
return new Hsv(h, s, v);
s = (chroma / v);
return new Hsv(h, s * 100, v * 100);
}
/// <summary>
@ -155,9 +158,12 @@ namespace ImageProcessor
/// </returns>
public static implicit operator Bgra(Hsv color)
{
if (Math.Abs(color.S) < Epsilon)
float s = color.S / 100;
float v = color.V / 100;
if (Math.Abs(s) < Epsilon)
{
byte component = (byte)(color.V * 255);
byte component = (byte)(v * 255);
return new Bgra(component, component, component, 255);
}
@ -165,51 +171,51 @@ namespace ImageProcessor
int i = (int)(Math.Truncate(h));
float f = h - i;
float p = color.V * (1.0f - color.S);
float q = color.V * (1.0f - (color.S * f));
float t = color.V * (1.0f - (color.S * (1.0f - f)));
float p = v * (1.0f - s);
float q = v * (1.0f - (s * f));
float t = v * (1.0f - (s * (1.0f - f)));
float r, g, b;
switch (i)
{
case 0:
r = color.V;
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = color.V;
g = v;
b = p;
break;
case 2:
r = p;
g = color.V;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = color.V;
b = v;
break;
case 4:
r = t;
g = p;
b = color.V;
b = v;
break;
default:
r = color.V;
r = v;
g = p;
b = q;
break;
}
return new Bgra((byte)b, (byte)g, (byte)r);
return new Bgra((byte)(Math.Round(b * 255)), (byte)(Math.Round(g * 255)), (byte)(Math.Round(r * 255)));
}
/// <summary>

56
tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs

@ -10,6 +10,7 @@
namespace ImageProcessor.Tests
{
using System;
using System.Diagnostics.CodeAnalysis;
using Xunit;
@ -94,13 +95,21 @@ namespace ImageProcessor.Tests
Justification = "Reviewed. Suppression is OK here.")]
public void BgrToHsv()
{
// Black
Bgra b = new Bgra(0, 0, 0, 255);
Hsv h = b;
Assert.Equal(0, h.H);
Assert.Equal(0, h.S);
Assert.Equal(0, h.V);
// White
Bgra color = new Bgra(255, 255, 255, 255);
Hsv hsv = color;
Assert.Equal(0, hsv.H);
Assert.Equal(0, hsv.S);
Assert.Equal(1, hsv.V);
Assert.Equal(100, hsv.V);
// Dark moderate pink.
Bgra color2 = new Bgra(106, 64, 128, 255);
@ -109,6 +118,51 @@ namespace ImageProcessor.Tests
Assert.Equal(320.6, hsv2.H, 1);
Assert.Equal(50, hsv2.S, 1);
Assert.Equal(50.2, hsv2.V, 1);
// Ochre.
Bgra color3 = new Bgra(34, 119, 204, 255);
Hsv hsv3 = color3;
Assert.Equal(30, hsv3.H, 1);
Assert.Equal(83.3, hsv3.S, 1);
Assert.Equal(80, hsv3.V, 1);
}
[Fact]
public void HsvToBgr()
{
// Dark moderate pink.
Hsv hsv = new Hsv(320.6f, 50, 50.2f);
Bgra bgra = hsv;
Assert.Equal(bgra.B, 106);
Assert.Equal(bgra.G, 64);
Assert.Equal(bgra.R, 128);
// Ochre
Hsv hsv2 = new Hsv(30, 83.3f, 80);
Bgra bgra2 = hsv2;
Assert.Equal(bgra2.B, 34);
Assert.Equal(bgra2.G, 119);
Assert.Equal(bgra2.R, 204);
// White
Hsv hsv3 = new Hsv(0, 0, 100);
Bgra bgra3 = hsv3;
Assert.Equal(bgra3.B, 255);
Assert.Equal(bgra3.G, 255);
Assert.Equal(bgra3.R, 255);
// Check others.
Random random = new Random(0);
for (var i = 0; i < 1000; i++)
{
Bgra bgra4 = new Bgra((byte)random.Next(255), (byte)random.Next(255), (byte)random.Next(255));
Hsv hsb4 = bgra4;
Assert.Equal(bgra4, (Bgra)hsb4);
}
}
}
}

Loading…
Cancel
Save