Browse Source

Merge branch 'main' into dp/jpeg-benchmark

pull/2051/head
James Jackson-South 4 years ago
committed by GitHub
parent
commit
8481a3ab6f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/ImageSharp/ImageFrame{TPixel}.cs
  2. 2
      src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.String.cs
  3. 4
      src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/RgbaVector.PixelOperations.cs
  4. 24
      src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
  5. 5
      tests/ImageSharp.Tests.ruleset
  6. 61
      tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs
  7. 16
      tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs
  8. 18
      tests/ImageSharp.Tests/TestUtilities/TestPixel.cs

6
src/ImageSharp/ImageFrame{TPixel}.cs

@ -362,10 +362,8 @@ namespace SixLabors.ImageSharp
return; return;
} }
this.PixelBuffer.FastMemoryGroup.TransformTo(destination, (s, d) => this.PixelBuffer.FastMemoryGroup.TransformTo(destination, (s, d)
{ => PixelOperations<TPixel>.Instance.To(this.GetConfiguration(), s, d));
PixelOperations<TPixel>.Instance.To(this.GetConfiguration(), s, d);
});
} }
/// <inheritdoc/> /// <inheritdoc/>

2
src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.String.cs

@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
/// <summary> /// <summary>
/// Gets the MDFileUnits exif tag. /// Gets the MDFileUnits exif tag.
/// </summary> /// </summary>
public static ExifTag<string> MDFileUnits => new ExifTag<string>(ExifTagValue.MDFileUnits); public static ExifTag<string> MDFileUnits { get; } = new ExifTag<string>(ExifTagValue.MDFileUnits);
/// <summary> /// <summary>
/// Gets the SEMInfo exif tag. /// Gets the SEMInfo exif tag.

4
src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/RgbaVector.PixelOperations.cs

@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.PixelFormats
internal class PixelOperations : PixelOperations<RgbaVector> internal class PixelOperations : PixelOperations<RgbaVector>
{ {
private static readonly Lazy<PixelTypeInfo> LazyInfo = private static readonly Lazy<PixelTypeInfo> LazyInfo =
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<RgbaVector>(PixelAlphaRepresentation.Unassociated), true); new(() => PixelTypeInfo.Create<RgbaVector>(PixelAlphaRepresentation.Unassociated), true);
/// <inheritdoc /> /// <inheritdoc />
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value;
@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{ {
Span<Vector4> destinationVectors = MemoryMarshal.Cast<RgbaVector, Vector4>(destinationPixels); 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 /> /// <inheritdoc />

24
src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs

@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.PixelFormats
public partial class PixelOperations<TPixel> public partial class PixelOperations<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
private static readonly Lazy<PixelTypeInfo> LazyInfo = new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<TPixel>(), true); private static readonly Lazy<PixelTypeInfo> LazyInfo = new(() => PixelTypeInfo.Create<TPixel>(), true);
/// <summary> /// <summary>
/// Gets the global <see cref="PixelOperations{TPixel}"/> instance for the pixel type <typeparamref name="TPixel"/> /// Gets the global <see cref="PixelOperations{TPixel}"/> instance for the pixel type <typeparamref name="TPixel"/>
@ -116,29 +116,29 @@ namespace SixLabors.ImageSharp.PixelFormats
Span<TPixel> destinationPixels) Span<TPixel> destinationPixels)
where TSourcePixel : unmanaged, IPixel<TSourcePixel> where TSourcePixel : unmanaged, IPixel<TSourcePixel>
{ {
const int SliceLength = 1024; const int sliceLength = 1024;
int numberOfSlices = sourcePixels.Length / SliceLength; int numberOfSlices = sourcePixels.Length / sliceLength;
using IMemoryOwner<Vector4> tempVectors = configuration.MemoryAllocator.Allocate<Vector4>(SliceLength); using IMemoryOwner<Vector4> tempVectors = configuration.MemoryAllocator.Allocate<Vector4>(sliceLength);
Span<Vector4> vectorSpan = tempVectors.GetSpan(); Span<Vector4> vectorSpan = tempVectors.GetSpan();
for (int i = 0; i < numberOfSlices; i++) for (int i = 0; i < numberOfSlices; i++)
{ {
int start = i * SliceLength; int start = i * sliceLength;
ReadOnlySpan<TSourcePixel> s = sourcePixels.Slice(start, SliceLength); ReadOnlySpan<TSourcePixel> s = sourcePixels.Slice(start, sliceLength);
Span<TPixel> d = destinationPixels.Slice(start, SliceLength); Span<TPixel> d = destinationPixels.Slice(start, sliceLength);
PixelOperations<TSourcePixel>.Instance.ToVector4(configuration, s, vectorSpan); PixelOperations<TSourcePixel>.Instance.ToVector4(configuration, s, vectorSpan, PixelConversionModifiers.Scale);
this.FromVector4Destructive(configuration, vectorSpan, d); this.FromVector4Destructive(configuration, vectorSpan, d, PixelConversionModifiers.Scale);
} }
int endOfCompleteSlices = numberOfSlices * SliceLength; int endOfCompleteSlices = numberOfSlices * sliceLength;
int remainder = sourcePixels.Length - endOfCompleteSlices; int remainder = sourcePixels.Length - endOfCompleteSlices;
if (remainder > 0) if (remainder > 0)
{ {
ReadOnlySpan<TSourcePixel> s = sourcePixels.Slice(endOfCompleteSlices); ReadOnlySpan<TSourcePixel> s = sourcePixels.Slice(endOfCompleteSlices);
Span<TPixel> d = destinationPixels.Slice(endOfCompleteSlices); Span<TPixel> d = destinationPixels.Slice(endOfCompleteSlices);
vectorSpan = vectorSpan.Slice(0, remainder); vectorSpan = vectorSpan.Slice(0, remainder);
PixelOperations<TSourcePixel>.Instance.ToVector4(configuration, s, vectorSpan); PixelOperations<TSourcePixel>.Instance.ToVector4(configuration, s, vectorSpan, PixelConversionModifiers.Scale);
this.FromVector4Destructive(configuration, vectorSpan, d); this.FromVector4Destructive(configuration, vectorSpan, d, PixelConversionModifiers.Scale);
} }
} }

5
tests/ImageSharp.Tests.ruleset

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?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" /> <Include Path="..\shared-infrastructure\sixlabors.tests.ruleset" Action="Default" />
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1313" Action="None" />
</Rules>
<Rules AnalyzerId="xunit.analyzers" RuleNamespace="xunit.analyzers"> <Rules AnalyzerId="xunit.analyzers" RuleNamespace="xunit.analyzers">
<Rule Id="xUnit1004" Action="None" /> <Rule Id="xUnit1004" Action="None" />
<Rule Id="xUnit1013" Action="None" /> <Rule Id="xUnit1013" Action="None" />

61
tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs

@ -320,30 +320,51 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations
(s, d) => this.Operations.ToVector4(this.Configuration, s, d.GetSpan())); (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<Abgr32>(),
new TestPixel<Rgba32>(), new TestPixel<Argb32>(),
new TestPixel<Bgr24>(),
new TestPixel<Bgr565>(),
new TestPixel<Bgra32>(), new TestPixel<Bgra32>(),
new TestPixel<Rgb24>(), new TestPixel<Bgra4444>(),
new TestPixel<L8>(), new TestPixel<Bgra5551>(),
new TestPixel<Byte4>(),
new TestPixel<HalfSingle>(),
new TestPixel<HalfVector2>(),
new TestPixel<HalfVector4>(),
new TestPixel<L16>(), 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<Rgb48>(),
new TestPixel<Rgba64>() new TestPixel<Rgba1010102>(),
new TestPixel<Rgba32>(),
new TestPixel<Rgba64>(),
new TestPixel<RgbaVector>(),
new TestPixel<Short2>(),
new TestPixel<Short4>(),
}; };
[Theory] [Theory]
[MemberData(nameof(Generic_To_Data))] [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> where TDestPixel : unmanaged, IPixel<TDestPixel>
{ {
const int Count = 2134; const int count = 2134;
TPixel[] source = CreatePixelTestData(Count); TPixel[] source = CreatePixelTestData(count);
var expected = new TDestPixel[Count]; var expected = new TDestPixel[count];
PixelConverterTests.ReferenceImplementations.To<TPixel, TDestPixel>(this.Configuration, source, expected); 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);
} }
[Theory] [Theory]
@ -1234,23 +1255,11 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations
} }
// TODO: We really need a PixelTypeInfo.BitsPerComponent property!! // TODO: We really need a PixelTypeInfo.BitsPerComponent property!!
private static bool IsComplexPixel() private static bool IsComplexPixel() => default(TDest) switch
{ {
switch (default(TDest)) HalfSingle or HalfVector2 or L16 or La32 or NormalizedShort2 or Rg32 or Short2 => true,
{ _ => Unsafe.SizeOf<TDest>() > sizeof(int),
case HalfSingle _: };
case HalfVector2 _:
case L16 _:
case La32 _:
case NormalizedShort2 _:
case Rg32 _:
case Short2 _:
return true;
default:
return Unsafe.SizeOf<TDest>() > sizeof(int);
}
}
} }
} }
} }

16
tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs

@ -189,5 +189,21 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
// assert // assert
Assert.Equal(expected, rgba.ToScaledVector4()); Assert.Equal(expected, rgba.ToScaledVector4());
} }
[Fact]
public void Issue2048()
{
// https://github.com/SixLabors/ImageSharp/issues/2048
RgbaVector green = Color.Green.ToPixel<RgbaVector>();
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);
}
} }
} }

18
tests/ImageSharp.Tests/TestUtilities/TestPixel.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using Xunit.Abstractions; using Xunit.Abstractions;
@ -16,6 +17,11 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities
public TestPixel(float red, float green, float blue, float alpha) public TestPixel(float red, float green, float blue, float alpha)
{ {
Guard.MustBeBetweenOrEqualTo(red, 0F, 1F, nameof(red));
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.Red = red;
this.Green = green; this.Green = green;
this.Blue = blue; this.Blue = blue;
@ -33,14 +39,11 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities
public TPixel AsPixel() public TPixel AsPixel()
{ {
var pix = default(TPixel); 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));
return pix; return pix;
} }
internal Span<TPixel> AsSpan() internal Span<TPixel> AsSpan() => new(new[] { this.AsPixel() });
{
return new Span<TPixel>(new[] { this.AsPixel() });
}
public void Deserialize(IXunitSerializationInfo info) public void Deserialize(IXunitSerializationInfo info)
{ {
@ -58,9 +61,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities
info.AddValue("alpha", this.Alpha); info.AddValue("alpha", this.Alpha);
} }
public override string ToString() public override string ToString() => $"{typeof(TPixel).Name}{this.AsPixel()}";
{
return $"{typeof(TPixel).Name}{this.AsPixel().ToString()}";
}
} }
} }

Loading…
Cancel
Save