I am working on a 2D app, which is used to analyze photo’s.
I ran into a rather big problem concerning jpg color space.
As i understand, a jpeg can have a different colorspace embedded than standard sRGB.
Different camera’s/imaging software, different color spaces.
I have been googling around and have been reading up on the subject, but before i have to go hardcore into color space conversion, i was wondering if anyone else has encountered this and if you perhaps have some pointers on how to get this done in Unity?
I should mention, that i am loading the images from disk into a RawImage. So i am looking for a way to detect the color space the image is in when i load it and then convert it before i show it.
In order to be able to handle jpg color spaces, i need to Decode the jpg.
Unity itself doesn’t provide tools for this, it assumes sRGB.
While looking for a solution, i found two things.
So far though i, have not been able to integrate these in my project.
The opensource library does not seem to be well documented and i have not added an external library before, so i feel i am stumbling in the dark. (i am more scripter than programmer)
When i try to add the namespace : System.Windows.Media.Imaging so i can use the .NET JpegBitmapDecoder, i am getting this error : error CS0234: The type or namespace name ‘Media’ does not exist in the namespace ‘System.Windows’ (are you missing an assembly reference?)
I will keep trying to integrate one of these in my project.
Any help is more than welcome
I think the build settings give a choice between .Net frameworks. The namespace referenced is in the 4.x framework but probably not in the .Net Standard 2.0 framework, perhaps you just want to change this build option?
Dumb thought but perhaps it’d be easier if you let Unity load the JPEG and you just use a JPEG library to read the colour space without decoding the image?
The problem is that color values are off with images that have an embedded color space when i don’t convert them to RGB first.
Before now, i was loading the image like this :
As you can see, colors on the left are not correct.
So i need to alter the byte[ ] bytes that make up the colors.
Even if i let Unity load the image.
I need info on it’s color space to translate colors… however i load it.
Or am i misunderstanding you?
When it comes to “System.Windows.Media.Imaging” not being accessible, i found something interesting.
In order to use these libraries, you have to add the corresponding dll’s to your Assets/Plugins folder.
I have managed to get “System.Drawing” working in my code.
Also learned a bit about using an alias to prevent conflicts.
so instead of the usual “using System.Drawing;”, you can use “using sd=System.Drawing;”
But “System.Windows.Media.Imaging” is not so simple.
There are several other dll’s that it needs. And it get’s messy when i try to add it all.
using ImageMagick;
.
.
.
private void LoadExternalImage(string path)
{
byte[] bytes;
using (MagickImage newMImage = new MagickImage(path))
{
// i have no idea about this profile, more interested in the second ..
newMImage.AddProfile(ImageMagick.ColorProfile.USWebCoatedSWOP);
// Adding the second profile will transform the colorspace from CMYK to RGB
newMImage.AddProfile(ImageMagick.ColorProfile.SRGB);
bytes = newMImage.ToByteArray();
}
Texture2D texture = new Texture2D(2, 2,TextureFormat.RGB24,false,false);
texture.LoadImage(bytes);
//
rawImage.texture = texture;
}
Colors of the loaded images are now correct.
Hope this helps someone.
Thanks for sharing your discoveries. I’ve just run into a similar problem. It appears that new iPhones embed Display P3 profile into saved JPGs making them look different when they’re imported into Unity (or views by image viewers that ignore color spaces).
So I wonder, did you manage to automatically detect whether the image has an embedded color profile or not? (Since there is no need for any color manipulation if the image is in good old sRGB)