diff --git a/.gitattributes b/.gitattributes
index 195506770..163f9ddfe 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -64,13 +64,20 @@
# treat as binary
*.bmp binary
*.dll binary
+*.eot binary
*.exe binary
*.gif binary
*.jpg binary
+*.pdf binary
*.png binary
-*.tga binary
+*.ppt binary
+*.pptx binary
*.ttf binary
*.snk binary
+*.woff binary
+*.woff2 binary
+*.xls binary
+*.xlsx binary
# diff as plain text
*.doc diff=astextplain
*.docx diff=astextplain
@@ -78,6 +85,7 @@
*.pdf diff=astextplain
*.pptx diff=astextplain
*.rtf diff=astextplain
+*.svg diff=astextplain
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.bmp filter=lfs diff=lfs merge=lfs -text
diff --git a/Directory.Build.props b/Directory.Build.props
index e865a83f8..95cadcd57 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -29,10 +29,42 @@
true
+
+
+
+
+ $(DefineConstants);SUPPORTS_MATHF;SUPPORTS_HASHCODE;SUPPORTS_EXTENDED_INTRINSICS;SUPPORTS_SPAN_STREAM;SUPPORTS_ENCODING_STRING
+
+
+ $(DefineConstants);SUPPORTS_MATHF;SUPPORTS_HASHCODE;SUPPORTS_EXTENDED_INTRINSICS;SUPPORTS_SPAN_STREAM;SUPPORTS_ENCODING_STRING
+
+
+ $(DefineConstants);SUPPORTS_MATHF;
+
+
+ $(DefineConstants);SUPPORTS_MATHF;SUPPORTS_SPAN_STREAM;SUPPORTS_ENCODING_STRING
+
+
+ $(DefineConstants);SUPPORTS_EXTENDED_INTRINSICS
+
+
true
-
+
false
diff --git a/shared-infrastructure b/shared-infrastructure
index faf84e44e..c2e689abe 160000
--- a/shared-infrastructure
+++ b/shared-infrastructure
@@ -1 +1 @@
-Subproject commit faf84e44ec90e8a42a7271bcd04fea76279efb08
+Subproject commit c2e689abe9227209e6d5bc4bf56255d92b4a5d62
diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
index 5a53d3e78..c4e3224bb 100644
--- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
+++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
@@ -8,18 +8,10 @@
SixLabors.ImageSharp.Drawing
Image Draw Shape Path Font
SixLabors.ImageSharp
- netcoreapp2.1;netstandard1.3;netstandard2.0
-
-
-
- $(DefineConstants);SUPPORTS_MATHF
+ netcoreapp2.1;netstandard2.0;netstandard1.3
-
- $(DefineConstants);SUPPORTS_HASHCODE
-
-
diff --git a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs
index a9df07ced..058c6d0eb 100644
--- a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs
+++ b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs
@@ -90,19 +90,23 @@ namespace SixLabors.ImageSharp.Processing
{
Span amountSpan = amountBuffer.Memory.Span;
Span overlaySpan = overlay.Memory.Span;
+ float blendPercentage = this.Options.BlendPercentage;
- for (int i = 0; i < scanline.Length; i++)
+ if (blendPercentage < 1)
{
- if (this.Options.BlendPercentage < 1)
+ for (int i = 0; i < scanline.Length; i++)
{
- amountSpan[i] = scanline[i] * this.Options.BlendPercentage;
+ amountSpan[i] = scanline[i] * blendPercentage;
+ overlaySpan[i] = this[x + i, y];
}
- else
+ }
+ else
+ {
+ for (int i = 0; i < scanline.Length; i++)
{
amountSpan[i] = scanline[i];
+ overlaySpan[i] = this[x + i, y];
}
-
- overlaySpan[i] = this[x + i, y];
}
Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
diff --git a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs
index 9e354120e..126567899 100644
--- a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs
+++ b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs
@@ -2,11 +2,13 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.Memory;
using SixLabors.Primitives;
using SixLabors.Shapes;
@@ -47,7 +49,7 @@ namespace SixLabors.ImageSharp.Processing
throw new ArgumentNullException(nameof(colors));
}
- if (!colors.Any())
+ if (colors.Length == 0)
{
throw new ArgumentOutOfRangeException(
nameof(colors),
@@ -99,7 +101,7 @@ namespace SixLabors.ImageSharp.Processing
throw new ArgumentNullException(nameof(colors));
}
- if (!colors.Any())
+ if (colors.Length == 0)
{
throw new ArgumentOutOfRangeException(
nameof(colors),
@@ -133,22 +135,19 @@ namespace SixLabors.ImageSharp.Processing
private readonly float length;
- private readonly PointF[] buffer;
-
public Edge(Path path, Color startColor, Color endColor)
{
this.path = path;
Vector2[] points = path.LineSegments.SelectMany(s => s.Flatten()).Select(p => (Vector2)p).ToArray();
- this.Start = points.First();
+ this.Start = points[0];
this.StartColor = (Vector4)startColor;
this.End = points.Last();
this.EndColor = (Vector4)endColor;
this.length = DistanceBetween(this.End, this.Start);
- this.buffer = new PointF[this.path.MaxIntersections];
}
public PointF Start { get; }
@@ -159,18 +158,38 @@ namespace SixLabors.ImageSharp.Processing
public Vector4 EndColor { get; }
- public Intersection? FindIntersection(PointF start, PointF end)
+ public Intersection? FindIntersection(PointF start, PointF end, MemoryAllocator allocator)
{
- int intersections = this.path.FindIntersections(start, end, this.buffer);
-
- if (intersections == 0)
+ // TODO: The number of max intersections is upper bound to the number of nodes of the path.
+ // Normally these numbers would be small and could potentially be stackalloc rather than pooled.
+ // Investigate performance beifit of checking length and choosing approach.
+ using (IMemoryOwner memory = allocator.Allocate(this.path.MaxIntersections))
{
- return null;
- }
+ Span buffer = memory.Memory.Span;
+ int intersections = this.path.FindIntersections(start, end, buffer);
+
+ if (intersections == 0)
+ {
+ return null;
+ }
+
+ buffer = buffer.Slice(0, intersections);
+
+ PointF minPoint = buffer[0];
+ var min = new Intersection(minPoint, ((Vector2)(minPoint - start)).LengthSquared());
+ for (int i = 1; i < buffer.Length; i++)
+ {
+ PointF point = buffer[i];
+ var current = new Intersection(point, ((Vector2)(point - start)).LengthSquared());
- return this.buffer.Take(intersections)
- .Select(p => new Intersection(point: p, distance: ((Vector2)(p - start)).LengthSquared()))
- .Aggregate((min, current) => min.Distance > current.Distance ? current : min);
+ if (min.Distance > current.Distance)
+ {
+ min = current;
+ }
+ }
+
+ return min;
+ }
}
public Vector4 ColorAt(float distance)
@@ -197,6 +216,10 @@ namespace SixLabors.ImageSharp.Processing
private readonly IList edges;
+ private readonly TPixel centerPixel;
+
+ private readonly TPixel transparentPixel;
+
///
/// Initializes a new instance of the class.
///
@@ -214,13 +237,15 @@ namespace SixLabors.ImageSharp.Processing
: base(configuration, options, source)
{
this.edges = edges;
-
PointF[] points = edges.Select(s => s.Start).ToArray();
this.center = points.Aggregate((p1, p2) => p1 + p2) / edges.Count;
this.centerColor = (Vector4)centerColor;
+ this.centerPixel = centerColor.ToPixel();
+
+ this.maxDistance = points.Select(p => (Vector2)(p - this.center)).Max(d => d.Length());
- this.maxDistance = points.Select(p => (Vector2)(p - this.center)).Select(d => d.Length()).Max();
+ this.transparentPixel = Color.Transparent.ToPixel();
}
///
@@ -232,22 +257,20 @@ namespace SixLabors.ImageSharp.Processing
if (point == this.center)
{
- return new Color(this.centerColor).ToPixel();
+ return this.centerPixel;
}
var direction = Vector2.Normalize(point - this.center);
-
PointF end = point + (PointF)(direction * this.maxDistance);
(Edge edge, Intersection? info) = this.FindIntersection(point, end);
if (!info.HasValue)
{
- return Color.Transparent.ToPixel();
+ return this.transparentPixel;
}
PointF intersection = info.Value.Point;
-
Vector4 edgeColor = edge.ColorAt(intersection);
float length = DistanceBetween(intersection, this.center);
@@ -263,9 +286,10 @@ namespace SixLabors.ImageSharp.Processing
{
(Edge edge, Intersection? info) closest = default;
+ MemoryAllocator allocator = this.Target.MemoryAllocator;
foreach (Edge edge in this.edges)
{
- Intersection? intersection = edge.FindIntersection(start, end);
+ Intersection? intersection = edge.FindIntersection(start, end, allocator);
if (!intersection.HasValue)
{
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs
index 524b66e05..ca639cd14 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs
@@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
source,
sourceRectangle))
{
- amount.Memory.Span.Fill(1f);
+ amount.Memory.Span.Fill(1F);
ParallelHelper.IterateRows(
workingRect,
diff --git a/src/ImageSharp/Common/Extensions/EncoderExtensions.cs b/src/ImageSharp/Common/Extensions/EncoderExtensions.cs
index 59c878485..87aaa93a9 100644
--- a/src/ImageSharp/Common/Extensions/EncoderExtensions.cs
+++ b/src/ImageSharp/Common/Extensions/EncoderExtensions.cs
@@ -1,7 +1,7 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-#if !NETCOREAPP2_1
+#if !SUPPORTS_ENCODING_STRING
using System;
using System.Text;
@@ -32,4 +32,4 @@ namespace SixLabors.ImageSharp
}
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/ImageSharp/Common/Extensions/StreamExtensions.cs b/src/ImageSharp/Common/Extensions/StreamExtensions.cs
index 6af09b220..cee3e2414 100644
--- a/src/ImageSharp/Common/Extensions/StreamExtensions.cs
+++ b/src/ImageSharp/Common/Extensions/StreamExtensions.cs
@@ -4,7 +4,6 @@
using System;
using System.Buffers;
using System.IO;
-
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
@@ -15,7 +14,6 @@ namespace SixLabors.ImageSharp
///
internal static class StreamExtensions
{
-#if NETCOREAPP2_1
///
/// Writes data from a stream into the provided buffer.
///
@@ -24,23 +22,18 @@ namespace SixLabors.ImageSharp
/// The offset within the buffer to begin writing.
/// The number of bytes to write to the stream.
public static void Write(this Stream stream, Span buffer, int offset, int count)
- {
- stream.Write(buffer.Slice(offset, count));
- }
+ => stream.Write(buffer.Slice(offset, count));
///
/// Reads data from a stream into the provided buffer.
///
/// The stream.
- /// The buffer..
+ /// The buffer.
/// The offset within the buffer where the bytes are read into.
/// The number of bytes, if available, to read.
/// The actual number of bytes read.
public static int Read(this Stream stream, Span buffer, int offset, int count)
- {
- return stream.Read(buffer.Slice(offset, count));
- }
-#endif
+ => stream.Read(buffer.Slice(offset, count));
///
/// Skips the number of bytes in the given stream.
@@ -75,17 +68,39 @@ namespace SixLabors.ImageSharp
}
public static void Read(this Stream stream, IManagedByteBuffer buffer)
- {
- stream.Read(buffer.Array, 0, buffer.Length());
- }
+ => stream.Read(buffer.Array, 0, buffer.Length());
public static void Write(this Stream stream, IManagedByteBuffer buffer)
+ => stream.Write(buffer.Array, 0, buffer.Length());
+
+#if !SUPPORTS_SPAN_STREAM
+ // This is a port of the CoreFX implementation and is MIT Licensed:
+ // https://github.com/dotnet/corefx/blob/17300169760c61a90cab8d913636c1058a30a8c1/src/Common/src/CoreLib/System/IO/Stream.cs#L742
+ public static int Read(this Stream stream, Span buffer)
{
- stream.Write(buffer.Array, 0, buffer.Length());
+ // This uses ArrayPool.Shared, rather than taking a MemoryAllocator,
+ // in order to match the signature of the framework method that exists in
+ // .NET Core.
+ byte[] sharedBuffer = ArrayPool.Shared.Rent(buffer.Length);
+ try
+ {
+ int numRead = stream.Read(sharedBuffer, 0, buffer.Length);
+ if ((uint)numRead > (uint)buffer.Length)
+ {
+ throw new IOException("Stream was too long.");
+ }
+
+ new Span(sharedBuffer, 0, numRead).CopyTo(buffer);
+ return numRead;
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(sharedBuffer);
+ }
}
-#if NET472 || NETSTANDARD1_3 || NETSTANDARD2_0
- // This is a port of the CoreFX implementation and is MIT Licensed: https://github.com/dotnet/coreclr/blob/c4dca1072d15bdda64c754ad1ea474b1580fa554/src/System.Private.CoreLib/shared/System/IO/Stream.cs#L770
+ // This is a port of the CoreFX implementation and is MIT Licensed:
+ // https://github.com/dotnet/corefx/blob/17300169760c61a90cab8d913636c1058a30a8c1/src/Common/src/CoreLib/System/IO/Stream.cs#L775
public static void Write(this Stream stream, ReadOnlySpan buffer)
{
// This uses ArrayPool.Shared, rather than taking a MemoryAllocator,
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 596710294..eda5f1f78 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -445,11 +445,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Keeps track of rows, which have undefined pixels.
private void UncompressRle4(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels)
{
-#if NETCOREAPP2_1
Span cmd = stackalloc byte[2];
-#else
- var cmd = new byte[2];
-#endif
int count = 0;
while (count < buffer.Length)
@@ -556,11 +552,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Keeps track of rows, which have undefined pixels.
private void UncompressRle8(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels)
{
-#if NETCOREAPP2_1
Span cmd = stackalloc byte[2];
-#else
- var cmd = new byte[2];
-#endif
int count = 0;
while (count < buffer.Length)
@@ -639,11 +631,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Keeps track of rows, which have undefined pixels.
private void UncompressRle24(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels)
{
-#if NETCOREAPP2_1
Span cmd = stackalloc byte[2];
-#else
- var cmd = new byte[2];
-#endif
int uncompressedPixels = 0;
while (uncompressedPixels < buffer.Length)
@@ -1213,11 +1201,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
private void ReadInfoHeader()
{
-#if NETCOREAPP2_1
Span buffer = stackalloc byte[BmpInfoHeader.MaxHeaderSize];
-#else
- var buffer = new byte[BmpInfoHeader.MaxHeaderSize];
-#endif
// Read the header size.
this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize);
@@ -1339,11 +1323,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
private void ReadFileHeader()
{
-#if NETCOREAPP2_1
Span buffer = stackalloc byte[BmpFileHeader.Size];
-#else
- var buffer = new byte[BmpFileHeader.Size];
-#endif
this.stream.Read(buffer, 0, BmpFileHeader.Size);
short fileTypeMarker = BinaryPrimitives.ReadInt16LittleEndian(buffer);
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index f7576bacb..41be71d2b 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -173,11 +173,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
reserved: 0,
offset: BmpFileHeader.Size + infoHeaderSize + colorPaletteSize);
-#if NETCOREAPP2_1
Span buffer = stackalloc byte[infoHeaderSize];
-#else
- var buffer = new byte[infoHeaderSize];
-#endif
fileHeader.WriteTo(buffer);
stream.Write(buffer, 0, BmpFileHeader.Size);
diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
index af390e954..2ae8a834e 100644
--- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
@@ -113,11 +113,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
Unsafe.Add(ref suffixRef, code) = (byte)code;
}
-#if NETCOREAPP2_1
Span buffer = stackalloc byte[255];
-#else
- var buffer = new byte[255];
-#endif
while (xyz < length)
{
@@ -227,11 +223,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The .
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
-#if NETCOREAPP2_1
private int ReadBlock(Span buffer)
-#else
- private int ReadBlock(byte[] buffer)
-#endif
{
int bufferSize = this.stream.ReadByte();
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
index 535330394..9fa4ce6d8 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -22,11 +22,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.Frame = frame;
this.Id = id;
- // Valid sampling factors are 1..2
- if (horizontalFactor == 0
- || verticalFactor == 0
- || horizontalFactor > 2
- || verticalFactor > 2)
+ // Validate sampling factors.
+ if (horizontalFactor == 0 || verticalFactor == 0)
{
JpegThrowHelper.ThrowBadSampling();
}
@@ -138,4 +135,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.SpectralBlocks = this.memoryAllocator.Allocate2D(width, height, AllocationOptions.Clean);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
index ec9cca8c8..62765a884 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
@@ -764,7 +764,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
for (int i = 0; i < this.ComponentCount; i++)
{
byte hv = this.temp[index + 1];
- int h = hv >> 4;
+ int h = (hv >> 4) & 15;
int v = hv & 15;
if (maxH < h)
diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
index 1ff3bb599..d4f42a6c3 100644
--- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
+++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
@@ -565,11 +565,8 @@ namespace SixLabors.ImageSharp.Formats.Tga
{
this.currentStream = stream;
-#if NETCOREAPP2_1
Span buffer = stackalloc byte[TgaFileHeader.Size];
-#else
- var buffer = new byte[TgaFileHeader.Size];
-#endif
+
this.currentStream.Read(buffer, 0, TgaFileHeader.Size);
this.fileHeader = TgaFileHeader.Parse(buffer);
this.metadata = new ImageMetadata();
diff --git a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
index 3f4fb8f93..9dcea142f 100644
--- a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
+++ b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
@@ -97,11 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
pixelDepth: (byte)this.bitsPerPixel.Value,
imageDescriptor: imageDescriptor);
-#if NETCOREAPP2_1
Span buffer = stackalloc byte[TgaFileHeader.Size];
-#else
- byte[] buffer = new byte[TgaFileHeader.Size];
-#endif
fileHeader.WriteTo(buffer);
stream.Write(buffer, 0, TgaFileHeader.Size);
diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 8110cb57e..28343eaaa 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -12,6 +12,7 @@
netcoreapp2.1;netstandard1.3;netstandard2.0
$(TargetFrameworks);net472
+ netcoreapp2.1;netstandard2.0;netstandard1.3;net472
true
true
@@ -20,23 +21,6 @@
SixLabors.ImageSharp
-
-
- $(DefineConstants);SUPPORTS_MATHF
-
-
-
- $(DefineConstants);SUPPORTS_HASHCODE
-
-
-
- $(DefineConstants);SUPPORTS_EXTENDED_INTRINSICS
-
-
-
-
-
-
diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs
index 031e732ea..224e07b1e 100644
--- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs
@@ -433,5 +433,21 @@ namespace SixLabors.ImageSharp.Tests.Drawing
}
}
+ [Theory]
+ [WithBlankImages(200, 200, PixelTypes.Rgb24)]
+ public void BrushApplicatorIsThreadSafeIssue1044(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ provider.VerifyOperation(
+ TolerantComparer,
+ img =>
+ {
+ var brush = new PathGradientBrush(
+ new[] { new PointF(0, 0), new PointF(200, 0), new PointF(200, 200), new PointF(0, 200), new PointF(0, 0) },
+ new[] { Color.Red, Color.Yellow, Color.Green, Color.DarkCyan, Color.Red });
+
+ img.Mutate(m => m.Fill(brush));
+ }, false, false);
+ }
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs
index 4a3ef9b95..37da32d76 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs
@@ -31,6 +31,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
TestImages.Jpeg.Issues.InvalidAPP0721,
TestImages.Jpeg.Issues.ExifGetString750Load,
TestImages.Jpeg.Issues.ExifGetString750Transform,
+ TestImages.Jpeg.Issues.BadSubSampling1076,
// LibJpeg can open this despite the invalid density units.
TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825B,
@@ -38,6 +39,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
// LibJpeg can open this despite incorrect colorspace metadata.
TestImages.Jpeg.Issues.IncorrectColorspace855,
+ // LibJpeg can open this despite the invalid subsampling units.
+ TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824C,
+
// High depth images
TestImages.Jpeg.Baseline.Testorig12bit,
};
@@ -71,7 +75,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
TestImages.Jpeg.Issues.Fuzz.NullReferenceException823,
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824A,
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824B,
- TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824C,
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824D,
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824E,
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824F,
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index ada077496..f5cdb29b6 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -192,6 +192,7 @@ namespace SixLabors.ImageSharp.Tests
public const string IncorrectColorspace855 = "Jpg/issues/issue855-incorrect-colorspace.jpg";
public const string IncorrectResize1006 = "Jpg/issues/issue1006-incorrect-resize.jpg";
public const string ExifResize1049 = "Jpg/issues/issue1049-exif-resize.jpg";
+ public const string BadSubSampling1076 = "Jpg/issues/issue-1076-invalid-subsampling.jpg";
public static class Fuzz
{
diff --git a/tests/Images/External b/tests/Images/External
index d8ea82085..fbba5e2a7 160000
--- a/tests/Images/External
+++ b/tests/Images/External
@@ -1 +1 @@
-Subproject commit d8ea82085ac39a6aa6ca8e0806a9518d3a7d3337
+Subproject commit fbba5e2a78aa479c0752dc0fd91ec25b4948704a
diff --git a/tests/Images/Input/Jpg/issues/issue-1076-invalid-subsampling.jpg b/tests/Images/Input/Jpg/issues/issue-1076-invalid-subsampling.jpg
new file mode 100644
index 000000000..6cc3531a0
--- /dev/null
+++ b/tests/Images/Input/Jpg/issues/issue-1076-invalid-subsampling.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1507746a6c37697cb985fc7427709fd68478ff7cbdfe20f6cfbe7257ed6c7ccd
+size 39149