No estoy seguro de que esto sea posible, pero estoy buscando escribir un script que devuelva el promedio hex
o el rgb
valor de una imagen. Sé que se puede hacer en AS pero estoy buscando hacerlo en JavaScript.
No estoy seguro de que esto sea posible, pero estoy buscando escribir un script que devuelva el promedio hex
o el rgb
valor de una imagen. Sé que se puede hacer en AS pero estoy buscando hacerlo en JavaScript.
Respuestas:
AFAIK, la única forma de hacer esto es con <canvas/>
...
DEMO V2 : http://jsfiddle.net/xLF38/818/
Tenga en cuenta que esto solo funcionará con imágenes en el mismo dominio y en navegadores que admitan el lienzo HTML5:
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 */
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;
}
Para IE, consulte excanvas .
'rgb('+rgb.r+','+rgb.b+','+rgb.g+')'
y debería ser 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')'
. es extraño cuando el color dominante es el azul pero el resultado es el verde :).
img.crossOrigin = '';
antes de establecer el src
atributo. Se encuentra en: coderwall.com/p/pa-2uw
count === length / 4 / blockSize
;)
Pensé que publicaría un proyecto que encontré recientemente para obtener un color dominante:
Un guión para tomar el color dominante o una paleta de colores representativa de una imagen. Utiliza javascript y lienzo.
Las otras soluciones que mencionan y sugieren el color dominante nunca realmente responden a la pregunta en el contexto adecuado ("en javascript"). Con suerte, este proyecto ayudará a quienes quieran hacer precisamente eso.
El "color dominante" es complicado. Lo que quiere hacer es comparar la distancia entre cada píxel y todos los demás píxeles en el espacio de color (Distancia euclidiana) y luego encontrar el píxel cuyo color es más cercano a cualquier otro color. Ese píxel es el color dominante. El color medio suele ser barro.
Ojalá tuviera MathML aquí para mostrarte la distancia euclidiana. Buscalo en Google.
He logrado la ejecución anterior en el espacio de color RGB usando PHP / GD aquí: https://gist.github.com/cf23f8bddb307ad4abd8
Sin embargo, esto es muy costoso computacionalmente. Bloqueará su sistema en imágenes grandes y definitivamente bloqueará su navegador si lo prueba en el cliente. He estado trabajando en refactorizar mi ejecución para: - almacenar resultados en una tabla de búsqueda para uso futuro en la iteración sobre cada píxel. - para dividir imágenes grandes en cuadrículas de 20px 20px para un dominio localizado. - utilizar la distancia euclidiana entre x1y1 y x1y2 para calcular la distancia entre x1y1 y x1y3.
Por favor, avíseme si progresa en este frente. Estaría feliz de verlo. Voy a hacer lo mismo.
Canvas es definitivamente la mejor manera de hacer esto en el cliente. SVG no, SVG está basado en vectores. Después de bajar la ejecución, lo siguiente que quiero hacer es ejecutar esto en el lienzo (tal vez con un webworker para el cálculo de la distancia total de cada píxel).
Otra cosa en la que pensar es que RGB no es un buen espacio de color para hacer esto, porque la distancia euclidiana entre colores en el espacio RGB no está muy cerca de la distancia visual. Un mejor espacio de color para hacer esto podría ser LUV, pero no he encontrado una buena biblioteca para esto, ni ningún algoritmo para convertir RGB a LUV.
Un enfoque completamente diferente sería ordenar los colores en un arco iris y construir un histograma con tolerancia para tener en cuenta los diferentes tonos de un color. No lo he intentado, porque clasificar los colores en un arco iris es difícil, al igual que los histogramas de colores. Podría intentar esto a continuación. Nuevamente, avíseme si logra algún progreso aquí.
Primero: se puede hacer sin HTML5 Canvas o SVG.
En realidad, alguien logró generar archivos PNG del lado del cliente usando JavaScript , sin lienzo o SVG, usando el esquema de URI de datos .
Segundo: es posible que en realidad no necesite Canvas, SVG o cualquiera de los anteriores.
Si solo necesita procesar imágenes en el lado del cliente, sin modificarlas, todo esto no es necesario.
Puede obtener la dirección de origen de la etiqueta img en la página, realizar una solicitud XHR (lo más probable es que provenga del caché del navegador) y procesarla como un flujo de bytes desde Javascript.
Necesitará una buena comprensión del formato de imagen. (El generador anterior se basa parcialmente en fuentes libpng y podría proporcionar un buen punto de partida).
Diría a través de la etiqueta de lienzo HTML.
Puede encontrar aquí una publicación de @Georg que habla de un pequeño código del desarrollador de Opera:
// Get the CanvasPixelArray from the given coordinates and dimensions.
var imgd = context.getImageData(x, y, width, height);
var pix = imgd.data;
// Loop over each pixel and invert the color.
for (var i = 0, n = pix.length; i < n; i += 4) {
pix[i ] = 255 - pix[i ]; // red
pix[i+1] = 255 - pix[i+1]; // green
pix[i+2] = 255 - pix[i+2]; // blue
// i+3 is alpha (the fourth element)
}
// Draw the ImageData at the given (x,y) coordinates.
context.putImageData(imgd, x, y);
Esto invierte la imagen utilizando los valores R, G y B de cada píxel. Puede almacenar fácilmente los valores RGB, luego redondear las matrices rojo, verde y azul, y finalmente convertirlos de nuevo en un código HEX.
Recientemente me encontré con un complemento jQuery que hace lo que originalmente quería https://github.com/briangonzalez/jquery.adaptive-backgrounds.js en lo que respecta a obtener un color dominante de una imagen.
Javascript no tiene acceso a los datos de color de píxeles individuales de una imagen. Al menos, tal vez no hasta html5 ... momento en el que es lógico pensar que podrá dibujar una imagen en un lienzo y luego inspeccionar el lienzo (tal vez, nunca lo he hecho yo mismo).
Personalmente, combinaría Color Thief junto con esta versión modificada de Name that Color para obtener una gama más que suficiente de resultados de colores dominantes para las imágenes.
Ejemplo:
Considere la siguiente imagen:
Puede utilizar el siguiente código para extraer datos de imagen relacionados con el color dominante:
let color_thief = new ColorThief();
let sample_image = new Image();
sample_image.onload = () => {
let result = ntc.name('#' + color_thief.getColor(sample_image).map(x => {
const hex = x.toString(16);
return hex.length === 1 ? '0' + hex : hex;
}).join(''));
console.log(result[0]); // #f0c420 : Dominant HEX/RGB value of closest match
console.log(result[1]); // Moon Yellow : Dominant specific color name of closest match
console.log(result[2]); // #ffff00 : Dominant HEX/RGB value of shade of closest match
console.log(result[3]); // Yellow : Dominant color name of shade of closest match
console.log(result[4]); // false : True if exact color match
};
sample_image.crossOrigin = 'anonymous';
sample_image.src = document.getElementById('sample-image').src;
Se trata de "Cuantificación de color" que tiene varios enfoques como MMCQ (cuantificación de corte mediano modificado) u OQ (cuantificación de octárbol). Diferentes enfoques utilizan K-Means para obtener grupos de colores.
He reunido todo aquí, ya que estaba encontrando una solución para tvOS
donde hay un subconjunto de XHTML, que no tiene ningún <canvas/>
elemento:
Genere los colores dominantes para una imagen RGB con XMLHttpRequest
Una forma menos precisa pero más rápida de obtener un color promedio de la imagen con datauri
soporte:
function get_average_rgb(img) {
var context = document.createElement('canvas').getContext('2d');
if (typeof img == 'string') {
var src = img;
img = new Image;
img.setAttribute('crossOrigin', '');
img.src = src;
}
context.imageSmoothingEnabled = true;
context.drawImage(img, 0, 0, 1, 1);
return context.getImageData(1, 1, 1, 1).data.slice(0,3);
}
Existe una herramienta online pickimagecolor.com que te ayuda a encontrar el color medio o dominante de la imagen, solo tienes que subir una imagen desde tu ordenador y luego hacer clic en la imagen. Da el color promedio en HEX, RGB y HSV. También encuentra los tonos de color que combinan con ese color para elegir. Lo he usado varias veces.