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