Imagesharp: Image.Resize fails with InvalidCastException when Vector.IsHardwareAccelerated is false

Created on 22 Mar 2017  路  28Comments  路  Source: SixLabors/ImageSharp

Prerequisites

  • [x] I have written a descriptive issue title
  • [x] I have verified that I am running the latest version of ImageSharp
  • [x] I have verified if the problem exist in both DEBUG and RELEASE mode
  • [X] I have searched open and closed issues to ensure it has not already been reported

Description

using the function image.Resize returns an error no matter the values I try

Steps to Reproduce

using (Image image = new Image("whatever path to the pic here"))
{
    image.Resize(2240, 2240);                
}

System Configuration

  • ImageSharp version: 1.0.0-alpha4-00043 and 1.0.0-alpha4-00046
  • Other ImageSharp packages and versions: ImageSharp.Drawing 1.0.0-alpha4-00043
  • Environment (Operating system, version and so on): windows 10, visual studio 2017
  • .NET Framework version: 4.6
  • Additional information:

Error information:

ImageSharp.ImageProcessingException occurred
  HResult=0x80131500
  Message=An error occured when processing the image using ResizeProcessor`1. See the inner exception for more detail.
  Source=ImageSharp
  StackTrace:
   at ImageSharp.Processing.ImageProcessor`1.Apply(ImageBase`1 source, Rectangle sourceRectangle)
   at ImageSharp.Image`1.ApplyProcessor(IImageProcessor`1 processor, Rectangle rectangle)
   at ImageSharp.ImageExtensions.Resize[TColor](Image`1 source, Int32 width, Int32 height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, Boolean compand)
   at ImageSharp.ImageExtensions.Resize[TColor](Image`1 source, Int32 width, Int32 height, IResampler sampler, Boolean compand)
   at ImageSharp.ImageExtensions.Resize[TColor](Image`1 source, Int32 width, Int32 height)
   at CatalogLib.ImgSharpCreator.Start(FileInfo workFile) in E:\dev\vs\Catalog\CatalogLib\ImgSharpCreator.cs:line 86
   at WPFCatalog.MainWindowViewModel.Start() in E:\dev\vs\Catalog\WPFCatalog\MainWindowViewModel.cs:line 89

Inner Exception 1:
AggregateException: One or more errors occurred.

Inner Exception 2:
InvalidCastException: Unable to cast object of type 'System.UInt32[]' to type 'System.Single[]'.



Most helpful comment

Latest of .NET Native finally has support for hardware acceleration of vectors so it'll be a nice bump for folks on UWP. You can see more under .NET Native in these release notes: https://blogs.msdn.microsoft.com/dotnet/2017/01/30/announcing-net-core-net-native-and-nuget-updates-in-vs-2017-rc/

All 28 comments

madd4384
This is the image I'm trying to run the application against, I hope the upload didn't mess up the metadata or other stuff

I've tested the above code with stream, byte[] and filepath variations and I'm not getting any error whatsoever. @MaddoScientisto Can you share the WPF application code?

@blackcity @Raja4567 Thanks for stepping in here btw. It's absolutely amazing getting help triaging issues from the community at large. 馃挴

I'm using the filepath, as for sharing the code... that might be complicated because it's a large, complex and messy project

this sounds like its going to be something inside the Color specific BulkPixelOperations<Color> its the only time I can see us doing a uint[] to float[] conversion.

my guess is its around this line https://github.com/JimBobSquarePants/ImageSharp/blob/69daa8464a30a62d5901d986a3ab620bbbbcff34/src/ImageSharp/Colors/Color.BulkOperations.cs#L66

@tocsoft just wanted to post the same ;)

@MaddoScientisto few questions:

  • Can you share the stack trace of Inner Exception 2?
  • Is the same exception thrown when the image width is <1024?

here's the stacktrace of the inner exception 2:

   at System.Numerics.Vector`1.CopyTo(T[] destination, Int32 startIndex)
   at ImageSharp.Color.BulkOperations.ToVector4SimdAligned(BufferSpan`1 sourceColors, BufferSpan`1 destVectors, Int32 count)
   at ImageSharp.Color.BulkOperations.ToVector4(BufferSpan`1 sourceColors, BufferSpan`1 destVectors, Int32 count)
   at ImageSharp.Processing.Processors.ResizeProcessor`1.<>c__DisplayClass2_5.<OnApply>b__1(Int32 y)
   at System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.<ForWorker>b__1()
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
   at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )

Still happens with a 600x600 picture

I now upgraded to 1.0.0-alpha4-00046, still got the issue

@MaddoScientisto there's no need!
What is the value of Vector.IsHardwareAccelerated on your machine?

Update based on a gitter chat
I've update the title to reflect our findings thus far... issues seams to be related to Vector.IsHardwareAccelerated being false.

I'm getting the same - code on alpha2 was working fine.

At the moment I only have a stack trace from Azure / AppInsights, will repro locally shortly:

``` An error occured when processing the image using ResizeProcessor1. See the inner exception for more detail.One or more errors occurred. (Unable to cast object of type 'System.UInt32[]' to type 'System.Single[]'.)Unable to cast object of type 'System.UInt32[]' to type 'System.Single[]'.

ImageSharp.Processing.ImageProcessor1.Apply(ImageBase1 source, Rectangle sourceRectangle)
ImageSharp.Image1.ApplyProcessor(IImageProcessor1 processor, Rectangle rectangle)
ImageSharp.ImageExtensions.ResizeTColor
ImageSharp.ImageExtensions.ResizeTColor
(my code here)
[external code]
Microsoft.ApplicationInsights.AspNetCore.ExceptionTrackingMiddleware.d__4.MoveNext()
````

My code:

````
// byteStream is a MemoryStream containing a JPG
image = new ImageSharp.Image(byteStream);

// ...

var thumb = image
.Crop(new Rectangle((int)request.Crop.X, (int)request.Crop.Y, (int)request.Crop.Width, (int)request.Crop.Height))
.Resize(256, 256);
````

@kierenj i'm pretty sure if you set your azure website to run in x64 mode on the 'Application Settings' screen it should resolve your issue. In general you will find that ImageSharp will run faster in x64 processes as we can then make use of SIMD options via System.Numerics.Vectors which only works via the x64 RyuJit jitter.

Interesting update!

This file fails: https://dl.dropboxusercontent.com/u/18385630/MSZ-7.jpg
This file works: https://dl.dropboxusercontent.com/u/18385630/freshfield_lane_richmond_blend_red_brick.jpg

Thanks for the recommendation @tocsoft, will look into it

Should be fixed with the next new package release. (1.0.0-alpha5-00036)

@MaddoScientisto @kierenj Can you check the situation with your bad (32 bit?) configs where Vector.IsHardwareAccelerated == false?

I work on the .NET Native compiler team and this looks similar to other crashes we've had reported and think is fixed on latest of our tools. If someone has a repro and VS 2017 here's an experiment:

  • Open the nuget package manager
  • Select the package for Microsoft.NETCore.UniversalWindowApplication (aka the UWP metapackage)
  • Update to 5.3.1
  • Rerun the repro

5.3+ of that package will cause you to be built targeting the latest runtime and compilers from us (v1.6). I'm somewhat optimistic that it will cause this issue to disappear but if you discover it doesn't I'm happy to help investigate.

Thanks @MattWhilden , We've just pushed some updates which we think should fix our immediate issue, If it's not the case any help would be really appreciated 馃憤

I'll keep an eye on the issue but feel free to ping me directly or send a mail to [email protected].

@MattWhilden So it happened sometimes on 64bit ~RyuJIT~ runtime? I could only reproduce it by forcing a 32 bit build. Or was this UWP specific?

Our reporters were all .NET core server users AFAIK.

Oh goodness me. Somehow I read this as a UWP related issue. Sorry to have added confusion. Happy to route things either way (the RyuJIT and CoreCLR folks sit on the same floor :-) ).

Some more info that's probably not super relevant: In the default config for UWP, DEBUG will build/run against CoreCLR (which has the RyuJit code generator). RELEASE will build/run against the .NET Native stack. If you discover issues with one and not the other then it's probably an issue on our (the broader .NET team) side and we'd love to be able to get it corrected.

Yeah my comment was also really confused, nevermind it,

I think I get it now:
similar issues used to happen on the Native runtime too .. but this is not the case anymore :)

If this also means that all the System.Numerics.Vectors stuff is SIMD accelerated on .NET Native now, it should be really good news for ImageSharp UWP users because we heavily rely on SIMD optimizations :)

Latest of .NET Native finally has support for hardware acceleration of vectors so it'll be a nice bump for folks on UWP. You can see more under .NET Native in these release notes: https://blogs.msdn.microsoft.com/dotnet/2017/01/30/announcing-net-core-net-native-and-nuget-updates-in-vs-2017-rc/

@antonfirsov I'm due to set up another Azure environment for this project soon, so will set it up as 32-bit first, try this, and report back. May be in a few days' time but will keep you in the loop. Thank you

Hey @kierenj did you ever manage to get the test environment set up? We'd really like to be able to close this.

I'm getting the issue again, on the live environment - an Azure App Service running in 64-bit mode. That's 1.0.0-alpha4-00048 though. I'll try 32-bit on latest alpha on the prototype version and report back in a few minutes ..

(Update: breaking changes between alphas, ...)

Ok, cool, 1.0.0-alpha5-00036 looks to work on both 64-bit and 32-bit mode. Not sure why alpha4 stopped working in 64-bit mode (it seemed to work for a while), but it did. Maybe random chance.

Sneaky question - new Image constructor overloads don't take Streams. If I do a private static readonly Configuration _isConfig = new Configuration(new BmpFormat(), new GifFormat(), new JpegFormat(), new PngFormat()); and Image.Load(_isConfig, stream) is that fairly close to "best-practise"? Thanks.

All good for me :+1:

That's way of using Image.Load is exactly the way you want to be doing it if you want/need a custom config.

I don't care about a custom config, but there's no overload in the latest alpha which just takes a Stream.. unless I'm missing something?

Looks like this is fixed as of 1.0.0-alpha5-00036 so closing.

Was this page helpful?
0 / 5 - 0 ratings