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

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

11 ответов


AFAIK, единственный способ сделать это-с <canvas/>...

демо-версии v2: http://jsfiddle.net/xLF38/818/

Примечание, это будет работать только с изображениями в том же домене и в браузерах, которые поддерживают HTML5 canvas:

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.


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

Цвета Вора

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

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


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

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

Я выполнил вышеуказанное выполнение в цветовом пространстве 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 или что-либо из вышеперечисленного.
Если вам только нужно


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

вы можете найти здесь сообщение @Georg о небольшом коде Opera dev:

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


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


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


речь идет о "цветовом квантовании", которое имеет несколько подходов, таких как MMCQ (модифицированное квантование медианного разреза) или OQ (квантование Октрея). Другой подход использование K-Означает для получения кластеров цветов.

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

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


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


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

Решение Все-В-Одном

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

пример:

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

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;