Read the statement by Michael Teeuw here.
Contrasting text on changing background
-
I’m trying to come up with a configuration that (mostly) guarantees text visibility in the following way:
White background shows black text and vice versa
Yellow background shows blue text and vice versa…the point being that the text color should ALWAYS be different from the background color, so that it can be read even if the background color changes. I’d also like that to happen with randomly-selected wallpapers.
So I’m wondering: Is it something I can do with CSS?
Or do I need to try something else? -
@mwm341 I want that too. text over photos. haven’t figured out a way yet.
some kind of css transform i think
https://css-tricks.com/methods-contrasting-text-backgrounds/
https://stackoverflow.com/questions/50986688/invert-text-color-based-on-background-in-css -
@sdetweil I guess one could cheat a little by doing something with an animated (slow) colour gradient, assuming that the text will be visible some of the time (in the place where I do it) - but that not much of a solution… (sigh)
-
@sdetweil said in Contrasting text on changing background:
@mwm341 I want that too. text over photos. haven’t figured out a way yet.
I kludged something together today with the MMM-Wallpaper module. It’s not elegant, but it’s been working for me so far.
What I’m doing is having the module draw the image onto an off-screen canvas and compute its average brightness using the luminance formula. Based on whether this brightness exceeds a defined threshold (115 has been working for me), the module then updates a global CSS variable with either a light or dark text color.
I’m using
color: var(--dynamic-text-color);
as the variable. Since it’s determining global brightness, it can still “miss” picking a good color for each module.Depending on compute load, I’m thinking an update would be to determine that brightness value for each quadrant of an image then creating a variable for each quadrant and setting the text style in those areas to that color. A downside to this approach is that it won’t work perfectly with different display aspect ratios, but if you’re only ever using a 16:9 display that would be mitigated.
Brightness function:
// Helper function to compute average brightness of an image. getAverageBrightness: function(image, callback) { var canvas = document.createElement("canvas"); var width = image.naturalWidth; var height = image.naturalHeight; canvas.width = width; canvas.height = height; var context = canvas.getContext("2d"); context.drawImage(image, 0, 0, width, height); try { var imageData = context.getImageData(0, 0, width, height); } catch (error) { console.error("Error accessing image data:", error); callback(255); // Assume bright background if error. return; } var data = imageData.data; var colorSum = 0; var pixels = data.length / 4; for (var i = 0; i < data.length; i += 4) { var r = data[i]; var g = data[i + 1]; var b = data[i + 2]; // Calculate brightness using the luminance formula. var brightness = 0.299 * r + 0.587 * g + 0.114 * b; colorSum += brightness; } var averageBrightness = colorSum / pixels; callback(averageBrightness); },
Updated onImageLoaded function:
onImageLoaded: function(imageData, element) { var self = this; return () => { self.resetLoadImageTimer(); element.className = `wallpaper ${self.config.crossfade ? "crossfade-image" : ""}`; element.style.opacity = 1; // Analyze the image brightness and adjust text color accordingly. // This will update both the module's caption and a global CSS variable. self.getAverageBrightness(element, function(brightness) { var threshold = 128; // Adjust this threshold as needed. var textColor = brightness > threshold ? "black" : "white"; self.title.style.color = textColor; // Set a global CSS variable for dynamic text color. document.documentElement.style.setProperty('--dynamic-text-color', textColor); }); self.title.style.display = "none"; setTimeout(() => { var caption = imageData.caption; if (self.config.caption && caption) { self.title.innerHTML = caption; self.title.style.display = "initial"; } if (self.imageElement !== null) { self.content.removeChild(self.imageElement); } self.imageElement = self.nextImageElement; self.nextImageElement = null; }, self.config.crossfade ? 1000 : 0); }; },