Jor*_*rdy 5 html javascript css image colors
我的图像资源中有一些徽标。这些标志将被导入到本网站中。每个标志都有随机颜色(可以是白色、黑色、灰色、红色、蓝色、绿色等)并具有透明背景。例如:
以下代码将用于在网站页面上显示徽标:
.magic-box {
width: 200px;
height: 100px;
border: 1px solid black;
position: relative;
border-radius: 20px;
background-color: white; /* can be changed */
}
.magic-image {
max-height: 100%;
max-width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.images {
display: flex;
}Run Code Online (Sandbox Code Playgroud)
<div class="images">
<div class="magic-box">
<img src="https://i.stack.imgur.com/b7yHv.png" class="magic-image" />
</div>
<div class="magic-box">
<img src="https://i.stack.imgur.com/IhCH1.png" class="magic-image" />
</div>
<div class="magic-box">
<img src="https://i.stack.imgur.com/tYjdM.png" class="magic-image" />
</div>
</div>Run Code Online (Sandbox Code Playgroud)
问题是当我将背景颜色设置为.magic-box白色时,白色徽标不会显示。当背景颜色设置为黑色时,黑色标志不可见,等等。
.magic-box {
width: 200px;
height: 100px;
border: 1px solid black;
position: relative;
border-radius: 20px;
background-color: black; /* can be changed */
}
.magic-image {
max-height: 100%;
max-width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.images {
display: flex;
}Run Code Online (Sandbox Code Playgroud)
<div class="images">
<div class="magic-box">
<img src="https://i.stack.imgur.com/b7yHv.png" class="magic-image" />
</div>
<div class="magic-box">
<img src="https://i.stack.imgur.com/IhCH1.png" class="magic-image" />
</div>
<div class="magic-box">
<img src="https://i.stack.imgur.com/tYjdM.png" class="magic-image" />
</div>
</div>Run Code Online (Sandbox Code Playgroud)
如何以编程方式确定最适合background-color应用于每个.magic-box元素的?
注意:每个图像的背景颜色可以不同
此方法将图像渲染为 1x1 像素<canvas>,以检索平均亮度/亮度,从而找到合适的背景颜色。
function adjustBG(image, grayscale = true) {
// try to fix CORS issues
image.crossOrigin = "anonymous";
// draw image on canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = image.src;
img.crossOrigin = "anonymous"; // ADDED
img.onload = function () {
canvas.width = 1;
canvas.height = 1;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 1, 1);
// calculate average color form 1x1 px canvas
let color = ctx.getImageData(0, 0, 1, 1).data;
let [r, g, b, a] = [color[0], color[1], color[2], color[3]];
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
let contrast = +((255 - luminance) / 255).toFixed(2);
let bg = [255 - luminance, 255 - luminance, 255 - luminance].map(
(val) => {
return +val.toFixed(0);
}
);
let filters = [];
// optional convert all to grayscale
if (grayscale) {
filters.push(`grayscale(1)`);
}
// add background color if image is very bright
if (luminance > 160 && contrast < 0.5) {
//console.log(bg, luminance)
image.style.backgroundColor = `rgb(${bg.join(",")})`;
} else {
image.style.backgroundColor = `rgb(255,255,255)`;
}
// enhance contrast
if (contrast < 0.5) {
let newContrast = contrast ? 1/contrast : 1;
filters.push(`contrast(${newContrast })`);
}
image.style.filter = filters.join(" ");
};
Run Code Online (Sandbox Code Playgroud)
function adjustBG(image, grayscale = true) {
// try to fix CORS issues
image.crossOrigin = "anonymous";
// draw image on canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = image.src;
img.crossOrigin = "anonymous"; // ADDED
img.onload = function () {
canvas.width = 1;
canvas.height = 1;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 1, 1);
// calculate average color form 1x1 px canvas
let color = ctx.getImageData(0, 0, 1, 1).data;
let [r, g, b, a] = [color[0], color[1], color[2], color[3]];
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
let contrast = +((255 - luminance) / 255).toFixed(2);
let bg = [255 - luminance, 255 - luminance, 255 - luminance].map(
(val) => {
return +val.toFixed(0);
}
);
let filters = [];
// optional convert all to grayscale
if (grayscale) {
filters.push(`grayscale(1)`);
}
// add background color if image is very bright
if (luminance > 160 && contrast < 0.5) {
//console.log(bg, luminance)
image.style.backgroundColor = `rgb(${bg.join(",")})`;
} else {
image.style.backgroundColor = `rgb(255,255,255)`;
}
// enhance contrast
if (contrast < 0.5) {
let newContrast = contrast ? 1/contrast : 1;
filters.push(`contrast(${newContrast })`);
}
image.style.filter = filters.join(" ");
};
Run Code Online (Sandbox Code Playgroud)
let images = document.querySelectorAll("img");
addBGColor(true);
function revert() {
images.forEach((img) => {
img.style.removeProperty("background-color");
img.style.removeProperty("filter");
});
}
function addBGColor(grayscale = true) {
images.forEach((img) => {
adjustBG(img, grayscale);
});
}
function adjustBG(image, grayscale = true) {
// try to fix CORS issues
image.crossOrigin = "anonymous";
// draw image on canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = image.src;
img.crossOrigin = "anonymous"; // ADDED
img.onload = function() {
canvas.width = 1;
canvas.height = 1;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 1, 1);
// calculate average color form 1x1 px canvas
let color = ctx.getImageData(0, 0, 1, 1).data;
let [r, g, b, a] = [color[0], color[1], color[2], color[3]];
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
let contrast = +((255 - luminance) / 255).toFixed(2);
let bg = [255 - luminance, 255 - luminance, 255 - luminance].map(
(val) => {
return +val.toFixed(0);
}
);
let filters = [];
// optional convert all to grayscale
if (grayscale) {
filters.push(`grayscale(1)`);
}
// add background color if image is very bright
if (luminance > 160 && contrast < 0.5) {
//console.log(bg, luminance)
image.style.backgroundColor = `rgb(${bg.join(",")})`;
} else {
image.style.backgroundColor = `rgb(255,255,255)`;
}
// enhance contrast
if (contrast < 0.5) {
let newContrast = contrast ? 1 / contrast : 1;
filters.push(`contrast(${newContrast })`);
}
image.style.filter = filters.join(" ");
};
}Run Code Online (Sandbox Code Playgroud)
body {
background: #eee;
}
img {
width: 10em;
margin: 1em;
}Run Code Online (Sandbox Code Playgroud)
image.crossOrigin = 'anonymous'根据Rene van der Lende 的评论,我修改了averagecolor.js脚本并添加了一些功能。
以下代码片段还将检查图像的透明度以及仅灰度的颜色范围。
然而,该脚本对于更详细的颜色检测速度明显较慢。
<p><button onclick="revert()">revert</button> <button onclick="addBGColor(true)">Add BG color (grayscale)</button> <button onclick="addBGColor(false)">Add BG color (no change)</button></p>
<div class="logos">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='20' text-anchor='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 0)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 0, 0)'>LO<tspan fill='rgb(255, 0, 0)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 0)'>LO<tspan fill='rgb(255, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 255)'>LO<tspan fill='rgb(128, 128, 128)'>GO</tspan><tspan fill='rgba(0, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 0)'>LO<tspan fill='rgb(255, 255, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 1)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 255)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 255)'>LO<tspan fill='rgb(255, 200, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.75)'>*</tspan></text></svg>">
<img src="https://i.imgur.com/qO6ZdET.png" crossorigin="anonymous" data-contrast="0.69" data-bg="175,175,175" style="background-color: rgb(175, 175, 175);">
</div>Run Code Online (Sandbox Code Playgroud)
let images = document.querySelectorAll("img");
function revert() {
images.forEach((img) => {
img.style.removeProperty('background-color');
img.style.removeProperty('filter');
});
}
function addBGColor(options = { grayscale: true, complementraryColor: false, enhanceContrast: true }) {
images.forEach((img) => {
adjustBG(img, options);
});
}
function adjustBG(image, options = { grayscale: true, complementraryColor: false, enhanceContrast: true }) {
let grayscale = options.grayscale;
let complementraryColor = options.complementraryColor;
let enhanceContrast = options.enhanceContrast;
// try to fix CORS issues
image.crossOrigin = 'anonymous';
image.addEventListener('load', e=>{
// check transparency
let hasTransparency = checkImgTransparency(image);
let isGray = checkImgGrayScale(image);
// skip opaque images
if (!hasTransparency) {
console.log('nothing to do', image.src);
return false
}
// get average color based on flattened transparency
let { r, g, b, a, colors } = getAverageColor(image, 24, 24, false);
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
let contrast = +((255 - luminance) / 255).toFixed(2);
let bg = [255 - luminance, 255 - luminance, 255 - luminance];
// calculate complementary color
let colComplemantary = [255 - r, 255 - g, 255 - b];
let filters = [];
// optional convert all to grayscale
if (grayscale && !isGray) {
filters.push(`grayscale(1)`)
}
// add background color if image is very bright
let contrastAdjust = 1 + (luminance / 255);
let colorBG = !complementraryColor ? 'rgb(255,255,255)' : `rgb(${colComplemantary.join(',')})`;
image.setAttribute('data-contrast', contrast);
image.setAttribute('data-bg', bg.join(','));
// almost white
if (luminance > 170 && contrast < 0.5) {
colorBG = `rgb(${bg.join(',')})`;
}
// enhance contrast
if (enhanceContrast && contrast < 0.5) {
let newContrast = contrast ? 1/contrast : 1;
filters.push(`contrast(${newContrast })`);
}
// apply styles
image.style.backgroundColor = colorBG;
image.style.filter = filters.join(' ');
})
// if image is ready loaded
let isloaded = image.complete;
if (isloaded) {
image.dispatchEvent(new Event('load'));
}
}
/**
* based on
* https://matkl.github.io/average-color/average-color.js
*/
function getAverageColor(img, width=24, height=24, flattenTransparency = false) {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
canvas.width = width;
canvas.height = height;
//document.body.appendChild(canvas)
// flatten transparency
if (flattenTransparency) {
//add rect
ctx.fillStyle = "rgb(255,255, 255)";
ctx.fillRect(0, 0, width, height);
}
ctx.drawImage(img, 0, 0, width, height);
let imageData = ctx.getImageData(0, 0, width, height);
let data = imageData.data;
let [rT, gT, bT, aT] = [0, 0, 0, 0];
let colLength = data.length/4;
// get colors
let colors = [];
for (let i = 0; i < data.length; i += 4) {
r = data[i];
g = data[i + 1];
b = data[i + 2];
a = data[i + 3];
// exclude transparent colors
if(a>128){
rT += r;
gT += g;
bT += b;
aT += a;
} else{
colLength--;
}
// count colors
let colStr = [r, g, b].join('_');
colors.push(colStr)
}
// calculate average color
rT = Math.floor(rT / colLength);
gT = Math.floor(gT / colLength);
bT = Math.floor(bT / colLength);
aT = Math.floor(aT / colLength);
// remove duplicates
colors = [...new Set(colors)];
return { r: rT, g: gT, b: bT, a: aT , colors: colors.length};
}
function colorIsgrayscale(r, g, b, tolerance = 0.25) {
let isGray = false;
let rT = +(r * tolerance).toFixed(0);
let gT = +(g * tolerance).toFixed(0);
let bT = +(b * tolerance).toFixed(0);
let colorAverage = (rT + gT + bT) / 3;
if (colorAverage == rT && colorAverage == gT && colorAverage == bT) {
isGray = true;
}
return isGray;
}
function checkImgGrayScale(img, tolerance = 0.9) {
let isGrayscale = false;
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
let [w, h] = [8, 8];
ctx.drawImage(img, 0, 0, w, h);
let imageData = ctx.getImageData(0, 0, w, h);
let data = imageData.data;
let gray = 0;
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
let isGray = colorIsgrayscale(r, g, b);
if(isGray){
gray++;
}
}
if(gray===data.length/4){
isGrayscale = true;
}
return isGrayscale;
}
function checkImgTransparency(img) {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 3, 3);
let imageData = ctx.getImageData(0, 0, 2, 2);
let data = imageData.data;
let hasAlpha = data[3] < 255 ? true : false;
return hasAlpha;
}Run Code Online (Sandbox Code Playgroud)
body {
background: #eee;
}
img {
width: 10em;
margin: 1em;
}Run Code Online (Sandbox Code Playgroud)
与第一种方法类似,我们通过渲染元素来<canvas>计算适当的滤镜属性值来分析图像的对比度和亮度,以增强contrast(2)或反转非常明亮的颜色invert(1)
<p><button onclick="revert()">revert</button>
<button onclick="addBGColor({grayscale: true, complementraryColor: false, enhanceContrast: false})">Add BG color (grayscale)</button> <button onclick="addBGColor({grayscale: false, complementraryColor: true, enhanceContrast: false})">Add BG color (complementary color)</button></p>
<div class="logos">
<img alt="logo white" src="https://i.postimg.cc/FzFQ3n3D/b7yHv.png" class="magic-image" />
<img alt="logo black" src="https://i.postimg.cc/J0TCqcQm/IhCH1.png" class="magic-image" />
<img src="https://i.imgur.com/qO6ZdET.png" >
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='20' text-anchor='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 0)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 0, 0)'>LO<tspan fill='rgb(255, 0, 0)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 0)'>LO<tspan fill='rgb(255, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 255)'>LO<tspan fill='rgb(128, 128, 128)'>GO</tspan><tspan fill='rgba(0, 255, 255, 0.4)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 0)'>LO<tspan fill='rgb(255, 255, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 1)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(255, 255, 255)'>LO<tspan fill='rgb(128, 128, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.5)'>*</tspan></text></svg>">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='5' text-anchor='middle' dominant-baseline='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 255, 255)'>LO<tspan fill='rgb(255, 200, 255)'>GO</tspan><tspan fill='rgba(255, 255, 255, 0.75)'>*</tspan></text></svg>">
</div>Run Code Online (Sandbox Code Playgroud)
let images = document.querySelectorAll("img");
function fixImgColors() {
images.forEach((img) => {
adjustLightColors(img);
});
}
function revert() {
images.forEach((img) => {
img.style.removeProperty('background-color');
img.style.removeProperty('filter');
});
}
function adjustLightColors(image) {
// draw image on canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = image.src;
img.onload = function() {
canvas.width = 1;
canvas.height = 1;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, 1, 1);
// calculate average color form 1x1 px canvas
let color = ctx.getImageData(0, 0, 1, 1).data;
let [r, g, b] = [color[0], color[1], color[2]];
// calculate relative luminance
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
// invert if image is very bright
let filterInvert = luminance > 128 ? 1 : 0;
let contrast = Math.ceil(1 + (luminance / 255));
image.style.filter = `invert(${filterInvert}) grayscale(1) contrast(${contrast}`;
};
}Run Code Online (Sandbox Code Playgroud)
<p><button onclick="revert()">revert</button> <button onclick="fixImgColors()">Adjust colors</button></p>
<div class="logos">
<img src="data:image/svg+xml, <svg width='200' height='100' viewBox='0 0 200 100' xmlns='http://www.w3.org/2000/svg'><text x='100' y='50' font-size='60' dy='20' text-anchor='middle' font-family='sans-serif' font-weight='bold' fill='rgb(0, 0, 0)'>LO<tspan fill='rgb(128,