Browse Source

Merge branch 'main' into stefannikolei/nullable/zlib

pull/2325/head
James Jackson-South 3 years ago
committed by GitHub
parent
commit
06f1edff78
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
  2. 6
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs
  3. 6
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
  4. 12
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  5. 302
      src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs
  6. 6
      src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs
  7. 4
      src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
  8. 2
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs
  9. 40
      tests/ImageSharp.Tests/Drawing/DrawImageTests.cs
  10. 9
      tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs
  11. 11
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  12. 2
      tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
  13. 1
      tests/ImageSharp.Tests/TestImages.cs
  14. 3
      tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png
  15. 3
      tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png
  16. 3
      tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png
  17. 3
      tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png
  18. 3
      tests/Images/Input/Jpg/issues/issue-2315.jpg

22
src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs

@ -26,16 +26,6 @@ internal readonly struct JFifMarker : IEquatable<JFifMarker>
/// <param name="yDensity">The vertical pixel density.</param>
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<JFifMarker>
public PixelResolutionUnit DensityUnits { get; }
/// <summary>
/// Gets the horizontal pixel density. Must not be zero.
/// Gets the horizontal pixel density.
/// </summary>
public short XDensity { get; }
/// <summary>
/// Gets the vertical pixel density. Must not be zero.
/// Gets the vertical pixel density.
/// </summary>
public short YDensity { get; }
@ -88,12 +78,8 @@ internal readonly struct JFifMarker : IEquatable<JFifMarker>
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;

6
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs

@ -121,4 +121,10 @@ internal abstract class SpectralConverter
return size;
}
/// <summary>
/// Gets a value indicating whether the converter has a pixel buffer.
/// </summary>
/// <returns><see langword="true"/> if the converter has a pixel buffer; otherwise, <see langword="false"/>.</returns>
public abstract bool HasPixelBuffer();
}

6
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs

@ -85,6 +85,12 @@ internal class SpectralConverter<TPixel> : SpectralConverter, IDisposable
/// </summary>
public Configuration Configuration { get; }
/// <summary>
/// Gets a value indicating whether the converter has a pixel buffer.
/// </summary>
/// <returns><see langword="true"/> if the converter has a pixel buffer; otherwise, <see langword="false"/>.</returns>
public override bool HasPixelBuffer() => this.pixelBuffer is not null;
/// <summary>
/// Gets converted pixel buffer.
/// </summary>

12
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);
}

302
src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs

@ -12,168 +12,280 @@ namespace SixLabors.ImageSharp.Processing;
public static class DrawImageExtensions
{
/// <summary>
/// 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.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
/// <returns>The <see cref="Image{TPixelDst}"/>.</returns>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="colorBlending">The blending mode.</param>
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
/// <returns>The <see cref="Image{TPixelDst}"/>.</returns>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
}
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="colorBlending">The color blending mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
/// <summary>
/// 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.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="colorBlending">The color blending mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Rectangle rectangle,
PixelColorBlendingMode colorBlending,
float opacity)
=> DrawImage(source, image, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="colorBlending">The color blending mode.</param>
/// <param name="alphaComposition">The alpha composition mode.</param>
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
/// <returns>The <see cref="Image{TPixelDst}"/>.</returns>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="colorBlending">The color blending mode.</param>
/// <param name="alphaComposition">The alpha composition mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
/// <summary>
/// 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.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="options">The options, including the blending type and blending amount.</param>
/// <returns>The <see cref="Image{TPixelDst}"/>.</returns>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="options">The options, including the blending type and blending amount.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Rectangle rectangle,
GraphicsOptions options)
=> DrawImage(source, image, Point.Empty, rectangle, options);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
/// <returns>The <see cref="Image{TPixelDst}"/>.</returns>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="colorBlending">The color blending to apply.</param>
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
/// <returns>The <see cref="Image{TPixelDst}"/>.</returns>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
/// <summary>
/// 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.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="colorBlending">The color blending to apply.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="options">The options containing the blend mode and opacity.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
GraphicsOptions options)
=> DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="options">The options containing the blend mode and opacity.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="colorBlending">The color blending to apply.</param>
/// <param name="alphaComposition">The alpha composition mode.</param>
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
/// <returns>The <see cref="Image{TPixelDst}"/>.</returns>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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));
/// <summary>
/// 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.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <param name="options">The options containing the blend mode and opacity.</param>
/// <returns>The <see cref="Image{TPixelDst}"/>.</returns>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="colorBlending">The color blending to apply.</param>
/// <param name="alphaComposition">The alpha composition mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
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);
}

6
src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs

@ -63,7 +63,7 @@ public class DrawImageProcessor : IImageProcessor
public IImageProcessor<TPixelBg> CreatePixelSpecificProcessor<TPixelBg>(Configuration configuration, Image<TPixelBg> source, Rectangle sourceRectangle)
where TPixelBg : unmanaged, IPixel<TPixelBg>
{
var visitor = new ProcessorFactoryVisitor<TPixelBg>(configuration, this, source, sourceRectangle);
ProcessorFactoryVisitor<TPixelBg> visitor = new(configuration, this, source, sourceRectangle);
this.Image.AcceptVisitor(visitor);
return visitor.Result;
}
@ -88,8 +88,7 @@ public class DrawImageProcessor : IImageProcessor
public void Visit<TPixelFg>(Image<TPixelFg> image)
where TPixelFg : unmanaged, IPixel<TPixelFg>
{
this.Result = new DrawImageProcessor<TPixelBg, TPixelFg>(
=> this.Result = new DrawImageProcessor<TPixelBg, TPixelFg>(
this.configuration,
image,
this.source,
@ -98,6 +97,5 @@ public class DrawImageProcessor : IImageProcessor
this.definition.ColorBlendingMode,
this.definition.AlphaCompositionMode,
this.definition.Opacity);
}
}
}

4
src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs

@ -89,7 +89,7 @@ internal class DrawImageProcessor<TPixelBg, TPixelFg> : ImageProcessor<TPixelBg>
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<TPixelBg, TPixelFg> : ImageProcessor<TPixelBg>
"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<TPixelBg, TPixelFg>.RowOperation operation = new(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity);
ParallelRowIterator.IterateRows(
configuration,
workingRect,

2
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)
{
}

40
tests/ImageSharp.Tests/Drawing/DrawImageTests.cs

@ -119,9 +119,7 @@ public class DrawImageTests
public void WorksWithDifferentLocations(TestImageProvider<Rgba32> provider, int x, int y)
{
using Image<Rgba32> background = provider.GetImage();
using Image<Rgba32> overlay = new(50, 50);
Assert.True(overlay.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> overlayMem));
overlayMem.Span.Fill(Color.Black);
using Image<Rgba32> 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<Rgba32> provider, int width, int height)
{
using Image<Rgba32> background = provider.GetImage();
using Image<Rgba32> 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<TPixel>(TestImageProvider<TPixel> 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()));
}
}

9
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()
{

11
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<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage(JpegDecoder.Instance);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
}

2
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;

1
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
{

3
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

3
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

3
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

3
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

3
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
Loading…
Cancel
Save