Skip to content

Image.Save ArgumentOutOfRangeException when resizing image #925

Closed

Description

@chrisdrobison

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

We are resizing an image 5 times and passing one resized stream to the next. We are getting the following error:

Value 255 must be greater than or equal to 0 and less than or equal to 2.
Parameter name: densityUnits

   at SixLabors.ImageSharp.Guard.ThrowArgumentOutOfRangeException(String parameterName, String message)
   at SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.JFifMarker..ctor(Byte majorVersion, Byte minorVersion, Byte densityUnits, Int16 xDensity, Int16 yDensity)
   at SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.JFifMarker.TryParse(Byte[] bytes, JFifMarker& marker)
   at SixLabors.ImageSharp.Formats.Jpeg.JpegDecoderCore.ProcessApplicationHeaderMarker(Int32 remaining)
   at SixLabors.ImageSharp.Formats.Jpeg.JpegDecoderCore.ParseStream(Stream stream, Boolean metadataOnly)
   at SixLabors.ImageSharp.Formats.Jpeg.JpegDecoderCore.Decode[TPixel](Stream stream)
   at SixLabors.ImageSharp.Formats.Jpeg.JpegDecoder.Decode[TPixel](Configuration configuration, Stream stream)
   at SixLabors.ImageSharp.Image.Decode[TPixel](Stream stream, Configuration config)
   at SixLabors.ImageSharp.Image.WithSeekableStream[T](Configuration config, Stream stream, Func`2 action)
   at SixLabors.ImageSharp.Image.Load[TPixel](Configuration config, Stream stream, IImageFormat& format)
   at SixLabors.ImageSharp.Image.Load(Stream stream)

Steps to Reproduce

            Stream rawImage; // Image already loaded here
            rawImage.Seek(0, SeekOrigin.Begin);

            // producing the master image from the Raw Image
            using (var masterlMemStream = RecMemStreamMan.GetStream())
            {
                var fileRepository = _fileRepositoryFactory.GetFileRepository(projectImage.ProjectId);

                // 1024 x 768
                await ResizeImage(rawImage, masterlMemStream, MaxImageHeight, MaxImageWidth, ResizeMode.Max, contentType);

                // producing large thumbnail
                using (var largeThumbMemStream = RecMemStreamMan.GetStream())
                {
                    // 206 x 206
                   // -------------- It breaks right here on this call -----------
                    await ResizeImage(masterlMemStream, largeThumbMemStream, MaxLargeThumbImageHeight,
                        MaxLargeThumbImageWidth,
                        ResizeMode.Crop, 
                        contentType);
                    fileRepository.AddFile(projectImage.LargeRemoteThumbFileName, contentType, largeThumbMemStream);
                }
                 
                // producing medium thumbnail
                using (var medThumbMemStream = RecMemStreamMan.GetStream())
                {
                    // 100 x 80
                    await ResizeImage(masterlMemStream, medThumbMemStream, MaxMedThumbImageHeight, MaxMedThumbImageWidth,
                        ResizeMode.Max, contentType);
                    fileRepository.AddFile(projectImage.MedRemoteThumbFileName, contentType, medThumbMemStream);
                }

                // producing thumbnail
                using (var newthumbMemStream = RecMemStreamMan.GetStream())
                {
                    // 32 x 32
                    await ResizeImage(masterlMemStream, newthumbMemStream, MaxThumbImageHeight, MaxThumbImageWidth,
                        ResizeMode.Pad, contentType);
                    fileRepository.AddFile(projectImage.RemoteThumbFileName, contentType, newthumbMemStream);
                }

                fileRepository.AddFile(projectImage.RemoteFileName, contentType, masterlMemStream);
            }
        private async Task ResizeImage(Stream originalStream, Stream newStream, int maxHeight, int maxWidth, ResizeMode fitMode, string contentType)
        {
            using (var image = Image.Load(originalStream))
            {
                IImageEncoder encoder;
                switch (contentType)
                {
                    case KnownMimeTypes.Jpeg:
                        encoder = new JpegEncoder();
                        break;
                    case KnownMimeTypes.Png:
                        encoder = new PngEncoder();
                        break;
                    case KnownMimeTypes.Bmp:
                        encoder = new BmpEncoder();
                        break;
                    case KnownMimeTypes.Gif:
                        encoder = new GifEncoder();
                        break;
                    default:
                        throw new NotSupportedException();
                }

                await Task.Run(() =>
                {
                    image.Mutate(context => context.Resize(new ResizeOptions()
                    {
                        Size = new Size(maxWidth, maxHeight),
                        Mode = fitMode
                    }));
                    image.Save(newStream, encoder);
                });
            }

            originalStream.Seek(0, SeekOrigin.Begin);
            newStream.Seek(0, SeekOrigin.Begin);
        }

System Configuration

  • ImageSharp version: beta6
  • Environment (Operating system, version and so on): Windows 10 (1803)
  • .NET Framework version: .NET Core 2.2

Activity

  1. chrisdrobison commented on Jun 4, 2019

    @chrisdrobison
    Author

    1559154999769

    Here is the image that it is failing on

  2. chrisdrobison commented on Jun 4, 2019

    @chrisdrobison
    Author

    If I pass the raw image into each resize operation rather than chaining the resize result down, everything works. But, I think you guys might want to know about this at any rate.

  3. JimBobSquarePants commented on Jun 5, 2019

    @JimBobSquarePants
    Member

    Thanks for raising this @chrisdrobison

    If you update to the latest build from MyGet you won't have this issue anymore. We fixed it a while back.

    However I do recommend some changes to your code as it is inefficient as it stands.

    You are much better loading the stream once and resizing that input image multiple times cloning the original using Clone instead of Mutate.

    I wouldn't wrap the synchronous ImageSharp methods in an allocating Task either. There's no benefit to be found there.

  4. chrisdrobison commented on Jun 5, 2019

    @chrisdrobison
    Author

    Thanks for the feedback. Do you have a timeline for releasing that to Nuget?

  5. JimBobSquarePants commented on Jun 6, 2019

    @JimBobSquarePants
    Member

    Not yet. ASAP though, I'm desperate to get it shipped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions