MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.

    Contrasting text on changing background

    Scheduled Pinned Locked Moved General Discussion
    4 Posts 4 Posters 783 Views 5 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M Offline
      mwm341
      last edited by

      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?

      S 1 Reply Last reply Reply Quote 0
      • S Offline
        sdetweil @mwm341
        last edited by sdetweil

        @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

        Sam

        How to add modules

        learning how to use browser developers window for css changes

        M B 2 Replies Last reply Reply Quote 1
        • M Offline
          mwm341 @sdetweil
          last edited by

          @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)

          1 Reply Last reply Reply Quote 0
          • B Offline
            botts85 @sdetweil
            last edited by botts85

            @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);
                };
              },
            
            1 Reply Last reply Reply Quote 1
            • 1 / 1
            • First post
              Last post
            Enjoying MagicMirror? Please consider a donation!
            MagicMirror created by Michael Teeuw.
            Forum managed by Sam, technical setup by Karsten.
            This forum is using NodeBB as its core | Contributors
            Contact | Privacy Policy