-
-
Notifications
You must be signed in to change notification settings - Fork 888
Description
Prerequisites
- I have written a descriptive issue title
- I have verified that I am running the latest version of ImageSharp
- I have verified if the problem exist in both
DEBUGandRELEASEmode - I have searched open and closed issues to ensure it has not already been reported
ImageSharp version
3.0.1, 3.0.2-alpha.0.15
Other ImageSharp packages and versions
(None)
Environment (Operating system, version and so on)
Windows 7 SP1 x64, Windows 11 21H2 x64
.NET Framework version
.NET 6.0
Description
The DrawImage(Image, Point, Rectangle, float) method was added in 3.0.0 after #2112 and #2102 requested a method which could draw part of one image onto another. However, the method does not seem to work as intended as more often than not it throws one of two exceptions, or simply fails to produce the correct image.
Steps to Reproduce
The following code tries to draw a 32 x 32 piece of a 512 x 512 image onto a 100 x 100 image.
ImageProcessingException
using var src = Image.Load<Rgba32>("numbergrid.png");
using var dst = new Image<Rgba32>(100, 100, new Rgba32(0, 255, 255));
dst.Mutate(c => {
c.DrawImage(src, new Point(64, 10), new Rectangle(32, 32, 32, 32), 1.0f);
});
dst.SaveAsPng("result.png");Expected result:
Exception:
SixLabors.ImageSharp.ImageProcessingException
HResult=0x80131500
Message=Cannot draw image because the source image does not overlap the target image.
Source=SixLabors.ImageSharp
StackTrace:
at SixLabors.ImageSharp.Processing.Processors.Drawing.DrawImageProcessor`2.OnFrameApply(ImageFrame`1 source)
at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.Apply(ImageFrame`1 source)
at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.SixLabors.ImageSharp.Processing.Processors.IImageProcessor<TPixel>.Execute()
at SixLabors.ImageSharp.Processing.DefaultImageProcessorContext`1.ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
at SixLabors.ImageSharp.Processing.DrawImageExtensions.DrawImage(IImageProcessingContext source, Image image, Point location, Rectangle rectangle, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, Single opacity)
at SixLabors.ImageSharp.Processing.DrawImageExtensions.DrawImage(IImageProcessingContext source, Image image, Point location, Rectangle rectangle, Single opacity)
at ImageSharp_DrawImage_SrcRect_Test.Form1.<>c__DisplayClass2_0.<Form1_Shown>b__0(IImageProcessingContext c) in [REDACTED]
at SixLabors.ImageSharp.Processing.ProcessingExtensions.Mutate[TPixel](Image`1 source, Configuration configuration, Action`1 operation)
at SixLabors.ImageSharp.Processing.ProcessingExtensions.Mutate[TPixel](Image`1 source, Action`1 operation)
(...continues with my application's stack trace...)
ArgumentOutOfRangeException
using var src = Image.Load<Rgba32>("numbergrid.png");
using var dst = new Image<Rgba32>(100, 100, new Rgba32(0, 255, 255));
dst.Mutate(c => {
c.DrawImage(src, new Point(10, 10), new Rectangle(320, 128, 32, 32), 1.0f);
});
dst.SaveAsPng("result.png");Expected result:
Exception:
System.ArgumentOutOfRangeException
HResult=0x80131502
Message=Specified argument was out of the range of valid values. Arg_ParamName_Name
Source=SixLabors.ImageSharp
ParamName=DangerousGetRowSpan(128). Y was out of range. Height=100
StackTrace:
at SixLabors.ImageSharp.Memory.Buffer2D`1.ThrowYOutOfRangeException(Int32 y)
at SixLabors.ImageSharp.Memory.Buffer2D`1.DangerousGetRowSpan(Int32 y)
at SixLabors.ImageSharp.Processing.Processors.Drawing.DrawImageProcessor`2.RowOperation.Invoke(Int32 y)
at SixLabors.ImageSharp.Advanced.ParallelRowIterator.IterateRows[T](Rectangle rectangle, ParallelExecutionSettings& parallelSettings, T& operation)
at SixLabors.ImageSharp.Advanced.ParallelRowIterator.IterateRows[T](Configuration configuration, Rectangle rectangle, T& operation)
at SixLabors.ImageSharp.Processing.Processors.Drawing.DrawImageProcessor`2.OnFrameApply(ImageFrame`1 source)
at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.Apply(ImageFrame`1 source)
at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.SixLabors.ImageSharp.Processing.Processors.IImageProcessor<TPixel>.Execute()
at SixLabors.ImageSharp.Processing.DefaultImageProcessorContext`1.ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
at SixLabors.ImageSharp.Processing.DrawImageExtensions.DrawImage(IImageProcessingContext source, Image image, Point location, Rectangle rectangle, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, Single opacity)
at SixLabors.ImageSharp.Processing.DrawImageExtensions.DrawImage(IImageProcessingContext source, Image image, Point location, Rectangle rectangle, Single opacity)
at ImageSharp_DrawImage_SrcRect_Test.Form1.<>c__DisplayClass2_0.<Form1_Shown>b__0(IImageProcessingContext c) in [REDACTED]
at SixLabors.ImageSharp.Processing.ProcessingExtensions.Mutate[TPixel](Image`1 source, Configuration configuration, Action`1 operation)
at SixLabors.ImageSharp.Processing.ProcessingExtensions.Mutate[TPixel](Image`1 source, Action`1 operation)
(...continues with my application's stack trace...)
No exception, but incorrect result
using var src = Image.Load<Rgba32>("numbergrid.png");
using var dst = new Image<Rgba32>(100, 100, new Rgba32(0, 255, 255));
dst.Mutate(c => {
c.DrawImage(src, new Point(10, 10), new Rectangle(32, 32, 32, 32), 1.0f);
});
dst.SaveAsPng("result.png");Expected result:
Actual result:
Alternative code that produces the correct result
The following code clones and crops the source image instead, which produces the expected result regardless of the coordinates used:
using var src = Image.Load<Rgba32>("numbergrid.png");
using var dst = new Image<Rgba32>(100, 100, new Rgba32(0, 255, 255));
dst.Mutate(c => {
using var slice = src.Clone(c => c.Crop(new Rectangle(32, 32, 32, 32)));
c.DrawImage(slice, new Point(10, 10), 1.0f);
});Result:
Since this does unnecessary cloning and cropping of the source image, this is not a viable option.
Images
The image numbergrid.png used in the code:





