Light mode, Dark mode, LUTs, and blending. #3914
Replies: 8 comments 32 replies
-
Update: the original vispy PR while functional, was totally misimplemented by modifying auto-generated files. I've not been able to figure out the proper path—nor had much time to do so—so it's DOA at the moment. |
Beta Was this translation helpful? Give feedback.
-
Hi @psobolewskiPhD, so sorry this post hasn't gotten a lot of engagement yet! I'm definitely very supportive of getting the light mode and inverse lookup tables working well in napari. It looks like vispy/vispy#2320 just got merged which may be an important step!! Can you give an update here on how you think we should best move forward this (or point to another more recent convo, which I may have missed). Thanks!! |
Beta Was this translation helpful? Give feedback.
-
Going to bump this, because the GL_PRESETS bug in vispy fix has been merged (❤️ @brisvag ) so that is likely to be in a vispy release in the near future.
Now a PR to implement nr 2 on the list above is easy, because i've been using it for some time. I figure I would just need to write some tests. |
Beta Was this translation helpful? Give feedback.
-
Regarding No. 2 above and colormaps, I've made a colormap manager widget:
I have some thoughts to add a way to make a colormap from an RGB image, ala this twitter thread: |
Beta Was this translation helpful? Give feedback.
-
Updating the status of this Discussion. Here's the checklist from above:
Minimum blending along with a handful of inverted colormaps (ChrisLUTs) are in 0.4.17 #4875 I think the rest of the points regarding colormap management and/or importing ImageJ colormaps are sort of a new discussion/issue. Likewise better saving of rendered composites at full resolution via |
Beta Was this translation helpful? Give feedback.
-
So thinking out-loud here:
For a multi-channel image, this can be addressed by making the bottom-most layer So, what if instead we just make the bottom-most visible layer always use |
Beta Was this translation helpful? Give feedback.
-
Instead of changing the blending altogether, it seems like we could handle this on the vispy side and simply change the gl context as appropriate. This would also make it possible/easier to allow both translucent and translucent_no_depth at the bottom. Do you have a hunch on what exactly inside the |
Beta Was this translation helpful? Give feedback.
-
Status update: On knockoff effect: for splitting multichannel and our sample images, we have been using translucent for the base and additive for the rest—this was implemented to guard against blending with canvas. This is slightly annoying if you choose to reorder the layers, but no longer needed because of the new behavior of overriding the bottom visible layer blending mode. Remaining things and tangents:
|
Beta Was this translation helpful? Give feedback.
-
Based on the discussion at the Community Meeting (05.01.2022, napari/meeting-notes@eadff94) I wanted to get some thoughts down.
First aspect, the Light theme canvas
Napari offers two themes by default, one Light and one Dark. The light theme has a white canvas (255, 255, 255), which makes additive blending fail, because adding to 255 just clips to 255. This was first, I think, documented by @Czaki here:
#2140
and again by me here—at the time I didn't realize the nature of the problem:
#3374
As can be seen, in Light theme, the canvas combined with default additive blending mode ends up problematic because it can make the user think there is a bug or issue with the file if they use default opening parameters: don't specify a non-additive blending mode. Worse yet, many users, especially new ones, may not be fully aware of blending modes and blending in general. I didn't get it until @kevinyamauchi prompted me to change blending modes and I started thinking about it. Plus, this occurs even with 1 layer, making the blending issue even less intuitive, the fact that napari blends with canvas is not obvious.
In my opinion—and as was noted in the Community Meeting—the behavior in Light and Dark themes would be the same, so the user doesn't note a change. This would require both themes to have the same canvas, for example, or to not blend with canvas at all. The simplest work around at the moment, in this spirit, is to make the bottom most layer have blending
opaque
and then useadditive
for the rest.Second aspect, inverted LUTs
But! the above fix still only works for conventional LUTS: color on black. At the moment, the use of multiple inverted LUTs in napari is problematic, regardless of Light vs Dark mode. The default napari colormaps only include one such LUT:
gray r
but a number of such LUTs are becoming commonly used, popularized to a degree by @cleterrier see: https://twitter.com/search?q=%23invertedLUT andhttps://github.com/cleterrier/ChrisLUTs
(Note: napari by defaults ships with 3 BOP LUTS from ChrisLUTs)
Personally, I find the inverted LUTs very pleasing when working during the day, with light mode OS, but the behavior in napari is problematic, again due to blending, regardless of mode, because of additive blending between layers. In Dark mode only rears its head with multiple inverted LUTs blended.
Some code to try (should be able to paste into the console)
In Dark mode you should see just a hint of the image in pink. If you toggle vis from top to bottom, you will slowly reveal the bottom layer. Again, additive blending here is making virtually everything white. At best you can try to set blending to
translucent
and play withopacity
but it's not ideal.If you use the conventional LUTs:
You will see the expected behavior where the composite is properly formed and everything works as expected.
If you then try to use Light mode napari with the inverted LUTs, the current behavior of blending to the canvas 255 again crops up, but setting
opaque
doesn't really help.So for working with inverted LUTs a different blending mode between layers is needed. There are a few options, such as subtractive blending or minimum. Extensive discussion in the context of ImageJ can be found here:
https://forum.image.sc/t/multi-channel-composite-view-with-inverted-luts-in-imagej-fiji/61163/49
For subtractive blending, @kevinyamauchi implemented one option here:
#3910
Alas, again option only works for conventional LUTs and only in Light mode, because with inverted LUTs you just subtract down to zero and get a black square. Also, this mode of subtraction inverts the colors—see the PR above for examples.
An alternative is to invert before subtracting:
This works, but results in an artifact that I think is due to clipping. Here's a zoom of I_Blue layer:
Versus
opaque
which should be "ground truth" here:(opacity also doesn't work as expected, but that may be fixable with a bit of play.)
A slightly different option:
It's a bit saturated, but better than clipped I would say:
An alternative option is to use
minimum
blending. That requires a vispy PR (being brave!): vispy/vispy#2282to add the GL_MIN and GL_MAX modes.
The flaw with this one it selects the MIN of R, G, B independently, if I am understanding the docs right (https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendEquation.xhtml) so you tend to just get black where it's "blending" multiple channels:
Beta Was this translation helpful? Give feedback.
All reactions