9

有没有办法像在 Flash/ActionScript 中一样仅使用 HTML5/CSS/JavaScript 来更改图像的颜色?

这是 Flash 中的一个示例:http ://www.kirupa.com/developer/actionscript/color.htm : //www.kirupa.com/developer/actionscript/color.htm 编辑:这是我希望复制的过程。

我正在尝试完成这样的事情(颜色变化方面,保留照明和阴影):http: //www.acura.com/ExteriorColor.aspx?model= TL 无需每次都加载和替换新图像;我希望能够简单地改变色调(即做一个纯 HTML5/CSS/JS 方法)。编辑:这是我希望达到的结果,而不是过程。

基本上我想改变图像的调色板/色调,同时保留图像的其他方面(如渐变、照明等)。我已经接近了,但还不够接近;我已经到了使用图像蒙版并将其合成到原始图像上的地步(有点像透明图像叠加)。下面是一些示例代码(请注意,这只是一个片段,因此它可能有效也可能无效;我只显示示例代码,以便您了解我正在尝试做什么):

<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>

使用这种方法的主要问题是图像看起来非常平坦。缺少其他东西,或者我正在使用的蒙版(这是一个纯白色不规则形状的图像)是错误的方法。

4

3 回答 3

14

此功能需要加载图像并且它必须来自同一个域(由于跨域策略)

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();
}

假设您的标记如下所示:

<img id='myimage' src='image.jpg'/>

您可以通过使用以下参数调用它来使用它:

tintImage(
    document.getElementById('myImage'),
    "#550000" // for a redish tint
);

这里的工作示例:http: //jsfiddle.net/pHwmL/1/

于 2012-11-15T15:59:51.387 回答
3

当然,您可以获取像素数据,并对其进行 HSV 调整。你想要的方法是getImageData(它返回一个UInt8Array,而不是一个普通的js数组)。

这里有一篇不错的文章,应该可以帮助您入门。您可以将透明画布元素叠加在一起,这将有助于避免调整基础组件(在您的汽车示例中,轮胎、窗户等)时出现问题。

于 2012-04-09T16:36:03.803 回答
-2

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.

于 2012-04-09T06:21:11.603 回答