diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs index 42dcf7200a..e13b26f9a9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs @@ -26,16 +26,6 @@ internal readonly struct JFifMarker : IEquatable /// The vertical pixel density. private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, short xDensity, short yDensity) { - if (xDensity <= 0) - { - JpegThrowHelper.ThrowInvalidImageContentException($"X-Density {xDensity} must be greater than 0."); - } - - if (yDensity <= 0) - { - JpegThrowHelper.ThrowInvalidImageContentException($"Y-Density {yDensity} must be greater than 0."); - } - this.MajorVersion = majorVersion; this.MinorVersion = minorVersion; @@ -64,12 +54,12 @@ internal readonly struct JFifMarker : IEquatable public PixelResolutionUnit DensityUnits { get; } /// - /// Gets the horizontal pixel density. Must not be zero. + /// Gets the horizontal pixel density. /// public short XDensity { get; } /// - /// Gets the vertical pixel density. Must not be zero. + /// Gets the vertical pixel density. /// public short YDensity { get; } @@ -88,12 +78,8 @@ internal readonly struct JFifMarker : IEquatable byte densityUnits = bytes[7]; short xDensity = (short)((bytes[8] << 8) | bytes[9]); short yDensity = (short)((bytes[10] << 8) | bytes[11]); - - if (xDensity > 0 && yDensity > 0) - { - marker = new JFifMarker(majorVersion, minorVersion, densityUnits, xDensity, yDensity); - return true; - } + marker = new JFifMarker(majorVersion, minorVersion, densityUnits, xDensity, yDensity); + return true; } marker = default; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs index 0eb484b94a..51d9bfbced 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs @@ -121,4 +121,10 @@ internal abstract class SpectralConverter return size; } + + /// + /// Gets a value indicating whether the converter has a pixel buffer. + /// + /// if the converter has a pixel buffer; otherwise, . + public abstract bool HasPixelBuffer(); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs index 4bb58d8a12..d6250127f5 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs @@ -85,6 +85,12 @@ internal class SpectralConverter : SpectralConverter, IDisposable /// public Configuration Configuration { get; } + /// + /// Gets a value indicating whether the converter has a pixel buffer. + /// + /// if the converter has a pixel buffer; otherwise, . + public override bool HasPixelBuffer() => this.pixelBuffer is not null; + /// /// Gets converted pixel buffer. /// diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 511ec1ba1d..51de9ffbd1 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -356,6 +356,18 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals // to uint to avoid sign extension. if (stream.RemainingBytes < (uint)markerContentByteSize) { + if (metadataOnly && this.Metadata != null && this.Frame != null) + { + // We have enough data to decode the image, so we can stop parsing. + return; + } + + if (this.Metadata != null && this.Frame != null && spectralConverter.HasPixelBuffer()) + { + // We have enough data to decode the image, so we can stop parsing. + return; + } + JpegThrowHelper.ThrowNotEnoughBytesForMarker(fileMarker.Marker); } diff --git a/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs index 2cb8dc3211..ad93d6f167 100644 --- a/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs @@ -12,168 +12,280 @@ namespace SixLabors.ImageSharp.Processing; public static class DrawImageExtensions { /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, float opacity) { - var options = source.GetGraphicsOptions(); - return source.ApplyProcessor( - new DrawImageProcessor( - image, - Point.Empty, - options.ColorBlendingMode, - options.AlphaCompositionMode, - opacity)); + GraphicsOptions options = source.GetGraphicsOptions(); + return DrawImage(source, image, options.ColorBlendingMode, options.AlphaCompositionMode, opacity); } /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The blending mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The rectangle structure that specifies the portion of the image to draw. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Rectangle rectangle, + float opacity) + { + GraphicsOptions options = source.GetGraphicsOptions(); + return DrawImage(source, image, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity); + } + + /// + /// Draws the given image together with the currently processing image by blending their pixels. + /// + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The color blending mode. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, - float opacity) => - source.ApplyProcessor( - new DrawImageProcessor( - image, - Point.Empty, - colorBlending, - source.GetGraphicsOptions().AlphaCompositionMode, - opacity)); + float opacity) + => DrawImage(source, image, Point.Empty, colorBlending, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The rectangle structure that specifies the portion of the image to draw. + /// The color blending mode. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Rectangle rectangle, + PixelColorBlendingMode colorBlending, + float opacity) + => DrawImage(source, image, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); + + /// + /// Draws the given image together with the currently processing image by blending their pixels. + /// + /// The current image processing context. + /// The image to draw on the currently processing image. /// The color blending mode. /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, - float opacity) => - source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); + float opacity) + => DrawImage(source, image, Point.Empty, colorBlending, alphaComposition, opacity); + + /// + /// Draws the given image together with the currently processing image by blending their pixels. + /// + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The rectangle structure that specifies the portion of the image to draw. + /// The color blending mode. + /// The alpha composition mode. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Rectangle rectangle, + PixelColorBlendingMode colorBlending, + PixelAlphaCompositionMode alphaComposition, + float opacity) + => DrawImage(source, image, Point.Empty, rectangle, colorBlending, alphaComposition, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. + /// The current image processing context. + /// The image to draw on the currently processing image. /// The options, including the blending type and blending amount. - /// The . + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, - GraphicsOptions options) => - source.ApplyProcessor( - new DrawImageProcessor( - image, - Point.Empty, - options.ColorBlendingMode, - options.AlphaCompositionMode, - options.BlendPercentage)); + GraphicsOptions options) + => DrawImage(source, image, Point.Empty, options); + + /// + /// Draws the given image together with the currently processing image by blending their pixels. + /// + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The rectangle structure that specifies the portion of the image to draw. + /// The options, including the blending type and blending amount. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Rectangle rectangle, + GraphicsOptions options) + => DrawImage(source, image, Point.Empty, rectangle, options); + + /// + /// Draws the given image together with the currently processing image by blending their pixels. + /// + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + float opacity) + { + GraphicsOptions options = source.GetGraphicsOptions(); + return DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, opacity); + } /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The rectangle structure that specifies the portion of the image to draw. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, Point location, + Rectangle rectangle, float opacity) { - var options = source.GetGraphicsOptions(); - return source.ApplyProcessor( - new DrawImageProcessor( - image, - location, - options.ColorBlendingMode, - options.AlphaCompositionMode, - opacity)); + GraphicsOptions options = source.GetGraphicsOptions(); + return DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity); } /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. /// The color blending to apply. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, - float opacity) => - source.ApplyProcessor( - new DrawImageProcessor( - image, - location, - colorBlending, - source.GetGraphicsOptions().AlphaCompositionMode, - opacity)); + float opacity) + => DrawImage(source, image, location, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The rectangle structure that specifies the portion of the image to draw. + /// The color blending to apply. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + Rectangle rectangle, + PixelColorBlendingMode colorBlending, + float opacity) + => DrawImage(source, image, location, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); + + /// + /// Draws the given image together with the currently processing image by blending their pixels. + /// + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The options containing the blend mode and opacity. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + GraphicsOptions options) + => DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage); + + /// + /// Draws the given image together with the currently processing image by blending their pixels. + /// + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The rectangle structure that specifies the portion of the image to draw. + /// The options containing the blend mode and opacity. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + Rectangle rectangle, + GraphicsOptions options) + => DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage); + + /// + /// Draws the given image together with the currently processing image by blending their pixels. + /// + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. /// The color blending to apply. /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, - float opacity) => - source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); + float opacity) + => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The options containing the blend mode and opacity. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The rectangle structure that specifies the portion of the image to draw. + /// The color blending to apply. + /// The alpha composition mode. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, Point location, - GraphicsOptions options) => + Rectangle rectangle, + PixelColorBlendingMode colorBlending, + PixelAlphaCompositionMode alphaComposition, + float opacity) => source.ApplyProcessor( - new DrawImageProcessor( - image, - location, - options.ColorBlendingMode, - options.AlphaCompositionMode, - options.BlendPercentage)); + new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity), + rectangle); } diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs index b7d5b42f8a..9de4f862b8 100644 --- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -63,7 +63,7 @@ public class DrawImageProcessor : IImageProcessor public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixelBg : unmanaged, IPixel { - var visitor = new ProcessorFactoryVisitor(configuration, this, source, sourceRectangle); + ProcessorFactoryVisitor visitor = new(configuration, this, source, sourceRectangle); this.Image.AcceptVisitor(visitor); return visitor.Result; } @@ -88,8 +88,7 @@ public class DrawImageProcessor : IImageProcessor public void Visit(Image image) where TPixelFg : unmanaged, IPixel - { - this.Result = new DrawImageProcessor( + => this.Result = new DrawImageProcessor( this.configuration, image, this.source, @@ -98,6 +97,5 @@ public class DrawImageProcessor : IImageProcessor this.definition.ColorBlendingMode, this.definition.AlphaCompositionMode, this.definition.Opacity); - } } } diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs index 82e639f1bd..436a447972 100644 --- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs +++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs @@ -89,7 +89,7 @@ internal class DrawImageProcessor : ImageProcessor int width = maxX - minX; - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + Rectangle workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); // Not a valid operation because rectangle does not overlap with this image. if (workingRect.Width <= 0 || workingRect.Height <= 0) @@ -98,7 +98,7 @@ internal class DrawImageProcessor : ImageProcessor "Cannot draw image because the source image does not overlap the target image."); } - var operation = new RowOperation(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity); + DrawImageProcessor.RowOperation operation = new(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity); ParallelRowIterator.IterateRows( configuration, workingRect, diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs index aa88242ce4..b5a7245292 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs @@ -54,6 +54,8 @@ public class DecodeJpegParseStreamOnly { } + public override bool HasPixelBuffer() => throw new NotImplementedException(); + public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) { } diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 0dcb961f84..d017e5ad42 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -119,9 +119,7 @@ public class DrawImageTests public void WorksWithDifferentLocations(TestImageProvider provider, int x, int y) { using Image background = provider.GetImage(); - using Image overlay = new(50, 50); - Assert.True(overlay.DangerousTryGetSinglePixelMemory(out Memory overlayMem)); - overlayMem.Span.Fill(Color.Black); + using Image overlay = new(50, 50, Color.Black.ToRgba32()); background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F)); @@ -138,6 +136,31 @@ public class DrawImageTests appendSourceFileOrDescription: false); } + [Theory] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 10, 10)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 50, 25)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 50)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 50, 50)] + public void WorksWithDifferentBounds(TestImageProvider provider, int width, int height) + { + using Image background = provider.GetImage(); + using Image overlay = new(50, 50, Color.Black.ToRgba32()); + + background.Mutate(c => c.DrawImage(overlay, new Rectangle(0, 0, width, height), PixelColorBlendingMode.Normal, 1F)); + + background.DebugSave( + provider, + testOutputDetails: $"{width}_{height}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + + background.CompareToReferenceOutput( + provider, + testOutputDetails: $"{width}_{height}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + [Theory] [WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)] public void DrawTransformed(TestImageProvider provider) @@ -158,12 +181,12 @@ public class DrawImageTests Point position = new((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); image.Mutate(x => x.DrawImage(blend, position, .75F)); - image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); image.CompareToReferenceOutput( ImageComparer.TolerantPercentage(0.002f), provider, - appendSourceFileOrDescription: false, - appendPixelTypeToFileName: false); + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } [Theory] @@ -179,9 +202,6 @@ public class DrawImageTests Assert.Contains("does not overlap", ex.ToString()); - void Test() - { - background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions())); - } + void Test() => background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions())); } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs index 3890c20e93..3b7e20eb4e 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs @@ -46,15 +46,6 @@ public class JFifMarkerTests Assert.Equal(default, marker); } - [Fact] - public void MarkerIgnoresCorrectHeaderButInvalidDensities() - { - bool isJFif = JFifMarker.TryParse(this.bytes3, out JFifMarker marker); - - Assert.False(isJFif); - Assert.Equal(default, marker); - } - [Fact] public void MarkerEqualityIsCorrect() { diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 1d5a7e0ff8..425d12497c 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -300,4 +300,15 @@ public partial class JpegDecoderTests image.DebugSave(provider); image.CompareToOriginal(provider); } + + // https://github.com/SixLabors/ImageSharp/issues/2315 + [Theory] + [WithFile(TestImages.Jpeg.Issues.Issue2315_NotEnoughBytes, PixelTypes.Rgba32)] + public void Issue2315_DecodeWorks(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(JpegDecoder.Instance); + image.DebugSave(provider); + image.CompareToOriginal(provider); + } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs index 58347a0724..805ee586a8 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs @@ -187,6 +187,8 @@ public class SpectralJpegTests } } + public override bool HasPixelBuffer() => throw new NotImplementedException(); + public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) { this.frame = frame; diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 29223b1fe0..22a48ebee4 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -281,6 +281,7 @@ public static class TestImages public const string ValidExifArgumentNullExceptionOnEncode = "Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg"; public const string Issue2133_DeduceColorSpace = "Jpg/issues/Issue2133.jpg"; public const string Issue2136_ScanMarkerExtraneousBytes = "Jpg/issues/Issue2136-scan-segment-extraneous-bytes.jpg"; + public const string Issue2315_NotEnoughBytes = "Jpg/issues/issue-2315.jpg"; public static class Fuzz { diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png new file mode 100644 index 0000000000..64ce14d509 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f353ee06664a6ff27c533af63cffb9eac4917103ba0b7fff9084fb4d2d42fed7 +size 155 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png new file mode 100644 index 0000000000..7e0466186a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af198da8f611eb97f3e4e358cb097cd292771d52e991de76495f073c1f1b9338 +size 154 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png new file mode 100644 index 0000000000..6b93e597eb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35bda87f28e03c5ed0d45412e367fae9b04b7684f5242dc20e7709e8ed71cd86 +size 156 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png new file mode 100644 index 0000000000..540082dfdf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8b9ff745592bb0e0a365cb0985a5519bf567fc73a09211c88bcda51356f9202 +size 155 diff --git a/tests/Images/Input/Jpg/issues/issue-2315.jpg b/tests/Images/Input/Jpg/issues/issue-2315.jpg new file mode 100644 index 0000000000..fe3001eddc --- /dev/null +++ b/tests/Images/Input/Jpg/issues/issue-2315.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f129b057efb499d492e9afcffdd98de62aac1e04b97a09a75b4799ba498cd3c1 +size 319056