Habib Rehman Habib Rehman - 2 months ago 9
Javascript Question

Dominant color conversion of image in html canvas

After working/studying hours with canvas i have managed to get the image clone and it's pixels now i have made the user select a color from a color specterm and i have that color hex in my function :

move: function (color) {

// 'color' is the value user selected

var img_id = jQuery(".selected_bg_img").attr("id");

alert(img_id);

var x = 0;
var y = 0;
var width = 409;
var height = 409;


var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById(img_id);
ctx.drawImage(img,x,y,width,height);

var imageData = ctx.getImageData(0,0,width,height);

var data = imageData.data;

alert(data);

}


now two tasks are getting in way,

1. How do we extract the dominant color from data ?

2. How do we convert that dominant color to the color we got in function ? for live working example i have link given at end

NOTE: Select the images (any last 3) from left side of the product image and and when color is choose it clones the image to the canvas.

Here i am trying to clone the image with replacement of maximum color with the color user selected..

for (var i=0;i<imgData.data.length;i+=4)
{
imgData.data[i]=255-imgData.data[i];
imgData.data[i+1]=255-imgData.data[i+1];
imgData.data[i+2]=255-imgData.data[i+2];
imgData.data[i+3]=255;
}


*****EDIT*****

My problem is not very complex i think i have this image enter image description here
enter image description here

so we can see clearly that the dominant color is grey, by any method i am just trying to replace that color with the new color i have in my function move and draw that image with the new color. The image from where i have taken and shows another example :
http://www.art.com/products/p14499522-sa-i3061806/pela-silverman-colorful-season-i.htm?sOrig=CAT&sOrigID=0&dimVals=729271&ui=573414C032AA44A693A641C8164EB595 on left side of image when we select the similar image they have option "change color" at the bottom center of image. This is what exactly i'm trying to do.

So now i tried to read the image 1x1 and this is what i get in the console when i log it(particular for the image i have shown) :

[166, 158, 152, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…]


So it maybe the very first start from top left corner, i guess it need to be iterated over whole image and this is what i get when i iterated over whole image:

[110, 118, 124, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255…]


The loop i used for iteration is:

var imageData = ctx.getImageData(0,0,width,height);

var data = imageData.data;

for (var i=0;i<data.length;i+=4)
{
data[i]=255-data[i];
data[i+1]=255-data[i+1];
data[i+2]=255-data[i+2];
data[i+3]=255;
}
console.log(data);


Is this iteration right ? If yes, it seems to be now counting and replacing the dominant color and i'm blank here but i have now user value in rgb, need to look for places where that value should be placed

Answer

Here you go. It looks like I gave bad and misleading information earlier when I said that the link you'd found was going to be appropriate. sorry!

Basically, you needed to use the multiply composition mode. Here's a demo for you to try on. Clicking the 3rd image picks a new colour.

function byId(id){return document.getElementById(id)}
window.addEventListener('load', onDocLoaded, false);

function onDocLoaded(evt)
{
	byId('canvas2').addEventListener('click', onCanvasClicked, false);
	colorize('green');
}

function onCanvasClicked(evt)
{
	var newColour = getRandomColour();
	colorize(newColour);
}

function getRandomColour()
{
	return '#' + Math.floor(Math.random() * (Math.pow(2,24)-1)).toString(16);
}

function colorize(colourToUse)
{
	var mask = byId('maskImg');
	var colorImg = byId('colorImg');

	var width = colorImg.naturalWidth;
	var height = colorImg.naturalHeight;

	// draw the mask image to a canvas
	var can = byId('canvas1');
	var ctx = can.getContext('2d');
	can.width = width;
	can.height = height;
	ctx.drawImage(mask, 0, 0);
	
	// colorize the non transparent areas
	ctx.globalCompositeOperation = "source-in";
	ctx.fillStyle = colourToUse;
	ctx.fillRect(0, 0, can.width, can.height);
	
	
	// draw the combined output
	var can2 = byId('canvas2');
	var ctx2 = can2.getContext('2d');
	can2.width = width;
	can2.height = height;
	
	ctx2.drawImage(colorImg, 0, 0);
	ctx2.globalCompositeOperation = 'multiply';
	ctx2.drawImage(can,0,0);
}
body {
  background-color: ivory;
  padding: 20px;
}

canvas 
{
  border: 1px solid red;
  width: 275px;
  height: 275px;
}

.dontShow
{
	display: none;
}
	<img style='width:275px; height:275px' id='colorImg' src='http://cache1.artprintimages.com/images/spp/living_61_70.jpg'/><canvas id="canvas1"></canvas><canvas id='canvas2'></canvas>

	<!-- much easier than using image pre-loaders. onDocLoaded wont be fired until the html with images,script and css are available or have failed to load-->
	<img class='dontShow' id='maskImg' src='http://cache1.artprintimages.com/images/spp/living_61_70_mask.png'/>