-
-
Notifications
You must be signed in to change notification settings - Fork 854
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
Ensure PixelOperations.To(TPixel) uses scaling. #2050
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,7 @@ public partial struct RgbaVector | |
internal class PixelOperations : PixelOperations<RgbaVector> | ||
{ | ||
private static readonly Lazy<PixelTypeInfo> LazyInfo = | ||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<RgbaVector>(PixelAlphaRepresentation.Unassociated), true); | ||
new(() => PixelTypeInfo.Create<RgbaVector>(PixelAlphaRepresentation.Unassociated), true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have to say I am not a fan of this syntax for object creation... I find it a lot harder to read. especially in cases like this: // in some piece of unchanged code
var list = new List<ObjType>();
.
.
.
// lots of lines later
.
.
.
// in the middle of a PR change block, there is no context available while review what the hell this thing is.
list.Add(new(arg1, "arg2", 34)
{
OptionalProperty = bar
}); not going to block any PRs etc over this just wanted to comment on the fact I feel it drastically harms readability in most cases... the only exception I can kind of agree on is property initialization where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, definitely something to be aware of. I really like it in some scenarios though |
||
|
||
/// <inheritdoc /> | ||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; | ||
|
@@ -34,7 +34,7 @@ public override void From<TSourcePixel>( | |
{ | ||
Span<Vector4> destinationVectors = MemoryMarshal.Cast<RgbaVector, Vector4>(destinationPixels); | ||
|
||
PixelOperations<TSourcePixel>.Instance.ToVector4(configuration, sourcePixels, destinationVectors); | ||
PixelOperations<TSourcePixel>.Instance.ToVector4(configuration, sourcePixels, destinationVectors, PixelConversionModifiers.Scale); | ||
} | ||
|
||
/// <inheritdoc /> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<RuleSet Name="ImageSharp.Tests" ToolsVersion="16.0"> | ||
<RuleSet Name="ImageSharp.Tests" ToolsVersion="17.0"> | ||
<Include Path="..\shared-infrastructure\sixlabors.tests.ruleset" Action="Default" /> | ||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers"> | ||
<Rule Id="SA1313" Action="None" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allows us to replace "dummy" with discard "_" |
||
</Rules> | ||
<Rules AnalyzerId="xunit.analyzers" RuleNamespace="xunit.analyzers"> | ||
<Rule Id="xUnit1004" Action="None" /> | ||
<Rule Id="xUnit1013" Action="None" /> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -320,30 +320,51 @@ public void ToVector4(int count) | |
(s, d) => this.Operations.ToVector4(this.Configuration, s, d.GetSpan())); | ||
} | ||
|
||
public static readonly TheoryData<object> Generic_To_Data = new TheoryData<object> | ||
public static readonly TheoryData<object> Generic_To_Data = new() | ||
{ | ||
new TestPixel<A8>(), | ||
new TestPixel<Abgr32>(), | ||
new TestPixel<Rgba32>(), | ||
new TestPixel<Argb32>(), | ||
new TestPixel<Bgr24>(), | ||
new TestPixel<Bgr565>(), | ||
new TestPixel<Bgra32>(), | ||
new TestPixel<Rgb24>(), | ||
new TestPixel<L8>(), | ||
new TestPixel<Bgra4444>(), | ||
new TestPixel<Bgra5551>(), | ||
new TestPixel<Byte4>(), | ||
new TestPixel<HalfSingle>(), | ||
new TestPixel<HalfVector2>(), | ||
new TestPixel<HalfVector4>(), | ||
new TestPixel<L16>(), | ||
new TestPixel<L8>(), | ||
new TestPixel<La16>(), | ||
new TestPixel<La32>(), | ||
new TestPixel<NormalizedByte2>(), | ||
new TestPixel<NormalizedByte4>(), | ||
new TestPixel<NormalizedShort2>(), | ||
new TestPixel<NormalizedShort4>(), | ||
new TestPixel<Rg32>(), | ||
new TestPixel<Rgb24>(), | ||
new TestPixel<Rgb48>(), | ||
new TestPixel<Rgba64>() | ||
new TestPixel<Rgba1010102>(), | ||
new TestPixel<Rgba32>(), | ||
new TestPixel<Rgba64>(), | ||
new TestPixel<RgbaVector>(), | ||
new TestPixel<Short2>(), | ||
new TestPixel<Short4>(), | ||
}; | ||
|
||
[Theory] | ||
[MemberData(nameof(Generic_To_Data))] | ||
public void Generic_To<TDestPixel>(TestPixel<TDestPixel> dummy) | ||
public void Generic_To<TDestPixel>(TestPixel<TDestPixel> _) | ||
where TDestPixel : unmanaged, IPixel<TDestPixel> | ||
{ | ||
const int Count = 2134; | ||
TPixel[] source = CreatePixelTestData(Count); | ||
var expected = new TDestPixel[Count]; | ||
const int count = 2134; | ||
TPixel[] source = CreatePixelTestData(count); | ||
var expected = new TDestPixel[count]; | ||
|
||
PixelConverterTests.ReferenceImplementations.To<TPixel, TDestPixel>(this.Configuration, source, expected); | ||
|
||
TestOperation(source, expected, (s, d) => this.Operations.To(this.Configuration, s, d.GetSpan())); | ||
TestOperation(source, expected, (s, d) => this.Operations.To(this.Configuration, s, d.GetSpan()), false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need approximate comparison here now we've added all the types. Comparison is still very accurate. |
||
} | ||
|
||
[Theory] | ||
|
@@ -1234,23 +1255,11 @@ public void Verify() | |
} | ||
|
||
// TODO: We really need a PixelTypeInfo.BitsPerComponent property!! | ||
private static bool IsComplexPixel() | ||
private static bool IsComplexPixel() => default(TDest) switch | ||
{ | ||
switch (default(TDest)) | ||
{ | ||
case HalfSingle _: | ||
case HalfVector2 _: | ||
case L16 _: | ||
case La32 _: | ||
case NormalizedShort2 _: | ||
case Rg32 _: | ||
case Short2 _: | ||
return true; | ||
|
||
default: | ||
return Unsafe.SizeOf<TDest>() > sizeof(int); | ||
} | ||
} | ||
HalfSingle or HalfVector2 or L16 or La32 or NormalizedShort2 or Rg32 or Short2 => true, | ||
_ => Unsafe.SizeOf<TDest>() > sizeof(int), | ||
}; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -189,5 +189,21 @@ public void RgbaVector_FromGrey8() | |
// assert | ||
Assert.Equal(expected, rgba.ToScaledVector4()); | ||
} | ||
|
||
[Fact] | ||
public void Issue2048() | ||
{ | ||
// https://github.com/SixLabors/ImageSharp/issues/2048 | ||
RgbaVector green = Color.Green.ToPixel<RgbaVector>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually covered in the |
||
using Image<RgbaVector> source = new(Configuration.Default, 1, 1, green); | ||
using Image<HalfVector4> clone = source.CloneAs<HalfVector4>(); | ||
|
||
Rgba32 srcColor = default; | ||
Rgba32 cloneColor = default; | ||
source[0, 0].ToRgba32(ref srcColor); | ||
clone[0, 0].ToRgba32(ref cloneColor); | ||
|
||
Assert.Equal(srcColor, cloneColor); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
// Licensed under the Apache License, Version 2.0. | ||
|
||
using System; | ||
using System.Numerics; | ||
using SixLabors.ImageSharp.PixelFormats; | ||
using Xunit.Abstractions; | ||
|
||
|
@@ -16,6 +17,11 @@ public TestPixel() | |
|
||
public TestPixel(float red, float green, float blue, float alpha) | ||
{ | ||
Guard.MustBeBetweenOrEqualTo(red, 0F, 1F, nameof(red)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was unbounded when it shouldn't be. |
||
Guard.MustBeBetweenOrEqualTo(green, 0F, 1F, nameof(green)); | ||
Guard.MustBeBetweenOrEqualTo(blue, 0F, 1F, nameof(blue)); | ||
Guard.MustBeBetweenOrEqualTo(alpha, 0F, 1F, nameof(alpha)); | ||
|
||
this.Red = red; | ||
this.Green = green; | ||
this.Blue = blue; | ||
|
@@ -33,14 +39,11 @@ public TestPixel(float red, float green, float blue, float alpha) | |
public TPixel AsPixel() | ||
{ | ||
var pix = default(TPixel); | ||
pix.FromVector4(new System.Numerics.Vector4(this.Red, this.Green, this.Blue, this.Alpha)); | ||
pix.FromScaledVector4(new Vector4(this.Red, this.Green, this.Blue, this.Alpha)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best to be explicit despite guard. |
||
return pix; | ||
} | ||
|
||
internal Span<TPixel> AsSpan() | ||
{ | ||
return new Span<TPixel>(new[] { this.AsPixel() }); | ||
} | ||
internal Span<TPixel> AsSpan() => new(new[] { this.AsPixel() }); | ||
|
||
public void Deserialize(IXunitSerializationInfo info) | ||
{ | ||
|
@@ -58,9 +61,6 @@ public void Serialize(IXunitSerializationInfo info) | |
info.AddValue("alpha", this.Alpha); | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return $"{typeof(TPixel).Name}{this.AsPixel().ToString()}"; | ||
} | ||
public override string ToString() => $"{typeof(TPixel).Name}{this.AsPixel()}"; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed this by accident but it was something I found the other day when looking at the EXIF tags.