Reputation: 1962
So I thought I could do a smart manipulation of the color of a random shaped PNG image, by actually having 4 images of the same shape, but in Red, Green, Blue and Black, then set then on top of each other and manipulate their opacities.
I tried using the formula channelOpacity = channelVal / 255 / 3;
Well, it's not really that easy, it turns out. Has anyone attempted similar things and what would be a solution? Thank you.
Upvotes: 1
Views: 232
Reputation: 1962
I found a way to do it through canvas, here: permadi.com
Given that Firefox has also added support (v34) for the methods involved, this solution should work fine. Careful, there are a lot of mistakes in the code at the above link (I corrected them below), but the idea is awesome. Here's what it's about, roughly:
// image is an html image element
var myCanvas=document.createElement("canvas");
var myCanvasContext=myCanvas.getContext("2d");
var imgWidth=image.width;
var imgHeight=image.height;
// You'll get some string error if you fail to specify the dimensions
myCanvas.width= imgWidth;
myCanvas.height=imgHeight;
// alert(imgWidth);
myCanvasContext.drawImage(image,0,0);
// This function cannot be called if the image is not rom the same domain.
// You'll get security error if you do.
var imageData=myCanvasContext.getImageData(0,0, imgWidth, imgHeight);
// This loop gets every pixels on the image and
for (i=0; i<imageData.height; i++)
{
for (j=0; j<imageData.width; j++)
{
var index;
index=(i*4)*imageData.width+(j*4);
// then access your data and set it like this:
// imageData.data[index+0]; // red
// imageData.data[index+0]; // green
// imageData.data[index+0]; // ... till alpha
}
}
myCanvasContext.putImageData(imageData,0,0,0,0, imageData.width, imageData.height);
return myCanvas.toDataURL();
Upvotes: 1
Reputation: 35670
It's an interesting idea. However, opacity alone doesn't seem to accomplish your objective, because the order in which the PNGs are defined will affect the color of their combination.
For example, if you have a red PNG, a green PNG, then a blue PNG, all with opacity 0.33, you'll get something like this:
If you rearrange their order as green, red, then blue, you'll get this:
Green, blue, then red will give you this:
There may be a way to take the order into account in your calculations, which could make your idea really useful.
Here's a snippet that sets the opacity of stacked red, green, and blue circles, based on the normalized rgb hex values from a color picker. It does a decent job for colors that are primarily red, green, or blue, but it suffers from the issue I've described:
var colorPicker= document.getElementById('colorPicker');
colorPicker.oninput= function() {
var red = document.getElementById('red');
var green= document.getElementById('green');
var blue = document.getElementById('blue');
var r= parseInt(this.value.substr(1,2),16);
var g= parseInt(this.value.substr(3,2),16);
var b= parseInt(this.value.substr(5,2),16);
var factor = 1/(r+g+b);
red.style.opacity = r * factor;
green.style.opacity= g * factor;
blue.style.opacity = b * factor;
}
colorPicker.oninput();
img {
position: absolute;
}
Choose color: <input id="colorPicker" type="color" value="#ff0000">
<hr>
<img id="red" src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Bullet-red.png/240px-Bullet-red.png">
<img id="green" src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Bullet-green.png/240px-Bullet-green.png">
<img id="blue" src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Bullet-blue.png/240px-Bullet-blue.png">
Upvotes: 1