Получите средний цвет изображения с помощью Javascript

Не уверен, что это возможно, но нужно написать script, который вернет среднее значение hex или rgb для изображения. Я знаю, что это можно сделать в AS, но вы хотите сделать это в JavaScript.

Ответ 1

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.

Ответ 2

Понял, что я бы опубликовал проект, с которым я недавно столкнулся, чтобы получить доминирующий цвет:

Цветной вор

A script для захвата доминирующего цвета или репрезентативной цветовой палитры из изображения. Использует javascript и холст.

Другие решения, упоминающие и предлагающие доминирующий цвет, никогда не отвечают на вопрос в надлежащем контексте ( "в javascript" ). Надеюсь, этот проект поможет тем, кто хочет сделать именно это.

Ответ 3

"Доминантный цвет" сложный. То, что вы хотите сделать, это сравнить расстояние между каждым пикселем и каждым другим пикселем в цветовом пространстве (Euclidean Distance), а затем найти пиксель, цвет которого ближе всего к любому другому цвету. Этот пиксель является доминирующим цветом. Средний цвет обычно будет грязью.

Жаль, что у меня не было MathML, чтобы показать вам Евклидское расстояние. Google это.

Я выполнил вышеупомянутое выполнение в цветовом пространстве RGB, используя PHP/GD здесь: https://gist.github.com/cf23f8bddb307ad4abd8

Это, однако, очень дорого. Это приведет к сбою вашей системы на больших изображениях и, безусловно, приведет к краху вашего браузера, если вы попробуете его на клиенте. Я работал над реорганизацией моего исполнения: - сохранять результаты в таблице поиска для будущего использования в итерации по каждому пикселю. - делить большие изображения на сетки 20px 20px для локализованного доминирования. - использовать эвклидовое расстояние между x1y1 и x1y2, чтобы выяснить расстояние между x1y1 и x1y3.

Пожалуйста, дайте мне знать, если вы достигнете прогресса на этом фронте. Я был бы рад увидеть это. Я сделаю то же самое.

Canvas - это, безусловно, лучший способ сделать это в клиенте. SVG нет, SVG - векторный. После того, как я сниму исполнение, следующая вещь, которую я хочу сделать, - это запустить это на холсте (возможно, с веб-мастером для расчета общего расстояния на каждом пикселе).

Еще одна вещь, о которой стоит подумать, заключается в том, что RGB не является хорошим цветовым пространством для этого, потому что эвклидовое расстояние между цветами в пространстве RGB не очень близко к визуальному расстоянию. Лучшим цветовым пространством для этого может быть LUV, но я не нашел для этого хорошей библиотеки или каких-либо алгоритмов для преобразования RGB в LUV.

Совершенно другой подход состоял бы в сортировке ваших цветов в радуге и построении гистограммы с терпимостью для учета различных оттенков цвета. Я не пробовал этого, потому что сортировка цветов в радуге тяжелая, и так же цветовые гистограммы. Я мог бы попробовать это дальше. Опять же, дайте мне знать, если вы делаете какой-либо прогресс здесь.

Ответ 4

Во-первых: это можно сделать без холста HTML5 или SVG.
Фактически, кому-то просто удалось генерировать файлы PNG на стороне клиента с использованием JavaScript, без холста или SVG, используя схема URI данных.

Во-вторых: на самом деле вам может не понадобиться Canvas, SVG или любой из вышеперечисленных. Если вам нужно обработать изображения только на стороне клиента, не изменяя их, все это не требуется.

Вы можете получить адрес источника из тега img на странице, сделать запрос XHR - он, скорее всего, придет из кеша браузера - и обрабатывать его как поток байтов из Javascript.
Вам нужно хорошее понимание формата изображения. (Этот генератор частично основан на источниках libpng и может служить хорошей отправной точкой.)

Ответ 5

Я бы сказал через тег HTML canvas.

Вы можете найти здесь сообщение от @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, затем округлить красные, зеленые и синие массивы и, наконец, преобразовать их обратно в HEX-код.

Ответ 6

Недавно я наткнулся на плагин jQuery, который делает то, что я изначально хотел https://github.com/briangonzalez/jquery.adaptive-backgrounds.js в отношении получения доминирующего цвета с изображения.

Ответ 7

Javascript не имеет доступа к изображениям отдельных цветов пикселей. По крайней мере, не до тех пор, пока html5... в этот момент разумно, что вы сможете нарисовать изображение на холсте, а затем осмотреть холст (возможно, я никогда не делал этого сам).

Ответ 8

Речь идет о "цветовом квантовании", который имеет несколько подходов, таких как MMCQ (Модифицированное средовое квантование среза) или OQ (Octree Quantization). Разный подход использует K-Means для получения кластеров цветов.

Я собрал все вместе, так как нашел решение для tvOS, где есть подмножество XHTML, у которого нет элемента <canvas/>:

Создайте доминантные цвета для изображения RGB с XMLHttpRequest

Ответ 9

Все-в-одном решение

Я бы лично объединил Color Thief вместе с этой модифицированной версией Name that Color, чтобы получить более чем достаточный массив доминирующих цветовых результатов для изображений.

Пример:

Рассмотрим следующее изображение:

enter image description here

Вы можете использовать следующий код для извлечения данных изображения, относящихся к доминирующему цвету:

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;

Ответ 10

Существует онлайн-инструмент pickimagecolor.com, который поможет вам найти средний или доминирующий цвет изображения. Вам просто нужно загрузить изображение с вашего компьютера, а затем нажмите на изображение. Он дает средний цвет в HEX, RGB и HSV. Он также находит цветовые оттенки, соответствующие этому цвету. Я использовал его несколько раз.

Ответ 11

Менее точный, но самый быстрый способ получить средний цвет изображения с поддержкой 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);
}

Ответ 12

Как указано в других ответах, часто то, что вам действительно нужно, это доминирующий цвет в отличие от среднего цвета, который обычно бывает коричневым. Я написал сценарий, который получает наиболее распространенный цвет, и разместил его в этом списке.