Javascript Canvas - 使用 HTML5/CSS/JS 更改图像的颜色?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10069171/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Canvas - Change colors of an image using HTML5/CSS/JS?
提问by James Nine
Is there a way to change colors of an image much like in Flash/ActionScript with using only HTML5/CSS/JavaScript?
有没有办法像在 Flash/ActionScript 中一样只使用 HTML5/CSS/JavaScript 来改变图像的颜色?
Here's an example in Flash: http://www.kirupa.com/developer/actionscript/color.htmEDIT: This is the process I wish to duplicate.
下面是 Flash 中的一个示例:http: //www.kirupa.com/developer/actionscript/color.htm编辑:这是我希望复制的过程。
I'm trying to accomplish something like this (color changing aspect, preserving lighting and shadows): http://www.acura.com/ExteriorColor.aspx?model=TLWITHOUT loading & replacing a new image each time; I want to be able to simply change the color tone (i.e. do a pure HTML5/CSS/JS method). EDIT: This is the result I wish to achieve, not the process.
我正在尝试完成这样的事情(颜色改变方面,保留照明和阴影):http://www.acura.com/ExteriorColor.aspx ?model =TL 无需每次加载和替换新图像;我希望能够简单地改变色调(即做一个纯 HTML5/CSS/JS 方法)。编辑:这是我希望达到的结果,而不是过程。
Basically I want to change the palette/tone of an image, while preserving the other aspects of the image (such as gradient, lighting, etc.). I have gotten close, but not close enough; I've gotten to the point where I use an image mask and composite that over the original image (sort of like a transparent image overlay). Below is some sample code (please note this is just a snippet, so it may or may not work; I am only displaying sample code so you get an idea of what I'm trying to do):
基本上我想更改图像的调色板/色调,同时保留图像的其他方面(例如渐变、照明等)。我已经接近了,但还不够接近;我已经到了使用图像蒙版并将其合成在原始图像上的地步(有点像透明图像叠加)。下面是一些示例代码(请注意这只是一个片段,所以它可能会或可能不会工作;我只是显示示例代码,以便您了解我正在尝试做什么):
<div id='mask'>
<canvas id='canvas' width='100' height='100'></canvas>
</div>
<button data-rgba='255,0,0,0.5'>red</button>
<button data-rgba='0,255,0,0.5'>green</button>
<script>
foo = {};
foo.ctx = jQuery('#canvas')[0];
foo.ctx_context = foo.ctx.getContext('2d');
foo.mask = jQuery('#mask')[0];
foo.img = new Image();
foo.img_path = '/path/to/image_mask.png'; // 100px x 100px image
foo.changeColor = function(rgba){
foo.ctx_context.clearRect(0, 0, 100, 100);
foo.ctx_context.fillStyle = 'rgba(' + rgba + ')';
foo.ctx_context.fillRect(0, 0, 100, 100);
foo.ctx_context.globalCompositeOperation = 'destination-atop';
foo.ctx_context.drawImage(foo.img, 0, 0);
foo.ctx_context.css({'background-image': "url(" + foo.ctx.toDataURL("image/png") + ")"});
};
jQuery("button").click(function(){
foo.changeColor(jQuery(this).attr('data-rgba'));
});
</script>
The major problem with using this approach is that the images look really flat. There's something else missing, or the mask I'm using (which is a solid white irregular shaped image), is the wrong approach.
使用这种方法的主要问题是图像看起来非常平坦。还缺少其他东西,或者我正在使用的蒙版(这是一个纯白色不规则形状的图像),是错误的方法。
回答by lostsource
This function requires the image to be loaded and it has to be from the same domain (due to cross domain policy)
此功能需要加载图像,并且必须来自同一个域(由于跨域策略)
function tintImage(imgElement,tintColor) {
// create hidden canvas (using image dimensions)
var canvas = document.createElement("canvas");
canvas.width = imgElement.offsetWidth;
canvas.height = imgElement.offsetHeight;
var ctx = canvas.getContext("2d");
ctx.drawImage(imgElement,0,0);
var map = ctx.getImageData(0,0,320,240);
var imdata = map.data;
// convert image to grayscale
var r,g,b,avg;
for(var p = 0, len = imdata.length; p < len; p+=4) {
r = imdata[p]
g = imdata[p+1];
b = imdata[p+2];
// alpha channel (p+3) is ignored
avg = Math.floor((r+g+b)/3);
imdata[p] = imdata[p+1] = imdata[p+2] = avg;
}
ctx.putImageData(map,0,0);
// overlay filled rectangle using lighter composition
ctx.globalCompositeOperation = "lighter";
ctx.globalAlpha = 0.5;
ctx.fillStyle=tintColor;
ctx.fillRect(0,0,canvas.width,canvas.height);
// replace image source with canvas data
imgElement.src = canvas.toDataURL();
}
Assuming your markup looks like this:
假设您的标记如下所示:
<img id='myimage' src='image.jpg'/>
You could use it by calling it with the following parameters:
您可以通过使用以下参数调用它来使用它:
tintImage(
document.getElementById('myImage'),
"#550000" // for a redish tint
);
Working example here: http://jsfiddle.net/pHwmL/1/
这里的工作示例:http: //jsfiddle.net/pHwmL/1/
回答by dmp
Sure, you can get the pixel data, and do HSV adjustments on it. The method you want is getImageData (which returns a UInt8Array, not a normal js array).
当然,您可以获得像素数据,并对其进行 HSV 调整。你想要的方法是 getImageData (它返回一个 UInt8Array,而不是一个普通的 js 数组)。
There's a nice writeup herewhich should get you started. You can layer transparent canvas elements on top of each other, which should help avoiding problems with adjusting base components (in your car example, the tyres, windows etc).
有一个很好的书面记录在这里应该让你开始它。您可以将透明的画布元素相互叠加,这应该有助于避免调整基础组件(在您的汽车示例中,轮胎、窗户等)时出现问题。
回答by katherine
Usually doing something like change an image pixel by pixel is something you'd do on the server side, since it's very heavy for the browser. In the case of the Acura website there's nothing tricky going on - they just have a bunch of different JPGs. You could also try looking into Processing.js.
通常,您会在服务器端执行诸如逐像素更改图像之类的操作,因为它对浏览器来说非常繁重。在 Acura 网站的情况下,没有什么棘手的事情——他们只是有一堆不同的 JPG。您也可以尝试查看 Processing.js。