I need to load a PNG into a Texture2D and then read precisely the RGB values from each pixel.
However Unity is distorting it big time. I am sure the original PNG does not have a color profile embedded. And it is read perfectly, with the correct RGB values, by all the image viewers I tried
The RGB values printed are not the values present on the image. I created it myself using PngBitmapEncoder on Visual Studio (separate program) and am sure of the RGB values, which are well read by any image viewer (the test images have uniform color, so I can pick any pixel for test).
This may have to do with Texture2D.LoadImage() compressing the image to DXT5. Is there a way to disable compression on load? Test image attached, its uniform RGB values are 0, 154, 10. Unity reads 0, 146, 7
LoadImage uses ARGB32 for PNG files by default. It will only do compression if you use DXT1 or DXT5 as the format. Iâd start by omitting as much explicit info as possible and let Unity handle it.
Texture2D tex = new Texture2D(1, 1);
// LoadImage will default the format and resize the dimensions
text.LoadImage(fileData);
I started by being very âomissiveâ and frankly there was no difference in the results whatsoever. I guess LoadImage() supersedes everything.
I am transmitting many images per second through the network, so need to have compressed PNGs. I wish I could just let Unity handle it as you suggest, but it seems to mess up colors on load.
PNG supports lossless compression. Anyway it shouldnât matter. RGB values should be preserved. Unity can read (and display) the file but the values are a bit off.
Your Texture2D constructor is telling it to use mipmaps â Iâd change that to false. Also, add one more parameter, which tells it to use the linear (true) or sRGB (false) color space. I suspect the color space is responsible for the slight change in color youâre seeing.
I tried all the combinations already. But you are right, I should not have posted this code with mipmaps on. Also tried right now to change the color space from sRGB to linear and back. No change. My guess is LoadImage() supersedes all these parameters and forces a color space.
So, to give some further findings.
Loading a texture with loadimage results in graphics format with a value â88â. Its unnamed (its not a part of the enum!).
It happens regardless of textures original graphics format.
Texture format, on the other hand is overwritten to ARGB32
I presume this isnât intentional, since the texture seems to always end up compressed which renders LoadImage quite useless for a wide category of uses. The fact that â88â isnât even in the enum seems to point to a bug or an oversight too.
Well, if the image contains gamma information, Unity will use it to gamma correct the image. Since almost all png images usually have a gAMA chunk, pretty much all pngs would be affected in one way or the other. Though it depends on what gamma information has been stored. The PNG specification states:
I guess itâs not really a Unity issue since if gama correction information is present in an image, it should be used. When importing an image in Unity directly you actually have more options to control the import process compared to LoadImage.
Iâve written a PNG chunk parser some time ago which can be used to remove, insert or modify chunks in a png file. Note that in the case of the linked question the problematic bit was the gamma information. However itâs possible that other metadata could also cause issues. You could preprocess your image and remove unwanted chunks from the actual png file, or you could use it at runtime to strip out the unwanted chunks on the fly before passing the data to LoadImage
I would argue that it is a Unity issue.
If virtually all popular PNG file loaders (including ones from System.Drawing) as well as popular image editing programs (paint/paint.net/photoshop/gimp/aseprite) load the exact same RGB values and Unity doesnât, it should be either changed or documented in detail.
Importing an image in Unity is all fine and dandy, except when you donât have the image at build time. Modifying it using external tools is also somewhat of a solution⌠Except when itâs your users that are providing the image.
I would like to see this behavior either modified or clarified as intended in the documentation.
Especially the elusive âGraphicsFormat 88â. I will most likely raise an issue about this topic once I find a day to make a project to present it.