“True Tone” display function

Hey everyone, hope you’re doing well — and thank you very much in advance!

This is my first post here. We’re building a small, handheld, battery-powered incident and color light meter with a 240x320 TFT LCD. The menu is being built with LVGL.

I’m looking for a simple way to shift the color of all pixels on the display. The idea is to do any of these:

  1. Apply a permanent color correction if the backlight LED has a green/magenta tint to achieve more neutral white point
  2. Optionally: Let users tweak the white point in settings
  3. Pushing it: Add a True Tone-style feature based on ambient light color (which our device can measure)

Ideally, this would be a system-level shift. Could it work by adjusting all defined colors in the palette?

Would love to hear any other ideas too. I think this could be a useful feature to have in LVGL by default — getting the white point right is always tricky, and this could even allow for some virtual gamma tweaks.

Have a great Friday and weekend!

Marko

There are 2 ways you can go about doing this. You can handle it in the flush callback and you would need to iterate over the entire frame buffer that is being flushed one pixel at a time and apply a correction to the pixel.

This is possibly the easiest way to go about applying a color correction globally but it is also going to slow down due to the having to iterate over the entire frame buffer each and every time a buffer is going to get flushed.

Another option is to use themes but the problem with this is you only have the ability to set 2 colors a primary and a secondary. If you have overridden any of the colors at the object level any changes made to the theme are not going to apply to those objects for the colors you have changed. I believe this is how it works i am not 100% sure on that though. Maybe someone that has used themes will be able to chime in and let us know how they actually work.

The last option is to use styles. You can set up style groups and this would allow you to have custom colors set for specific widget types or pages or however you have things set up. you would apply the correction to those styles. The down side of using this method is you would need to apply the changes to each object if a change is made. This is the mechanism that I would personally use because it allows for having custom colors set for different widgets and if you have multiple widgets that use the same color arrangement then you would create a single style that you set the corrected colors to so that calculation only needs to be done a single time. then you apply that style to all of the objects that are using that color scheme.

With respect to using images. You are going to have to apply the adjustments on a per pixel basis for images.

1 Like

I did just have an idea on how to do this…

create a filter to correct the colors.

What is a color filter? Lets look at it from the standpoint of using an old school film camera. A filter is simply a lens that screws onto the camera. The lens is simply a colored piece of glass. Do the same thing but digitally. Create an object that has the same width and height as the screen. Remove all borders, outlines, padding and margins. Make the object transparent to input using the flags and then set all colors to completely transparent for all of the different pieces like the border, shadows and outlines. Now you can set the color for the background and set the opacity so it acts like a filter. I do wish that LVGL had a way of setting a blend mode so all objects behind it would be blended as an overlay instead of additive.

@kisvegabor would that be a feature that you would have interest in adding?

The first solution I gave in my previous post might actually be the better one because you can use an overlay algorithm to blend the colors. overlay blending is not additive. take this as an example. If you could take a color sample of what is being seen by a set of eyes from a display and the color what is being seen is 245, 255, 255 and you want it to be 255, 255, 255 you use overlay blending and place a color of 255, 245, 245 over the top of it. the resulting color ends up being 255, 255, 255. where as with a normal type blending you would need to mess with the alpha channel and that could end up causing an uneven distribution of the correction across the image. with overlay blending you set the alpha to 255 and leave it.

Here is an example.

You have this color which is 20, 113, 35
image

and you overlay it with 101, 55, 255
image

the resulting color is 16, 49, 70
image

here is an example written in Python.

pixel = [20, 113, 35]
overlay = [101, 55, 255]


def overlay_blend(base_c, overlay_c):
    if base_c > 127:
        result = int(round(overlay_c * ((255 - base_c) / 127) + (base_c - (255 - base_c))))
    else:
        result = int(round(overlay_c * (base_c / 127)))

    return result


for i in range(3):
    pixel[i] = overlay_blend(pixel[i], overlay[i])
    
print(pixel)
# output is [16, 49, 70]
1 Like

Hi,

The new recolor style property might help which is available in master. It’s like style_image_recolor but applies to any colors.


  lv_demo_widgets();
  lv_obj_set_style_recolor(lv_screen_active(), lv_color_hex(0xff0000), 0);
  lv_obj_set_style_recolor_opa(lv_screen_active(), LV_OPA_30, 0);

results in
image

1 Like

Hello @kdschlosser and @kisvegabor.

Thank you so much for both of your replies and sincere apologies for such delayed response.

We tried style change, and we’ll try the master style too.
The main goal with this exercise for us has been to see how well could we tune neutral white point in case LED backlight or some glass layer inside the TFT module would have unwanted color cast.

Turns out it’s possible, but only to a degree.
I’ll come back and share our findings, maybe helps others too.

Thank you!
Marko

Sounds interesting! Looking forward to hearing your results! :crossed_fingers: