Obter cor média da imagem via Javascript

Não tenho certeza se isso é possível, mas procurando escrever um script que retorne o valor médio de hex ou rgb para uma imagem. Eu sei que isso pode ser feito no AS, mas olhando para fazê-lo em JavaScript.

   

AFAIK, a única maneira de fazer isso é com

DEMO V2 : http://jsfiddle.net/xLF38/818/

Observe que isso funcionará apenas com imagens no mesmo domínio e em navegadores que suportam a canvas 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 o IE, confira excanvas .

Pensei em postar um projeto que recentemente encontrei para obter colors dominantes:

Ladrão de cor

Um script para pegar a cor dominante ou uma paleta de colors representativa de uma imagem. Usa javascript e canvas.

As outras soluções mencionando e sugerindo colors dominantes nunca realmente respondem à questão no contexto apropriado (“em javascript”). Espero que este projeto ajude aqueles que querem fazer exatamente isso.

“Cor dominante” é complicado. O que você quer fazer é comparar a distância entre cada pixel e todos os outros pixels no espaço de colors (Distância Euclidiana), e então encontrar o pixel cuja cor é mais próxima de todas as outras colors. Esse pixel é a cor dominante. A cor média geralmente será lama.

Eu gostaria de ter MathML aqui para mostrar-lhe a distância euclidiana. Google isso.

Eu realizei a execução acima no espaço de colors RGB usando PHP / GD aqui: https://gist.github.com/cf23f8bddb307ad4abd8

Isto, no entanto, é muito computacionalmente caro. Ele irá travar o seu sistema em imagens grandes, e definitivamente irá travar o seu navegador, se você tentar no cliente. Eu tenho trabalhado em refatorar minha execução para: – armazenar resultados em uma tabela de consulta para uso futuro na iteração sobre cada pixel. – dividir imagens grandes em grades de 20px 20px para dominância localizada. – para usar a distância euclidiana entre x1y1 e x1y2 para descobrir a distância entre x1y1 e x1y3.

Por favor, deixe-me saber se você faz progresso nessa frente. Eu ficaria feliz em ver isso. Eu vou fazer o mesmo.

Canvas é definitivamente a melhor maneira de fazer isso no cliente. O SVG não é, o SVG é baseado em vetores. Depois de baixar a execução, a próxima coisa que quero fazer é fazer com que isso corra na canvas (talvez com um webworker para o cálculo da distância total de cada pixel).

Outra coisa a se pensar é que o RGB não é um bom espaço de cor para fazer isso, porque a distância euclidiana entre colors no espaço RGB não está muito próxima da distância visual. Um espaço de cor melhor para fazer isso pode ser LUV, mas não encontrei uma boa biblioteca para isso, ou qualquer algoritmo para converter RGB em LUV.

Uma abordagem totalmente diferente seria classificar suas colors em um arco-íris e construir um histograma com tolerância para explicar os vários tons de uma cor. Eu não tentei isso, porque a sorting de colors em um arco-íris é difícil, assim como os histogramas de colors. Eu poderia tentar isso em seguida. Mais uma vez, deixe-me saber se você faz algum progresso aqui.

Primeiro: isso pode ser feito sem HTML5 Canvas ou SVG.
Na verdade, alguém conseguiu apenas gerar arquivos PNG do lado do cliente usando JavaScript , sem canvas ou SVG, usando o esquema de URI de dados .

Segundo: você pode realmente não precisar de Canvas, SVG ou qualquer um dos itens acima.
Se você só precisa processar imagens no lado do cliente, sem modificá-las, tudo isso não é necessário.

Você pode obter o endereço de origem da tag img na página, fazer uma solicitação XHR para ele – provavelmente ele virá do cache do navegador – e processá-lo como um stream de bytes do Javascript.
Você precisará de um bom entendimento do formato da imagem. (O gerador acima é parcialmente baseado em fonts libpng e pode fornecer um bom ponto de partida).

Eu diria através da tag de canvas HTML.

Você pode encontrar aqui um post do @Georg falando sobre um pequeno código do desenvolvedor do 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); 

Isso inverte a imagem usando o valor R, G e B de cada pixel. Você pode armazenar facilmente os valores RGB, arredondar os arrays Vermelho, Verde e Azul e, finalmente, convertê-los de volta em um código HEX.

O Javascript não tem access aos dados de cor de pixel individuais de uma imagem. Pelo menos, talvez não até html5 … em que ponto é razoável que você seja capaz de desenhar uma imagem para uma canvas e, em seguida, inspecionar a canvas (talvez, eu nunca fiz isso sozinho).

Recentemente me deparei com um plugin jQuery que faz o que eu queria originalmente https://github.com/briangonzalez/jquery.adaptive-backgrounds.js no que diz respeito a obter uma cor dominiate de uma imagem.

Trata-se de “quantização de colors”, que possui várias abordagens, como MMCQ (Modified Median Cut Quantization) ou OQ (Octree Quantization). Uma abordagem diferente usa o K-Means para obter clusters de colors.

Eu coloquei todos juntos aqui, desde que eu estava encontrando uma solução para o tvOS onde há um subconjunto de XHTML, que não tem nenhum elemento :

Gere as colors dominantes para uma imagem RGB com XMLHttpRequest

Existe uma ferramenta on-line pickimagecolor.com que ajuda você a encontrar a cor média ou dominante da imagem.Você só tem que fazer upload de uma imagem do seu computador e, em seguida, clique na imagem. Dá a cor média em HEX, RGB e HSV. Ele também encontra os tons de colors correspondentes a essa cor para escolher. Eu usei várias vezes.

datauri menos precisa, porém mais rápida, de obter a cor média da imagem com suporte a 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); } 

Solução All-In-One

Eu combinaria pessoalmente o Color Thief junto com essa versão modificada do Name that Color para obter uma matriz mais do que suficiente de resultados de colors dominantes para imagens.

Exemplo:

Considere a seguinte imagem:

insira a descrição da imagem aqui

Você pode usar o seguinte código para extrair dados de imagem relacionados à cor 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;