Skip to content

Negative height rectangles cause ArgumentOutOfRangeException for property MaxDegreeOfParallelism in IterateRows #875

@atruskie

Description

@atruskie

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 DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

Description

I made a mistake when cloning and cropping an image.

The problem is that the exception thrown was quite obscure. The error was related to MaxDegreeOfParallelism being invalid. Here is the stack trace:

SixLabors.ImageSharp.ImageProcessingException: An error occurred when processing the image using DrawImageProcessor`2. See the inner exception for more detail. ---> SixLabors.ImageSharp.ImageProcessingException: An error occurred when processing the image using DrawImageProcessor`2. See the inner exception for more detail. ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: MaxDegreeOfParallelism
   at System.Threading.Tasks.ParallelOptions.set_MaxDegreeOfParallelism(Int32 value)
   at SixLabors.ImageSharp.ParallelUtils.ParallelHelper.IterateRows(Rectangle rectangle, ParallelExecutionSettings& parallelSettings, Action`1 body)
   at SixLabors.ImageSharp.Processing.Processors.Drawing.DrawImageProcessor`2.OnFrameApply(ImageFrame`1 source, Rectangle sourceRectangle, Configuration configuration)
   at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.Apply(ImageFrame`1 source, Rectangle sourceRectangle, Configuration configuration)
   --- End of inner exception stack trace ---
   at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.Apply(ImageFrame`1 source, Rectangle sourceRectangle, Configuration configuration)
   at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.Apply(Image`1 source, Rectangle sourceRectangle)
   --- End of inner exception stack trace ---
   at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.Apply(Image`1 source, Rectangle sourceRectangle)
   at SixLabors.ImageSharp.Processing.DefaultInternalImageProcessorContext`1.ApplyProcessor(IImageProcessor`1 processor, Rectangle rectangle)
   at SixLabors.ImageSharp.Processing.DefaultInternalImageProcessorContext`1.ApplyProcessor(IImageProcessor`1 processor)
   at SixLabors.ImageSharp.Processing.DrawImageExtensions.DrawImage[TPixelDst,TPixelSrc](IImageProcessingContext`1 source, Image`1 image, Point location, GraphicsOptions options)

I've tracked down the root cause to:

int maxSteps = DivideCeil(rectangle.Width * rectangle.Height, parallelSettings.MinimumPixelsProcessedPerTask);
int numOfSteps = Math.Min(parallelSettings.MaxDegreeOfParallelism, maxSteps);
// Avoid TPL overhead in this trivial case:
if (numOfSteps == 1)
{
var rows = new RowInterval(rectangle.Top, rectangle.Bottom);
body(rows);
return;
}
int verticalStep = DivideCeil(rectangle.Height, numOfSteps);
var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = numOfSteps };

If the rectangle height is negative, then maxSteps will be negative, which will then set the MaxDegreeOfParallelism to a negative value.

Steps to Reproduce

It took me ages to work out what happened! I got my top and left variables back to front.

My crop was:

image.Mutate(x => x.DrawImage(source, new Point(top, left), GraphicsOptions.Default));

And should have been:

image.Mutate(x => x.DrawImage(source, new Point(left, top), GraphicsOptions.Default));

System Configuration

  • ImageSharp version: (local build) 2849fd9
  • Other ImageSharp packages and versions: (local build) 2849fd9
  • Environment (Operating system, version and so on): Win 10, 1809
  • .NET Framework version: ".NETFramework,Version=v4.6.2"
  • Additional information:

I think the ideal solution here is a couple more guards to provide a better error message when someone (like me) does something silly and messes up their coordinates.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions