I’m observing an issue with image colours in Pro Tools being rendered too light. Anything drawn programatically is showing a different colour to if it’s drawing from an image. Only affects macOS. I have a small sample to illustrate the problem.
I’ve made an image where all pixels are RGB 127/127/127. I drop that into an ImageComponent which is in the centre of a plugin which flood fills itself in the paint call to the same RGB. I should not be able to see the image given it’s on a background the same colour. In Pro Tools though the image is rendering too light. You see a border of the correctly coloured background and a light central region which is the image.
You can see a comparison of the AAX vs a VST3 in Reaper, in Reaper it’s showing as expected but in Pro Tools there is a border because the image is rendered incorrectly.
If I enable an OpenGL context on the entire plug-in component then Pro Tools paints everything too light as opposed to just things from the image, as shown:
It suggests it’s nothing to do with the image format (I have tried using jpg and gif source files as well). I tried changing JUCE_USE_COREIMAGE_LOADER and this didn’t make a difference. The code is super simple:
Any clues why this could be? I’ve noticed this on other vendor’s plug-ins that use Juce, and it’s been an issue on earlier releases of Juce and Pro Tools for me but I’m trying to get to the bottom of this one now since I am moving away from OpenGL in my plug-ins and am getting inconsistencies between the image and drawn areas which is less tolerable than everything simply being slightly the wrong colour.
I tried all 4 permutations of the “Convert to sRGB” and “Embed Color profile” options in photoshop on a PNG export, so I don’t think it is that. (I also tried JPG and GIF with/without colour profiles). No change. Also this wouldn’t explain why when an OpenGL context is attached the entire UI draws the wrong colours in Pro Tools.
OK, but taking OpenGL out of the situation for a moment. If I load an image that is one colour (and the image has no colour profile), pull out a pixel value and then paint the background that colour and then draw the image on top of it, how could you possibly see two different colours in the combined rendering?
I can click through every colour profile on the iMac, the whole screen changes colours a little for different profiles, but the fact that in Pro Tools there are two different painted colours (background region vs image region) does not change, they stay relatively the same with respect to each other.
If I attach the GL context to only the image component, then the image component is drawn the same colour as the background (i.e. both the correct colour). So this suggests when Juce is drawing images in Pro Tools some kind of correction is being applied to them, but when you prevent that by attaching a GL context they come out the correct colour.
gl_context.attachTo(image_component);
Apply the GL context to the top level component and everything is consistent, but consistently the wrong colour.
I tried loading from the paint method, it made no difference (all of the 4 colour profile versions I saved out of Photoshop). I also tried loading straight from disk using PNGImageFormat().decodeImage instead of from the ImageCache in case that made a difference, but no change.
When you use only OpenGl, it display lighter meaning that the lighter color is when color profile is not applied.
Hence the issue here is that in Protools the color profile is not used for the image display but is for the fillAll.
I would step into the ImageComponent paint function see what differs in Protools
like in case of Protools, Image do not take into account the color profile of the display.
It ends up in a call to CGContextDrawImage (context, imageRect, image); in void CoreGraphicsContext::drawImage, I see no real evidence as I step through to that point that it’s doing anything suspicious to colour profiles, but am not too familiar with the APIs at this level.
This is actually a macOS/Color Profile issue… I dealt with this issue and a client last week… and to prove it’s not a JUCE issue I created a test app and demonstrated to them that drawing a Photoshop image inside of JUCE and also opening it in Preview shows the “wrong” color:
In this image is the PNG opened in Preview (top left) and painted in my JUCE app (top right) and a filled rectangle painted in JUCE (bottom right).
Color Toolkit shows the value for all three on Mojave on my iMac in the bottom 3 values. The PNG was created in Photoshop and the color is 0xFF12403B. Interestingly enough GIMP shows the color value in its picker as 0xFF12403B.
I tried adjusting the Color Profile on my iMac and it didn’t change the value.
If I do the same test using macOS Lion (10.7.5) in a Parallels VM then all colors show as 0xFF12403B on the same iMac.
I found that the issue begins in Pro Tools 2019.5, with releases before that this effect doesn’t show up (the UI draws correctly just like it does in other hosts). I also spotted a few isolated colour changes in their UI when targeting stuff with the macOS color meter app, so I guess they’ve changed something about how the UI is being drawn and this is having some colour space impact somehow.
Digging a bit deeper into how the colour spaces are handled in Juce I found that swapping out occurrences of CGColorSpaceCreateDeviceRGB() with CGColorSpaceCreateWithName(kCGColorSpaceSRGB) has helped. Testing is so far is quite limited but I did try an old 2013 retina MBP and new iMac with success so I have some confidence this is a reasonable thing to be doing. If anybody knows more about how this stuff actually works it could be helpful as this was a stab-in-the-dark solution somewhat.