Не уверен, что это возможно, но хочу написать сценарий, который бы возвращал среднее значение hex
или rgb
значение для изображения. Я знаю, что это можно сделать в AS, но хочу сделать это в JavaScript.
Не уверен, что это возможно, но хочу написать сценарий, который бы возвращал среднее значение hex
или rgb
значение для изображения. Я знаю, что это можно сделать в AS, но хочу сделать это в JavaScript.
Ответы:
AFAIK, единственный способ сделать это - с <canvas/>
...
ДЕМО V2 : http://jsfiddle.net/xLF38/818/
Обратите внимание, это будет работать только с изображениями в том же домене и в браузерах, поддерживающих холст 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;
}
Для IE проверьте excanvas .
'rgb('+rgb.r+','+rgb.b+','+rgb.g+')'
и это должно быть 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')'
. странно, когда преобладает синий цвет, а получается зеленый :).
img.crossOrigin = '';
перед установкой src
атрибута. Найдено на coderwall.com/p/pa-2uw
count === length / 4 / blockSize
;)
Подумал, что опубликую проект, с которым недавно столкнулся, чтобы получить доминирующий цвет:
Скрипт для захвата доминирующего цвета или репрезентативной цветовой палитры изображения. Использует javascript и холст.
Другие решения, в которых упоминается и предлагается доминирующий цвет, на самом деле никогда не отвечают на вопрос в надлежащем контексте («в javascript»). Надеюсь, этот проект поможет тем, кто хочет именно этого.
«Доминирующий цвет» - это сложно. Что вы хотите сделать, так это сравнить расстояние между каждым пикселем и каждым другим пикселем в цветовом пространстве (Евклидово расстояние), а затем найти пиксель, цвет которого ближе всего к любому другому цвету. Этот пиксель является доминирующим цветом. Обычно средний цвет грязи.
Хотел бы я иметь здесь MathML, чтобы показать вам евклидово расстояние. Поищи в Гугле.
Я выполнил вышеуказанное выполнение в цветовом пространстве RGB с помощью PHP / GD здесь: https://gist.github.com/cf23f8bddb307ad4abd8
Однако это очень затратно с точки зрения вычислений. Это приведет к сбою вашей системы на больших изображениях и определенно приведет к сбою вашего браузера, если вы попробуете его в клиенте. Я работал над рефакторингом своего выполнения, чтобы: - сохранять результаты в таблице поиска для будущего использования в итерации по каждому пикселю. - разделить большие изображения на сетки 20px 20px для локализованного доминирования. - использовать евклидово расстояние между x1y1 и x1y2, чтобы вычислить расстояние между x1y1 и x1y3.
Пожалуйста, дайте мне знать, если вы добьетесь прогресса в этом направлении. Я был бы рад это увидеть. Я сделаю то же самое.
Canvas - определенно лучший способ сделать это в клиенте. SVG - нет, SVG - векторный. После того, как я завершу выполнение, следующее, что я хочу сделать, - это запустить его на холсте (возможно, с помощью веб-мастера для расчета общего расстояния каждого пикселя).
Еще одна вещь, о которой следует подумать, заключается в том, что RGB не является хорошим цветовым пространством для этого, потому что евклидово расстояние между цветами в пространстве RGB не очень близко к визуальному расстоянию. Лучшим цветовым пространством для этого может быть LUV, но я не нашел для этого хорошей библиотеки или каких-либо алгоритмов для преобразования RGB в LUV.
Совершенно другой подход заключался бы в том, чтобы отсортировать цвета по радуге и построить гистограмму с допуском для учета различных оттенков цвета. Я не пробовал этого, потому что сортировать цвета в радуге сложно, как и цветовые гистограммы. Я могу попробовать следующее. Опять же, дайте мне знать, если вы добьетесь здесь прогресса.
Во-первых: это можно сделать без HTML5 Canvas или SVG.
Фактически, кому-то просто удалось сгенерировать клиентские файлы PNG с использованием JavaScript , без холста или SVG, с использованием схемы URI данных. .
Во-вторых: вам может вообще не понадобиться Canvas, SVG или что-либо из вышеперечисленного.
Если вам нужно обрабатывать изображения только на стороне клиента, без изменяя их, все это не нужно.
Вы можете получить адрес источника из тега img на странице, сделать для него запрос XHR - он, скорее всего, будет поступать из кеша браузера - и обработать его как поток байтов из Javascript.
Вам потребуется хорошее понимание формата изображения. (Вышеупомянутый генератор частично основан на источниках libpng и может стать хорошей отправной точкой.)
Я бы сказал через HTML-тег холста.
Вы можете найти здесь сообщение от @Georg, в котором говорится о небольшом коде разработчика 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);
Это инвертирует изображение, используя значения R, G и B каждого пикселя. Вы можете легко сохранить значения RGB, затем округлить массивы Red, Green и Blue и, наконец, преобразовать их обратно в HEX-код.
Недавно я наткнулся на плагин jQuery, который делает то, что я изначально хотел https://github.com/briangonzalez/jquery.adaptive-backgrounds.js в отношении получения доминирующего цвета из изображения.
Javascript не имеет доступа к данным цвета отдельных пикселей изображения. По крайней мере, до html5 ... в этот момент логично, что вы сможете нарисовать изображение на холсте, а затем проверить холст (возможно, я никогда не делал этого сам).
Я лично совмещал бы Color Thief с этой модифицированной версией Name that Color, чтобы получить более чем достаточный массив результатов доминирующего цвета для изображений.
Пример:
Рассмотрим следующее изображение:
Вы можете использовать следующий код для извлечения данных изображения, относящихся к доминирующему цвету:
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;
Речь идет о «квантовании цвета», которое имеет несколько подходов, таких как MMCQ (модифицированное квантование с медианным отсечением ) или OQ (квантование октодерева). Другой подход использует K-средние для получения кластеров цветов.
Я собрал все вместе здесь, так как я нашел решение для того, tvOS
где есть подмножество XHTML, в котором нет <canvas/>
элемента:
Генерация доминирующих цветов для изображения RGB с помощью XMLHttpRequest
Менее точный, но самый быстрый способ получить средний цвет изображения с datauri
поддержкой:
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);
}
Существует онлайн-инструмент pickimagecolor.com, который поможет вам найти средний или доминирующий цвет изображения. Вам просто нужно загрузить изображение со своего компьютера, а затем щелкнуть изображение. Он дает средний цвет в HEX, RGB и HSV. Он также находит цветовые оттенки, соответствующие этому цвету, на выбор. Я использовал его несколько раз.