Skip to content

Commit 5fcd54a

Browse files
Merge branch 'master' into Release
2 parents 37933af + cdddb89 commit 5fcd54a

File tree

8 files changed

+511
-4
lines changed

8 files changed

+511
-4
lines changed

IronSoftware.Drawing/IronSoftware.Drawing.Common.Tests/UnitTests/AnyBitmapFunctionality.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,37 @@ public void AnyBitmap_should_get_Bytes()
215215
Assert.Equal(expected, resultExport);
216216
}
217217

218+
[FactWithAutomaticDisplayName]
219+
public void AnyBitmap_should_set_Pixel()
220+
{
221+
string imagePath = GetRelativeFilePath("checkmark.jpg");
222+
223+
using Image<Rgb24> formatRgb24 = Image.Load<Rgb24>(imagePath);
224+
using Image<Abgr32> formatAbgr32 = Image.Load<Abgr32>(imagePath);
225+
using Image<Argb32> formatArgb32 = Image.Load<Argb32>(imagePath);
226+
using Image<Bgr24> formatBgr24 = Image.Load<Bgr24>(imagePath);
227+
using Image<Bgra32> formatBgra32 = Image.Load<Bgra32>(imagePath);
228+
229+
Image[] images = { formatRgb24, formatAbgr32, formatArgb32, formatBgr24, formatBgra32 };
230+
231+
foreach (Image image in images)
232+
{
233+
AnyBitmap bitmap = (AnyBitmap)image;
234+
235+
// Get the current pixel color - should be white
236+
var pixelBefore = bitmap.GetPixel(0, 0);
237+
238+
// Check current pixel color is not black
239+
Assert.NotEqual(pixelBefore, Color.Black);
240+
241+
// Set the pixel color to black
242+
bitmap.SetPixel(0, 0, Color.Black);
243+
244+
// Check the pixel color has changed
245+
Assert.Equal(bitmap.GetPixel(0, 0), Color.Black);
246+
}
247+
}
248+
218249
[FactWithAutomaticDisplayName]
219250
public void AnyBitmap_should_get_Stream()
220251
{
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
using FluentAssertions;
2+
using System.Runtime.InteropServices;
3+
using Xunit.Abstractions;
4+
5+
namespace IronSoftware.Drawing.Common.Tests.UnitTests
6+
{
7+
public class PointFunctionality : TestsBase
8+
{
9+
public PointFunctionality(ITestOutputHelper output) : base(output)
10+
{
11+
}
12+
13+
[FactWithAutomaticDisplayName]
14+
public void Create_new_Point()
15+
{
16+
int constructorX = 0;
17+
int constructorY = 0;
18+
Point pt = new Point(constructorX, constructorY);
19+
_ = pt.X.Should().Be(constructorX);
20+
_ = pt.Y.Should().Be(constructorY);
21+
_ = pt.Should().BeEquivalentTo(new Point(constructorX, constructorY));
22+
23+
constructorX = 20;
24+
constructorY = 5;
25+
pt = new Point(constructorX, constructorY);
26+
_ = pt.X.Should().Be(constructorX);
27+
_ = pt.Y.Should().Be(constructorY);
28+
_ = pt.Should().BeEquivalentTo(new Point(constructorX, constructorY));
29+
30+
constructorX = 20;
31+
constructorY = 5;
32+
int xTranslation = 10;
33+
int yTranslation = -10;
34+
pt = new Point(constructorX, constructorY);
35+
pt.Offset(xTranslation, yTranslation);
36+
_ = pt.X.Should().Be(constructorX + xTranslation);
37+
_ = pt.Y.Should().Be(constructorY + yTranslation);
38+
_ = pt.Should().NotBeEquivalentTo(new Point(constructorX, constructorY));
39+
_ = pt.Should().BeEquivalentTo(new Point(constructorX + xTranslation, constructorY + yTranslation));
40+
}
41+
42+
[FactWithAutomaticDisplayName]
43+
public void Compare_Point_Equals()
44+
{
45+
int constructorX = 0;
46+
int constructorY = 0;
47+
Point pt1 = new Point(constructorX, constructorY);
48+
Point pt2 = new Point(constructorX, constructorY);
49+
pt1.Equals(pt2).Should().BeTrue();
50+
pt2.Equals(pt1).Should().BeTrue();
51+
52+
constructorX = 20;
53+
constructorY = 5;
54+
pt1 = new Point(constructorX, constructorY);
55+
pt2 = new Point(constructorX, constructorY);
56+
pt1.Equals(pt2).Should().BeTrue();
57+
pt2.Equals(pt1).Should().BeTrue();
58+
59+
int a = 5;
60+
int b = -20;
61+
pt1 = new Point(a, b);
62+
pt2 = new Point(b, a);
63+
pt1.Equals(pt2).Should().BeFalse();
64+
pt2.Equals(pt1).Should().BeFalse();
65+
}
66+
67+
68+
[FactWithAutomaticDisplayName]
69+
public void Create_new_PointF()
70+
{
71+
float constructorX = 0f;
72+
float constructorY = 0f;
73+
PointF pt = new PointF(constructorX, constructorY);
74+
_ = pt.X.Should().Be(constructorX);
75+
_ = pt.Y.Should().Be(constructorY);
76+
_ = pt.Should().BeEquivalentTo(new PointF(constructorX, constructorY));
77+
78+
constructorX = 20f;
79+
constructorY = 5f;
80+
pt = new PointF(constructorX, constructorY);
81+
_ = pt.X.Should().Be(constructorX);
82+
_ = pt.Y.Should().Be(constructorY);
83+
_ = pt.Should().BeEquivalentTo(new PointF(constructorX, constructorY));
84+
85+
constructorX = 20.5f;
86+
constructorY = 5.33f;
87+
float xTranslation = 10.88f;
88+
float yTranslation = -10.32f;
89+
pt = new PointF(constructorX, constructorY);
90+
pt.Offset(xTranslation, yTranslation);
91+
_ = pt.X.Should().Be(constructorX + xTranslation);
92+
_ = pt.Y.Should().Be(constructorY + yTranslation);
93+
_ = pt.Should().NotBeEquivalentTo(new PointF(constructorX, constructorY));
94+
_ = pt.Should().BeEquivalentTo(new PointF(constructorX + xTranslation, constructorY + yTranslation));
95+
}
96+
97+
98+
[FactWithAutomaticDisplayName]
99+
public void Compare_PointF_Equals()
100+
{
101+
float constructorX = 0.0f;
102+
float constructorY = 0.0f;
103+
PointF pt1 = new PointF(constructorX, constructorY);
104+
PointF pt2 = new PointF(constructorX, constructorY);
105+
pt1.Equals(pt2).Should().BeTrue();
106+
pt2.Equals(pt1).Should().BeTrue();
107+
108+
constructorX = 20.5f;
109+
constructorY = 5.5f;
110+
pt1 = new PointF(constructorX, constructorY);
111+
pt2 = new PointF(constructorX, constructorY);
112+
pt1.Equals(pt2).Should().BeTrue();
113+
pt2.Equals(pt1).Should().BeTrue();
114+
115+
float a = 5.5f;
116+
float b = -20.5f;
117+
pt1 = new PointF(a, b);
118+
pt2 = new PointF(b, a);
119+
pt1.Equals(pt2).Should().BeFalse();
120+
pt2.Equals(pt1).Should().BeFalse();
121+
}
122+
}
123+
}

IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,32 @@ public Color GetPixel(int x, int y)
10091009
return GetPixelColor(x, y);
10101010
}
10111011

1012+
/// <summary>
1013+
/// Sets the <see cref="Color"/> of the specified pixel in this
1014+
/// <see cref="AnyBitmap"/>
1015+
/// <para>Set in Rgb24 color format.</para>
1016+
/// </summary>
1017+
/// <param name="x">The x-coordinate of the pixel to retrieve.</param>
1018+
/// <param name="y">The y-coordinate of the pixel to retrieve.</param>
1019+
/// <param name="color">The color to set the pixel.</param>
1020+
/// <returns>void</returns>
1021+
public void SetPixel(int x, int y, Color color)
1022+
{
1023+
if (x < 0 || x >= Width)
1024+
{
1025+
throw new ArgumentOutOfRangeException(nameof(x),
1026+
"x is less than 0, or greater than or equal to Width.");
1027+
}
1028+
1029+
if (y < 0 || y >= Height)
1030+
{
1031+
throw new ArgumentOutOfRangeException(nameof(y),
1032+
"y is less than 0, or greater than or equal to Height.");
1033+
}
1034+
1035+
SetPixelColor(x, y, color);
1036+
}
1037+
10121038
/// <summary>
10131039
/// Retrieves the RGB buffer from the image at the specified path.
10141040
/// </summary>
@@ -1652,10 +1678,12 @@ public enum ImageFormat
16521678
Default = -1
16531679

16541680
}
1655-
1681+
# pragma warning disable CS0618
16561682
/// <summary>
16571683
/// Converts the legacy <see cref="RotateFlipType"/> to <see cref="RotateMode"/> and <see cref="FlipMode"/>
16581684
/// </summary>
1685+
[Obsolete("RotateFlipType is legacy support from System.Drawing. " +
1686+
"Please use RotateMode and FlipMode instead.")]
16591687
internal static (RotateMode, FlipMode) ParseRotateFlipType(RotateFlipType rotateFlipType)
16601688
{
16611689
return rotateFlipType switch
@@ -1671,6 +1699,7 @@ internal static (RotateMode, FlipMode) ParseRotateFlipType(RotateFlipType rotate
16711699
_ => throw new ArgumentOutOfRangeException(nameof(rotateFlipType), rotateFlipType, null),
16721700
};
16731701
}
1702+
# pragma warning restore CS0618
16741703

16751704
/// <summary>
16761705
/// Provides enumeration over how the image should be rotated.
@@ -2392,6 +2421,31 @@ private Color GetPixelColor(int x, int y)
23922421
}
23932422
}
23942423

2424+
private void SetPixelColor(int x, int y, Color color)
2425+
{
2426+
switch (Image)
2427+
{
2428+
case Image<Rgb24> imageAsFormat:
2429+
imageAsFormat[x, y] = color;
2430+
break;
2431+
case Image<Abgr32> imageAsFormat:
2432+
imageAsFormat[x, y] = color;
2433+
break;
2434+
case Image<Argb32> imageAsFormat:
2435+
imageAsFormat[x, y] = color;
2436+
break;
2437+
case Image<Bgr24> imageAsFormat:
2438+
imageAsFormat[x, y] = color;
2439+
break;
2440+
case Image<Bgra32> imageAsFormat:
2441+
imageAsFormat[x, y] = color;
2442+
break;
2443+
default:
2444+
(Image as Image<Rgba32>)[x, y] = color;
2445+
break;
2446+
}
2447+
}
2448+
23952449
private void LoadAndResizeImage(AnyBitmap original, int width, int height)
23962450
{
23972451
#if NET6_0_OR_GREATER
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
using System;
2+
3+
namespace IronSoftware.Drawing
4+
{
5+
/// <summary>
6+
/// Represents an ordered pair of double x- and y-coordinates that defines a point in a two-dimensional plane.
7+
/// </summary>
8+
public partial class Point
9+
{
10+
/// <summary>
11+
/// Gets or sets the x-coordinate of this <see cref="IronSoftware.Drawing.Point"/>.
12+
/// </summary>
13+
public double X { get; set; } = 0;
14+
15+
/// <summary>
16+
/// Gets or sets the y-coordinate of this <see cref="IronSoftware.Drawing.Point"/>.
17+
/// </summary>
18+
public double Y { get; set; } = 0;
19+
/// <summary>
20+
/// Initializes a new instance of the <see cref="IronSoftware.Drawing.Point"/> struct with the specified coordinates.
21+
/// </summary>
22+
/// <param name="x"></param>
23+
/// <param name="y"></param>
24+
public Point(double x, double y)
25+
{
26+
X = x;
27+
Y = y;
28+
}
29+
30+
/// <summary>
31+
/// Translates this <see cref="IronSoftware.Drawing.Point"/> by the specified amount.
32+
/// </summary>
33+
/// <param name="dx">The amount to offset the x-coordinate.</param>
34+
/// <param name="dy">The amount to offset the y-coordinate.</param>
35+
public void Offset(double dx, double dy)
36+
{
37+
X += dx;
38+
Y += dy;
39+
}
40+
41+
#region Implicit Operators
42+
43+
/// <summary>
44+
/// Implicitly casts SixLabors.ImageSharp.Point objects to Point
45+
/// </summary>
46+
/// <param name="point">System.Drawing.Point will automatically be cast to <see cref="Point"/> </param>
47+
public static implicit operator Point(SixLabors.ImageSharp.Point point)
48+
{
49+
return new Point(point.X, point.Y);
50+
}
51+
52+
/// <summary>
53+
/// Implicitly casts Point objects to SixLabors.ImageSharp.Point
54+
/// </summary>
55+
/// <remarks>SixLabors.ImageSharp.Point only uses int instead of double for X and Y. Decimals will be removed.</remarks>
56+
/// <param name="point">Point will automatically be cast to SixLabors.ImageSharp.Point</param>
57+
public static implicit operator SixLabors.ImageSharp.Point(Point point)
58+
{
59+
return new SixLabors.ImageSharp.Point((int)point.X, (int)point.Y);
60+
}
61+
62+
/// <summary>
63+
/// Implicitly casts System.Drawing.Point objects to <see cref="Point"/>.
64+
/// </summary>
65+
/// <param name="point">System.Drawing.Point will automatically be cast to <see cref="Point"/> </param>
66+
public static implicit operator Point(System.Drawing.Point point)
67+
{
68+
return new Point(point.X, point.Y);
69+
}
70+
71+
/// <summary>
72+
/// Implicitly casts Point objects to System.Drawing.Point
73+
/// </summary>
74+
/// <remarks>System.Drawing.Point only uses int instead of double for X and Y. Decimals will be removed.</remarks>
75+
/// <param name="point">Point will automatically be cast to System.Drawing.Point</param>
76+
public static implicit operator System.Drawing.Point(Point point)
77+
{
78+
return new System.Drawing.Point((int)point.X, (int)point.Y);
79+
}
80+
81+
/// <summary>
82+
/// Implicitly casts Microsoft.Maui.Graphics.Point objects to <see cref="Point"/>.
83+
/// </summary>
84+
/// <param name="point">Microsoft.Maui.Graphics.Point will automatically be cast to <see cref="Point"/> </param>
85+
public static implicit operator Point(Microsoft.Maui.Graphics.Point point)
86+
{
87+
return new Point(point.X, point.Y);
88+
}
89+
90+
/// <summary>
91+
/// Implicitly casts Point objects to Microsoft.Maui.Graphics.Point
92+
/// </summary>
93+
/// <param name="point">Point will automatically be cast to Microsoft.Maui.Graphics.Point</param>
94+
public static implicit operator Microsoft.Maui.Graphics.Point(Point point)
95+
{
96+
return new Microsoft.Maui.Graphics.Point(point.X, point.Y);
97+
}
98+
99+
/// <summary>
100+
/// Implicitly casts SkiaSharp.SKPointI objects to <see cref="Point"/>.
101+
/// </summary>
102+
/// <param name="point">SkiaSharp.SKPointI will automatically be cast to <see cref="Point"/> </param>
103+
public static implicit operator Point(SkiaSharp.SKPointI point)
104+
{
105+
return new Point(point.X, point.Y);
106+
}
107+
108+
/// <summary>
109+
/// Implicitly casts Point objects to SkiaSharp.SKPointI
110+
/// </summary>
111+
/// <remarks>SkiaSharp.SKPointI only uses int instead of double for X and Y. Decimals will be removed.</remarks>
112+
/// <param name="point">Point will automatically be cast to SkiaSharp.SKPointI</param>
113+
public static implicit operator SkiaSharp.SKPointI(Point point)
114+
{
115+
return new SkiaSharp.SKPointI((int)point.X, (int)point.Y);
116+
}
117+
118+
#endregion
119+
120+
#region Override Methods
121+
/// <summary>
122+
/// Specifies whether this <see cref="IronSoftware.Drawing.Point"/> instance contains the same coordinates as another <see cref="IronSoftware.Drawing.Point"/>.
123+
/// </summary>
124+
/// <param name="obj">The point to test for equality.</param>
125+
/// <returns>true if other has the same coordinates as this point instance.</returns>
126+
public override bool Equals(object obj)
127+
{
128+
Point otherPoint;
129+
try
130+
{
131+
otherPoint = obj as Point;
132+
}
133+
catch
134+
{
135+
return false;
136+
}
137+
return (this.X == otherPoint.X && this.Y == otherPoint.Y);
138+
}
139+
140+
/// <summary>
141+
/// Hashing integer based on image raw binary data.
142+
/// </summary>
143+
/// <returns>Int</returns>
144+
public override int GetHashCode()
145+
{
146+
return base.GetHashCode();
147+
}
148+
#endregion
149+
}
150+
}

0 commit comments

Comments
 (0)