I am working on a product that outputs images from users and the image information is overlayed on top of the aforementioned images. As you might imagine, the images require different text colors due to lightness/darkness. Is there a way to achieve this with JavaScript?
EDIT: I found a similar question to mine and there was a solution given in a jsfiddle (http://jsfiddle.net/xLF38/818). I am using jQuery for my site though. How would I convert the vanilla JavaScript to jQuery?
var rgb = getAverageRGB(document.getElementById('i'));
document.body.style.backgroundColor = 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
function getAverageRGB(imgEl) {
var blockSize = 5, // only visit every 5 pixels
defaultRGB = {
r: 0,
g: 0,
b: 0
}, // for non-supporting envs
canvas = document.createElement('canvas'),
context = canvas.getContext && canvas.getContext('2d'),
data, width, height,
i = -4,
length,
rgb = {
r: 0,
g: 0,
b: 0
},
count = 0;
if (!context) {
return defaultRGB;
}
height = canvas.height = imgEl.naturalHeight || imgEl.offsetHeight || imgEl.height;
width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;
context.drawImage(imgEl, 0, 0);
try {
data = context.getImageData(0, 0, width, height);
} catch (e) {
/* security error, img on diff domain */
alert('x');
return defaultRGB;
}
length = data.data.length;
while ((i += blockSize * 4) < length) {
++count;
rgb.r += data.data[i];
rgb.g += data.data[i + 1];
rgb.b += data.data[i + 2];
}
// ~~ used to floor values
rgb.r = ~~ (rgb.r / count);
rgb.g = ~~ (rgb.g / count);
rgb.b = ~~ (rgb.b / count);
return rgb;
}
function isDark(color) { var match = /rgb\((\d+). *?(\d+). *?(\d+)\)/. exec(color); return (match[1] & 255) + (match[2] & 255) + (match[3] & 255) < 3 * 256 / 2; } $('div').
I finally found something to do precisely what I want it to do! Enter Brian Gonzalez's jquery.adaptive-backgrounds.js. Check this out:
$parent.css({
// backgroundColor: data.color
color: data.color
});
I just commented out the backgroundColor rule and made a new one for color. For white text, a text-shadow like:
text-shadow: 0 0 1px rgba($black, 0.3); // using Sass
should be enough. Thank you to everyone for your answers!
This is possible using the canvas element. You would have to create a canvas
element, draw the image element into the canvas, get the canvas's image data, look at the portion where the text is, convert those values to grayscale, average them, then compare them with a halfway point. Some example code:
var img = document.getElementById('myImage');
var c = document.createElement('canvas');
var ctx = c.getContext('2d');
var w = img.width, h = img.height;
c.width = w; c.height = h;
ctx.drawImage(img, 0, 0);
var data = ctx.getImageData(0, 0, w, h).data;
var brightness = 0;
var sX = 0, sY = 0, eX = w, eY = h;
var start = (w * sY + sX) * 4, end = (w * eY + eX) * 4;
for (var i = start, n = end; i < n; i += 4) {
var r = data[i],
g = data[i + 1],
b = data[i + 2];
brightness += 0.34 * r + 0.5 * g + 0.16 * b;
if (brightness !== 0) brightness /= 2;
}
if (brightness > 0.5) var textColor = "#FFFFFF";
else var textColor = "#000000";
I haven't tested this code, though it should work. Make sure to change the sX, sY, eX, eY values to only the area where your text is, otherwise you will get unsatisfactory results (it will still work). Good luck!
EDIT: You will not have to display your image in any special way. Just make sure that the color of the overlay text is the variable textColor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With