You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
JpegEncoder producing incorrect output on windows-arm (was working on beta0005) #1275
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 already found the issue #871 which seems to be resolved, but as the issue was for linux-arm this one is maybe specific to windows-arm.
On beta0005, the image was saving correctly, on rc3 it is kinda grayish with squares.
Original image:
Resized image:
Steps to Reproduce
Just loading and saving the image:
// Loading originalImage
using (var targetImage = new MemoryStream())
{
using (var image = SixLabors.ImageSharp.Image.Load(originalImage))
{
image.SaveAsJpeg(targetImage);
}
}
// Saving targetImage
System Configuration
ImageSharp version: 1.0.0-rc0003
Other ImageSharp packages and versions: N/A
Environment (Operating system, version and so on): Windows 10 IoT Core 10.0.17763.1217
.NET Framework version: UWP - Windows 10, version 1903
Additional information: Application running on Raspberry PI 3 B / ARM architecture
@peter-bozovic Well for one it's weird that you're seeing this both in DEBUG and RELEASE modes on UWP, as those use two completely different runtimes (UWP-flavored .NET Core 2.1-like runtime in DEBUG vs. .NET Native in RELEASE). First thing, what I would suggest is to first try to isolate the issue a bit more, eg.:
You haven't specified this, I assume you did check to be using the latest .NETCore-UWP lib? That'd be 6.2.10 I think.
Can you repro this with another framework? Eg. does this happen with a .NET Core 2.1/3.1 or .NET 5 console app too?
Can you try this with the previous RC builds too, to see if this has been there for a while or somehow started recently?
Yes, it's weird and sorry for such specific configuration where I found it :(
About the Relase, I'm building it without the "Compile with .NET native tool chain", so it's probably not using the .NET Native. I don't know if it's the limitation of the Windows IoT Core, or the ARM architecture, but with that option, the app doesn't build.
I don't know where to check the .NETCore-UWP ? I'm using the "Universal Windows" app project type and all I see are Min and Target versions for the SDK. It doesn't mention anywhere .NET Core or .NET Framework.
Yes, I have tested the .NET 4.5 console app and it works correctly. It also works on ASPNET Core 3.1 API website.
About other versions of the library:
beta0006
beta0007
rc0001 & rc0002 - they are the same size, assuming they produce same result
rc0003 produced few kb smaller file (in the initial post)
About the Relase, I'm building it without the "Compile with .NET native tool chain", so it's probably not using the .NET Native. I don't know if it's the limitation of the Windows IoT Core, or the ARM architecture, but with that option, the app doesn't build.
Mh, that kinda sounds similar to #1204, in fact I've had to drop the ARM arch in my UWP app as well as I just couldn't get it to work fine with .NET Native using the latest RC builds of ImageSharp. I wonder if these two issues are somewhat related 🤔
As for the .NETCore-UWP package, you need to open the NuGet packages window for your UWP app and check this one:
Make sure you have the latest version installed, just to be extra sure.
Besides, staying up to date is always great regardless of ImageSharp issues 😄
Ah yes, didn't see it in the list since it was filtered with "ImageSharp", daaah !
It's 6.2.10 :)
Sorry about the #1204, I just found for you the ARM32 architecture with Windows :D
And guess what, when I removed ImageSharp from our main solution, it's building for relase with .NET native !
ImageSharp was the culprit ...
Not good for those who really wants .NET native, but good to know there's workaround with disabling this build option ...
Yes that's the same thing I noticed, there's something in ImageSharp that's causing issues with the .NET Native compiler. I mean, that's not all that surprising considering the huge amount of heavily generic code that ImageSharp uses, that's one of the most difficult things to handle for a fully AOT compiler, in fact we've already had similar issues in the past (though those have been resolved thankfully, see #828). Right now I can't personally complain though, at least the crash seems to be isolated on ARM32, as all other archs are building just fine in UWP (including with .NET Native) as far as I can tell.
Your best bet at this point would probably be to either wait for Tom to chime in, or to prepare a .NET Native repro for the ARM32 build error (see the guide here) and send that to the .NET Native team for them to investigate 👍
@peter-bozovic can you please try saving out your test case in alternative formats, i.e. save as png/bmp too... just to verify that it is definitely the encoder and not the decoder that's at fault.
@JimBobSquarePants the change is quite small, wouldn't be sufficient I'm afraid. For the sake of investigation I would rather suggest testing out more aggressive changes:
(The changes already in place)
Wire out .AsSpanUnsafe() and PixelOperations<TPixel>.Instance.ToRgb24() doing dumb, safe & slow conversion
Remove all Unasafe.* trickery from LoadAndStretchEdges
Even consider NoInling on the block indexer
We can then test different permutations of 0-3 on different branches to find the root cause, and decide what goes into product code in the end.
@antonfirsov I'd like to get 0 tested first before attempting anything else.
Update
Looking at AsSpanUnsafe(). I cannot see anything that could corrupt memory there; everything looks stack only. I've updated the constraint of GenericBlock8x8<T> to use unmanaged to ensure the type parameter is though (I know everything we pass is unmanaged but convention is king) as I don't know whether the runtime helpers in the Span<T> constructor exist in earlier target frameworks. It's unfortunate MemoryMarshal.CreateSpan only exists in later targets.
I've updated our method implementation to use that where we can in the branch.
I had to deploy to the pi to replicate, you can just set the PI as a remote debug target for UWP apps and debug that way, its still should still just be an F5 debug experience
Should I be targeting x86? I assumed ARM64 since the issue title specifically mentions ARM and you can't build ARM32 but that didn't allow me to install.
Also what folder did you load/save the images to? I'm attempting to use the following but I don't want to keep getting it wrong as building the app takes a lifetime.
privateasyncTaskInitAsync(){StorageFolderpicturesFolder=KnownFolders.PicturesLibrary;if(string.IsNullOrWhiteSpace(picturesFolder.Path)){// Fallback for running in VSpicturesFolder=KnownFolders.SavedPictures;}using(varoutStream=awaitpicturesFolder.OpenStreamForWriteAsync("1275.jpg",CreationCollisionOption.ReplaceExisting).ConfigureAwait(false))using(varinStream=awaitpicturesFolder.OpenStreamForReadAsync("1275.png").ConfigureAwait(false)){using(varimage=awaitISImage.LoadAsync(inStream).ConfigureAwait(false)){awaitimage.SaveAsJpegAsync(outStream).ConfigureAwait(false);}}}
To be fair I didn't save the image to disk I cheated and just rendered to as an image to the screen. This is what I used to reproduce https://github.com/tocsoft/ImageSharpUwpArmIssueRepro it has an image control on the screen and I just render/display it in the constructor
I can't remember exactly what settings I ended up with, I just chose the device using the debug dropdown, I think I chose remote and it popped up a screen to pick the device, once I did this VS just changed the settings as required for the device. Only add thing i ended up needing to do was force image sharp to be release build and the uwp app to be debug (I couldn't get it to attach the debugger if memory served) ... also needed to reduce target frameworks down to netstandard1.3 only as it seemed to have been getting confused with the multiple frameworks being defined.
I am confused on how you are trying to run it... all I did was was hit debug from VS I never tried 'installing' it or anything like that just ran from VS targeting the PI and it just work. I might have had to run it from right clicking the project and starting it from there but nothing too unusual.
I've been trying to do it via Visual Studio but I keep hitting the following issue.
Failed to connect to device '127.0.0.1' using Universal Authentication. Please verify the correct remote authentication mode is specified in the project debug settings.
So I thought I'd deploy direct to see if anything works.
Activity
JimBobSquarePants commentedon Jul 14, 2020
@Sergio0694 @MattWhilden This um... This looks right up your street.
Sergio0694 commentedon Jul 14, 2020
@peter-bozovic Well for one it's weird that you're seeing this both in
DEBUGandRELEASEmodes on UWP, as those use two completely different runtimes (UWP-flavored .NET Core 2.1-like runtime inDEBUGvs. .NET Native inRELEASE). First thing, what I would suggest is to first try to isolate the issue a bit more, eg.:6.2.10I think.@JimBobSquarePants FYI Matthew is no longer in the .NET Native team (😢), pinging @tommcdon for more info 👍
peter-bozovic commentedon Jul 14, 2020
Yes, it's weird and sorry for such specific configuration where I found it :(
About the Relase, I'm building it without the "Compile with .NET native tool chain", so it's probably not using the .NET Native. I don't know if it's the limitation of the Windows IoT Core, or the ARM architecture, but with that option, the app doesn't build.
I don't know where to check the .NETCore-UWP ? I'm using the "Universal Windows" app project type and all I see are Min and Target versions for the SDK. It doesn't mention anywhere .NET Core or .NET Framework.
Yes, I have tested the .NET 4.5 console app and it works correctly. It also works on ASPNET Core 3.1 API website.
About other versions of the library:
beta0006

beta0007

rc0001 & rc0002 - they are the same size, assuming they produce same result

rc0003 produced few kb smaller file (in the initial post)
Sergio0694 commentedon Jul 14, 2020
Mh, that kinda sounds similar to #1204, in fact I've had to drop the ARM arch in my UWP app as well as I just couldn't get it to work fine with .NET Native using the latest RC builds of ImageSharp. I wonder if these two issues are somewhat related 🤔
As for the .NETCore-UWP package, you need to open the NuGet packages window for your UWP app and check this one:
Make sure you have the latest version installed, just to be extra sure.
Besides, staying up to date is always great regardless of ImageSharp issues 😄
peter-bozovic commentedon Jul 14, 2020
Ah yes, didn't see it in the list since it was filtered with "ImageSharp", daaah !
It's 6.2.10 :)
Sorry about the #1204, I just found for you the ARM32 architecture with Windows :D
And guess what, when I removed ImageSharp from our main solution, it's building for relase with .NET native !
ImageSharp was the culprit ...
Not good for those who really wants .NET native, but good to know there's workaround with disabling this build option ...
JimBobSquarePants commentedon Jul 14, 2020
Well no... No it wasn't. A bug/limitation in the compiler is responsible for any issues, not this library.
I'd really like to see issues like this fixed upstream. We can only build upon what the framework(s) provide us.
Sergio0694 commentedon Jul 14, 2020
Yes that's the same thing I noticed, there's something in ImageSharp that's causing issues with the .NET Native compiler. I mean, that's not all that surprising considering the huge amount of heavily generic code that ImageSharp uses, that's one of the most difficult things to handle for a fully AOT compiler, in fact we've already had similar issues in the past (though those have been resolved thankfully, see #828). Right now I can't personally complain though, at least the crash seems to be isolated on ARM32, as all other archs are building just fine in UWP (including with .NET Native) as far as I can tell.
Your best bet at this point would probably be to either wait for Tom to chime in, or to prepare a .NET Native repro for the ARM32 build error (see the guide here) and send that to the .NET Native team for them to investigate 👍
tocsoft commentedon Jul 14, 2020
@peter-bozovic can you please try saving out your test case in alternative formats, i.e. save as png/bmp too... just to verify that it is definitely the encoder and not the decoder that's at fault.
peter-bozovic commentedon Jul 14, 2020
Saving to PNG was working fine
JimBobSquarePants commentedon Jul 15, 2020
I'll be something to do with the way we translate from
Rgbr32toRgb24. I'm curious. @peter-bozovic Does usingImage<Rgb24>work with jpeg?24 remaining items
JimBobSquarePants commentedon Jul 29, 2020
@antonfirsov That and the
RgbToYCbCrTablescode has rewritten in my branch.https://github.com/SixLabors/ImageSharp/compare/js/simplify-jpeg-encoder
I've made a point of refactoring the code to use the indexers and methods we use successfully during decoding.
I wanted @brianpopow to check that there were no regressive issues caused by my changes.
antonfirsov commentedon Jul 29, 2020
@JimBobSquarePants the change is quite small, wouldn't be sufficient I'm afraid. For the sake of investigation I would rather suggest testing out more aggressive changes:
.AsSpanUnsafe()andPixelOperations<TPixel>.Instance.ToRgb24()doing dumb, safe & slow conversionUnasafe.*trickery fromLoadAndStretchEdgesNoInlingon the block indexerWe can then test different permutations of 0-3 on different branches to find the root cause, and decide what goes into product code in the end.
JimBobSquarePants commentedon Jul 29, 2020
@antonfirsov I'd like to get 0 tested first before attempting anything else.
Update
Looking at
AsSpanUnsafe(). I cannot see anything that could corrupt memory there; everything looks stack only. I've updated the constraint ofGenericBlock8x8<T>to useunmanagedto ensure the type parameter is though (I know everything we pass is unmanaged but convention is king) as I don't know whether the runtime helpers in theSpan<T>constructor exist in earlier target frameworks. It's unfortunateMemoryMarshal.CreateSpanonly exists in later targets.I've updated our method implementation to use that where we can in the branch.
JimBobSquarePants commentedon Aug 6, 2020
@tocsoft How did you get the issue to replicate locally?
I'm running via Visual Studio in Release mode x86 and cannot get my custom branch to replicate.
I can try deploying to the PI I bought to fix this but I'd rather work locally if I can.
tocsoft commentedon Aug 6, 2020
I had to deploy to the pi to replicate, you can just set the PI as a remote debug target for UWP apps and debug that way, its still should still just be an F5 debug experience
JimBobSquarePants commentedon Aug 6, 2020
Ok thanks!
Should I be targeting x86? I assumed ARM64 since the issue title specifically mentions ARM and you can't build ARM32 but that didn't allow me to install.
Also what folder did you load/save the images to? I'm attempting to use the following but I don't want to keep getting it wrong as building the app takes a lifetime.
tocsoft commentedon Aug 6, 2020
To be fair I didn't save the image to disk I cheated and just rendered to as an image to the screen. This is what I used to reproduce https://github.com/tocsoft/ImageSharpUwpArmIssueRepro it has an image control on the screen and I just render/display it in the constructor
I can't remember exactly what settings I ended up with, I just chose the device using the debug dropdown, I think I chose remote and it popped up a screen to pick the device, once I did this VS just changed the settings as required for the device. Only add thing i ended up needing to do was force image sharp to be release build and the uwp app to be debug (I couldn't get it to attach the debugger if memory served) ... also needed to reduce target frameworks down to netstandard1.3 only as it seemed to have been getting confused with the multiple frameworks being defined.
JimBobSquarePants commentedon Aug 6, 2020
This is the result of an attempted installation with ARM with "Compile with .NET native tool chain" turned off.
OK... I'm stumped. I need idiot proof instructions for how to get this on my device.
tocsoft commentedon Aug 6, 2020
I am confused on how you are trying to run it... all I did was was hit debug from VS I never tried 'installing' it or anything like that just ran from VS targeting the PI and it just work. I might have had to run it from right clicking the project and starting it from there but nothing too unusual.
JimBobSquarePants commentedon Aug 6, 2020
I've been trying to do it via Visual Studio but I keep hitting the following issue.
So I thought I'd deploy direct to see if anything works.
JimBobSquarePants commentedon Aug 6, 2020
Ok... I'm up and running and can replicate. I'll see what I can do....
Don't use RGB. Fixes #1275
JimBobSquarePants commentedon Aug 6, 2020
Ok.... Looks like I've fixed it. Tested both
Rgba32andRgb24and everything is working.I'm going to open a PR using the branch I've been testing with which quite a few changes to the encoder which make it easier to debug.
I only bought the one Raspberry PI (I'm gonna get another) so @brianpopow will need to double check my fix on Linux.
brianpopow commentedon Aug 7, 2020
I have just tested it on Linux + ARM. Works fine, no problems.