Skip to content

Blittable color #106575

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/libraries/NetCoreAppLibrary.props
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
System.Net.WebProxy;
System.Net.WebSockets;
System.Net.WebSockets.Client;
System.Numerics.Colors;
System.Numerics.Vectors;
System.ObjectModel;
System.Private.CoreLib;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@
<Reference Include="System.Linq" />
<Reference Include="System.Memory" />
<Reference Include="System.Net.Security" />
<Reference Include="System.Numerics.Colors" />
<Reference Include="System.ObjectModel" />
<Reference Include="System.Resources.Writer" />
<Reference Include="System.Runtime" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ namespace System.Drawing
public bool Equals(System.Drawing.Color other) { throw null; }
public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; }
public static System.Drawing.Color FromArgb(int argb) { throw null; }
public static System.Drawing.Color FromArgb(System.Numerics.Colors.Argb<byte> argb) { throw null; }
public static System.Drawing.Color FromArgb(int alpha, System.Drawing.Color baseColor) { throw null; }
public static System.Drawing.Color FromArgb(int red, int green, int blue) { throw null; }
public static System.Drawing.Color FromArgb(int alpha, int red, int green, int blue) { throw null; }
Expand All @@ -178,7 +179,10 @@ namespace System.Drawing
public float GetSaturation() { throw null; }
public static bool operator ==(System.Drawing.Color left, System.Drawing.Color right) { throw null; }
public static bool operator !=(System.Drawing.Color left, System.Drawing.Color right) { throw null; }
public static explicit operator System.Numerics.Colors.Argb<byte>(in System.Drawing.Color color) { throw null; }
public static implicit operator System.Drawing.Color(System.Numerics.Colors.Argb<byte> argb) { throw null; }
public int ToArgb() { throw null; }
public System.Numerics.Colors.Argb<byte> ToArgbValue() { throw null; }
public System.Drawing.KnownColor ToKnownColor() { throw null; }
public override string ToString() { throw null; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<ProjectReference Include="..\..\System.ObjectModel\ref\System.ObjectModel.csproj" />
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.ComponentModel.Primitives\ref\System.ComponentModel.Primitives.csproj" />
<ProjectReference Include="..\..\System.Numerics.Colors\ref\System.Numerics.Colors.csproj" />
<ProjectReference Include="..\..\System.Numerics.Vectors\ref\System.Numerics.Vectors.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<Reference Include="System.Collections" />
<Reference Include="System.ComponentModel.Primitives" />
<Reference Include="System.Memory" />
<Reference Include="System.Numerics.Colors" />
<Reference Include="System.Numerics.Vectors" />
<Reference Include="System.ObjectModel" />
<Reference Include="System.Runtime" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Numerics.Colors;
using System.Runtime.CompilerServices;

namespace System.Drawing
Expand Down Expand Up @@ -333,7 +334,7 @@ namespace System.Drawing
internal const uint ARGBBlueMask = 0xFFu << ARGBBlueShift;

// User supplied name of color. Will not be filled in if
// we map to a "knowncolor"
// we map to a "knownColor"
private readonly string? name; // Do not rename (binary serialization)

// Standard 32bit sRGB (ARGB)
Expand Down Expand Up @@ -398,10 +399,10 @@ public string Name

if (IsKnownColor)
{
string tablename = KnownColorNames.KnownColorToName((KnownColor)knownColor);
Debug.Assert(tablename != null, $"Could not find known color '{(KnownColor)knownColor}' in the KnownColorTable");
string tableName = KnownColorNames.KnownColorToName((KnownColor)knownColor);
Debug.Assert(tableName != null, $"Could not find known color '{(KnownColor)knownColor}' in the KnownColorTable");

return tablename;
return tableName;
}

// if we reached here, just encode the value
Expand Down Expand Up @@ -442,6 +443,10 @@ static void ThrowOutOfByteRange(int v, string n) =>

public static Color FromArgb(int argb) => FromArgb(unchecked((uint)argb));

public static Color FromArgb(Argb<byte> argb) => FromArgb(BitConverter.IsLittleEndian ?
Argb.ToUInt32LittleEndian(argb) :
Argb.ToUInt32BigEndian(argb));

public static Color FromArgb(int alpha, int red, int green, int blue)
{
CheckByte(alpha, nameof(alpha));
Expand Down Expand Up @@ -567,6 +572,10 @@ public float GetSaturation()

public int ToArgb() => unchecked((int)Value);

public Argb<byte> ToArgbValue() => BitConverter.IsLittleEndian ?
Argb.CreateLittleEndian(unchecked((uint)Value)) :
Argb.CreateBigEndian(unchecked((uint)Value));

public KnownColor ToKnownColor() => (KnownColor)knownColor;

public override string ToString() =>
Expand All @@ -582,6 +591,10 @@ public override string ToString() =>

public static bool operator !=(Color left, Color right) => !(left == right);

public static implicit operator Color(Argb<byte> argb) => FromArgb(argb);

public static explicit operator Argb<byte>(in Color color) => color.ToArgbValue();

public override bool Equals([NotNullWhen(true)] object? obj) => obj is Color other && Equals(other);

public bool Equals(Color other) => this == other;
Expand Down
75 changes: 60 additions & 15 deletions src/libraries/System.Drawing.Primitives/tests/ColorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics.Colors;
using System.Runtime.InteropServices;
using Xunit;

Expand Down Expand Up @@ -194,23 +195,45 @@ public void ArgbValues(string name, int alpha, int red, int green, int blue)
[InlineData(1, 2, 3, 4)]
public void FromArgb_Roundtrips(int a, int r, int g, int b)
{
Color c1 = Color.FromArgb(unchecked((int)((uint)a << 24 | (uint)r << 16 | (uint)g << 8 | (uint)b)));
Assert.Equal(a, c1.A);
Assert.Equal(r, c1.R);
Assert.Equal(g, c1.G);
Assert.Equal(b, c1.B);
{
Color c = Color.FromArgb(unchecked((int)((uint)a << 24 | (uint)r << 16 | (uint)g << 8 | (uint)b)));
Assert.Equal(a, c.A);
Assert.Equal(r, c.R);
Assert.Equal(g, c.G);
Assert.Equal(b, c.B);
}
{
Color c = Color.FromArgb(a, r, g, b);
Assert.Equal(a, c.A);
Assert.Equal(r, c.R);
Assert.Equal(g, c.G);
Assert.Equal(b, c.B);
}
{

Color c2 = Color.FromArgb(a, r, g, b);
Assert.Equal(a, c2.A);
Assert.Equal(r, c2.R);
Assert.Equal(g, c2.G);
Assert.Equal(b, c2.B);
Color c = Color.FromArgb(r, g, b);
Assert.Equal(255, c.A);
Assert.Equal(r, c.R);
Assert.Equal(g, c.G);
Assert.Equal(b, c.B);
}
{

Color c = Color.FromArgb(new Argb<byte>((byte)a, (byte)r, (byte)g, (byte)b));
Assert.Equal(a, c.A);
Assert.Equal(r, c.R);
Assert.Equal(g, c.G);
Assert.Equal(b, c.B);
}
{

Color c3 = Color.FromArgb(r, g, b);
Assert.Equal(255, c3.A);
Assert.Equal(r, c3.R);
Assert.Equal(g, c3.G);
Assert.Equal(b, c3.B);
// implicit operator Color(Argb<byte> argb)
Color c = new Argb<byte>((byte)a, (byte)r, (byte)g, (byte)b);
Assert.Equal(a, c.A);
Assert.Equal(r, c.R);
Assert.Equal(g, c.G);
Assert.Equal(b, c.B);
}
}

[Fact]
Expand Down Expand Up @@ -267,6 +290,28 @@ public void ToArgb(int argb, int alpha, int red, int green, int blue)
Assert.Equal(argb, Color.FromArgb(alpha, red, green, blue).ToArgb());
}

[Theory]
[InlineData(0x11, 0xcc, 0x88, 0x33)]
[InlineData(0xf1, 0xcc, 0x88, 0x33)]
public void ToArgbValue(int alpha, int red, int green, int blue)
{
{
var c = Color.FromArgb(alpha, red, green, blue).ToArgbValue();
Assert.Equal(alpha, c.A);
Assert.Equal(red, c.R);
Assert.Equal(green, c.G);
Assert.Equal(blue, c.B);
}
{
// explicit operator Argb<byte>(in Color color)
Argb<byte> c = (Argb<byte>)Color.FromArgb(alpha, red, green, blue);
Assert.Equal(alpha, c.A);
Assert.Equal(red, c.R);
Assert.Equal(green, c.G);
Assert.Equal(blue, c.B);
}
}

[Fact]
public void ToStringEmpty()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using System.Threading;
using Xunit;

namespace System.Drawing.Tests
namespace System.Drawing.Primitives.Tests
{
public class ColorTranslatorTests
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Reflection;
using Xunit;

namespace System.Drawing.PrimitivesTests
namespace System.Drawing.Primitives.Tests
{
public class PointFTests
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Globalization;
using Xunit;

namespace System.Drawing.PrimitivesTests
namespace System.Drawing.Primitives.Tests
{
public class PointTests
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Numerics;
using Xunit;

namespace System.Drawing.PrimitivesTest
namespace System.Drawing.Primitives.Tests
{
public class RectangleFTests
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Globalization;
using Xunit;

namespace System.Drawing.PrimitivesTest
namespace System.Drawing.Primitives.Tests
{
public class RectangleTests
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Numerics;
using Xunit;

namespace System.Drawing.PrimitivesTest
namespace System.Drawing.Primitives.Tests
{
public class SizeFTests
{
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/System.Drawing.Primitives/tests/SizeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Globalization;
using Xunit;

namespace System.Drawing.PrimitivesTests
namespace System.Drawing.Primitives.Tests
{
public class SizeTests
{
Expand Down
6 changes: 6 additions & 0 deletions src/libraries/System.Numerics.Colors/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Project>
<Import Project="..\Directory.Build.props" />
<PropertyGroup>
<StrongNameKeyId>Microsoft</StrongNameKeyId>
</PropertyGroup>
</Project>
7 changes: 7 additions & 0 deletions src/libraries/System.Numerics.Colors/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# System.Numerics.Colors

Provides APIs for convertible colors that contains only raw color data.

The intent is NOT to start building a general purpose image manipulation library. Libraries such as ImageSharp are the right answer for this.

WinForms and System.Drawing will be able to leverage this for performance, which was the original driver for this request.
Loading
Loading