# Gamma correction for colormaps

**URL:** <https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227>\
**Category:** Specific Domains\
**Tags:** makie, makielayout\
**Created:** [August 28, 2021, 3:40pm UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227 "2021-08-28T15:40:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [August 28, 2021, 3:40pm UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/1 "2021-08-28T15:40:09Z")

</div>

Is there a way to have a gamma `Node`, which is linked to the gamma value of a colormap in `Makie`?  
Colorbars can have `limits`, but no gamma yet as it seems. Is it possible to implement this into `Makie` or can one write a colormap function that supports this `gamma` parameters and use it instead of `:grays`?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 28, 2021, 5:09pm UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/2 "2021-08-28T17:09:58Z")

</div>

No, there’s no transform function for color maps, but you can transform your array passed to the color attribute of course.

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [August 28, 2021, 5:36pm UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/3 "2021-08-28T17:36:58Z")

</div>

Oh. I thought about this, but transforming the data is not a great idea, as this would mess up all the other reporting and I also could then not use the standard features etc. It also would cause performance issues. Thus a gamma-modified colormap would really be preferable.

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [August 29, 2021, 6:03am UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/4 "2021-08-29T06:03:51Z")

</div>

Here is some code which seems to do the trick:

```julia
using GLMakie
fig = Figure()
ax, im = heatmap(fig[1,1],rand(10,20))
cb = Colorbar(fig[1,2], im, label = "Brightness", alignmode = Outside())

using PerceptualColourMaps, ColorTypes
apply_gamma(rgba, gamma) = ColorTypes.RGBA(rgba.r^gamma,rgba.g^gamma,rgba.b^gamma,rgba.alpha)
m=cmap("L3", N=4096)
mg = apply_gamma.(m,0.3)
cb.colormap[] = mg

```

@jules which internal function are you using in `Makie` to convert a name to a colormap? I should presumable just hook into the same function and then submit the resulting colormap to `cb.colormap`, but it should have more than 256 values, as otherwise there may be too much blocking with low intensities for non-8-bit images and gamma values far from 1.0.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 29, 2021, 7:45am UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/5 "2021-08-29T07:45:24Z")

</div>

I think Makie.to\_colormap

---

<div class="post-metadata">

**Author:** ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)\
**Post date:** [August 29, 2021, 4:49pm UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/6 "2021-08-29T16:49:53Z")

</div>

I was curious what influence has the gamma-correction on a perceptually uniform colormap in the space CAM02-UCS (i.e. the space where the colormaps viridis, plasma, inferno, magma, as well as cmocean colormaps, are perceptually uniform).  
To illustrate this effect I used the `ehtplot`, a package developed for the EHT (Event Horizon Telescope) project, and released just before the publication of the first black-hole image, [https://github.com/liamedeiros/ehtplot](https://github.com/liamedeiros/ehtplot).

`ehtplot` converts r, g, b color-coordinates of a colormap to lightness, chroma and hue, as coordinates in the CAM02-UCS space. A colormap is perceptually uniform in this space if the lightness is a linear function of the normalized values.

In the panels posted below, the upper cell illustrates the representation of a colormap in this space. The lightness graph is colored by the colormap.

The second row can illustrate drawbacks of the colormap that can be fixed by ehtplot.  
The conclusion is that gamma-correction breaks the linearity of lightness, and the new colormap is no more perceptually uniform. But the non-linear lightness can be uniformized by ehtplot:

 ![plasma](https://global.discourse-cdn.com/julialang/original/3X/c/a/caef9c54c4eb8cb35e8d492194784636d3107fbb.png)  
 ![plasma0_45](https://global.discourse-cdn.com/julialang/original/3X/c/a/ca550125a25cf09d75f54fefce2df97bf75f0ed8.png)  
 ![plasma0_45u](https://global.discourse-cdn.com/julialang/original/3X/a/f/af10ea0988ac4db9ffe9058ca511fea60e2afba5.png)

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [August 30, 2021, 6:23am UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/7 "2021-08-30T06:23:42Z")

</div>

That’s a great thought and thanks for the figures. To see, if I understood this right (please correct me!), I will try to summarize and comment:  
I guess gamma corrections serve two major purposes:

1. correcting for nonlinearities in the display device. This would mean, for an RGB display device the R,G and B channels each get a gamma `correction` applied such that it performs linear. I guess this use still means one should apply them to RGB as before.
2. Enhancing the ability to perceive (or suppress) small data gradations for the low intensity region.

The latter is probably what it is mostly practically used for. Yet, as @empet has shown, in terms of perceived brightness a Gamma correction, equally applied to the RGB channels, does not really do what is is supposed to do for perceptual colormaps: The (perceived) brightness, i.e. `lightness` does not follow the naively expected gamma curve, but starts to get some bumps.

To me the conclusion is that one should create a modified `gamma`correction, which serves to act on `lightness` and/or `hue`. I have little experience with [perceptually uniform colorspaces](https://programmingdesignsystems.com/color/perceptually-uniform-color-spaces/) in Julia. Are there an easy to use `hsluvToRgb` and `RgbTohsluv` fuctions in Julia? Then it would be very easy to implement the application of to above `gamma` to the appropriate channels in `Julia`.

Maybe comparing a couple of images with low details in the low intensity region, shown in naive gamma and `perceptual gamma` would be enough for a small paper, if nobody has done this already. It may also be worth to pull the transformation math through and give more gist to such a paper and a (faster) RGB version of the `perceptual gamma` function.

---

<div class="post-metadata">

**Author:** ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)\
**Post date:** [August 30, 2021, 7:50am UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/8 "2021-08-30T07:50:24Z")

</div>

- I asked recently here [https://discourse.julialang.org/t/function-that-converts-rgb-color-to-cam02-ucs-coordinates/65822](https://discourse.julialang.org/t/function-that-converts-rgb-color-to-cam02-ucs-coordinates/65822) if a conversion RGB-\>CAM02-UCS, and conversely, is available in some Julia package, but the answer was negative.  
There is no direct transformation between the two color-spaces. The conversion is performed via a sequence of composed transformations.

- The non-linear lightness resulted after gamma-correction of RGB color coordinates can be uniformized in just a few lines of code  
[https://github.com/liamedeiros/ehtplot/blob/master/ehtplot/color/cmath.py#L84](https://github.com/liamedeiros/ehtplot/blob/master/ehtplot/color/cmath.py#L84).  
The result for the plasma example is posted below the first two previous images to compare the effect of uniformization.

- I don’t know if there is the posibility to call from Julia functions from `ehtplot`, as long as it can be installed only via setup.py.

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [August 30, 2021, 5:56pm UTC](https://discourse.julialang.org/t/gamma-correction-for-colormaps/67227/9 "2021-08-30T17:56:44Z")

</div>

Thanks for the reply. Sorry, I somehow must have missed the uniformized result. Anyway, I think this is not what I mean. In the original colormap you can see the red tones whereas the final “uniformized” one is missing them. What we want is simple a gamma applied to the (monochrome) argument rather than the R,G,B values. If the colormap is `RGB([red(gray_in),green(gray_in), blue(gray_in)])` then we now want `RGB([red(apply_gamma(gray_in)),green(apply_gamma(gray_in)), blue(apply_gamma(gray_in))])` in which case `red(gamma())` etc. define the new colormap.
