-
-
Notifications
You must be signed in to change notification settings - Fork 426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(Major issue) Pixel integrity loss across all formats for both save and load #513
Comments
Do you have a sample image that I can use to reproduce this issue? And does |
Here is a clean EXR, and a .r32 which is just a binary float array. You can use As for previous versions, I meant that this issue is present in the last 6 releases as well. I rolled back to see if maybe it was something in the newer version. I didn't notice this until now because I was dealing with high frequency images and this is more visible with low frequency shapes. If you need a 3D visualizer, let me know. I can email you some a private build. Thanks so much, Dirk! Really appreciate the fast response! |
Should I make a standalone sample application if you want to see the entire chain of code? |
I am now just looking at our code to see if I can find an explanation for this. For formats that don't have floating point precision it is logical that you will not get this kind of detail. Will need to take a good look at our exr coder to see if we do anything odd there. And it would be helpful if I have something to view the result of the operations. |
You got it. I'll prepare an app and send it to you in a couple of hours. |
Since some of the code and the visualizer is not open source, I've just emailed you the details. |
Tonight I focused mostly on EXR and it turns out that we can only read and write the image with half float (16-bit float) instead of a 32-bit float. We are using a C Api that only provides us with an RGBA version of the file. But with your test file ( And for the tiff coder you will need to set the bit depth to 32 bit to make sure you are writing floats to the file. But the Magick.Native library currently does not allow you to specify a depth higher than the quantum depth so you cannot do that now I will need to make a patch for that in the Magick.Native library to make this possible and then publish a new release of Magick.NET. And I think you don't need to use |
Good to know, thank you! Please don't do anything complicated on my account. Since we need the whole floats asap, I think we will switch to OpenImageIO for EXR for now. TIFF bitness and EXR coder rewriting can be done later or at all at your discretion, no problem! :) Btw, any idea why loading and resaving the EXR further degrade the values? Is it because it gets converted to float and then to half float again? |
Also, just to confirm, MagickImage's pixel cache has no problems with 32-bit floats? The loss of integrity is only in the file formats and their encoders, not with ImageMagick/Magick.NET itself? I ask because we still use it for plenty of internal processing and the output always goes back to pure floats, never to file. |
When an 32-bit EXR file is loaded the values are converted from 32-bit floats to 16-bit floats and then back to 32-bit float inside ImageMagick. Then when the file is saved the 32-bit values are changed into 16-bit and saved to the file. Then when that file is loaded those 16-bit values are changed into 32-bit in ImageMagick and back to 16-bit when the image is saved to EXR. I think we keep are getting some information loss when those conversions happen. I will not rewrite the encoder and decoder of EXR at this moment and maybe do that in the future. The fix for setting the depth of a MagickImage will be fixed the next release. The pixels cache of MagickImage is 32-bit floats for the Q16-HDRI build so you are correct that the loss of integrity only happens when we pass the data to the encoders inside ImageMagick. |
Just a little note for anyone who may stumble upon this later - 32-bit PFM format works beautifully with ImageMagick. We're using that for now to store the Magick data and convert it using an external tool (OpenImageIO's oiiotool.exe) to EXR. Just set: |
Support for writing 32-bit tiff files is now available in the new release (7.14.4.0). Closing this issue for now. |
Description
I have a single-channel linear grayscale image that contains a very low-octave (smooth) Perlin noise as float[] (range of 0..65535) which is converted to ImageMagick using
SetPixelsUnsafe().SetPixels()
.For the purposes of illustrating the gentle grades that are not perceivable to the human eye, I've shown the data as 3D heightfields.
When the image is saved, it shows loss of integrity in the form banding and moire patterns on the smooth structure. It happens regardless of format (PNG, TIFF, and even OpenEXR). PNG, etc can be lossy so that's understandable - even PNG64, maybe even TIFF, but EXR is meant for high precision storage of floats.
I suspected that my source data must be bad, so I saved the float[] to a binary file, loaded it in a 3rd party application. The image looked clean. I saved an OpenEXR from that application of the same data, and it looked clean too. Then I loaded that EXR into IM and it had banding artifacts.
Original data (visualized in 3rd party application)
Saved by Magick.NET
Recursive integrity loss
But it gets worse. Each load/save pass of the same images loses data integrity further.
This image shows the clean EXR brought into Magick.NET. It immediately shows banding.
Then I save that EXR via Magick.NET to EXR, and load it back, the banding has become more intense.
To double-check, I loaded the data back into the 3rd party visualizer, and the banding has intensified indeed.
Problem is with File I/O, not with Magick 'itself'
To rule this out, I loaded the clean float[] data into IM, then got the pixel data out as float[] to take to 3rd party application for confirmation, and it was clean. This leads me to believe that floats are being quantized, truncated, or somehow losing integrity while saving and loading. Directly pushed pixels that were generated on the fly retain 100% integrity.
I checked with both multi-channel and single-channel images. Problem persists in both. It also is the same whether using scRGB or LinearGray color spaces.
Steps to Reproduce
Dozens (if not a hundred+) of my users have diligently done tests and confirmed this issue.
System Configuration
Magick.NET-Q16-HDRI-OpenMP-x64 7.14.3.0
Windows 10
Has existed in the last ~6+ releases
Issues #376 and #479 MAY be stemming from this issue.
The text was updated successfully, but these errors were encountered: