【问题标题】:Canvas - Change colors of an image using HTML5/CSS/JS?Canvas - 使用 HTML5/CSS/JS 更改图像的颜色?
【发布时间】:2012-04-21 14:06:20
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 一旦你得到答案,请发布一个完整的小提琴。谢谢!

标签: javascript css html canvas html5-canvas


【解决方案1】:

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

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/

【讨论】:

  • 请注意,当您说跨域时,使用 chrome 进行本地开发的人将无法看到它的正常工作(我总是在本地直通网络服务器上运行以验证它会工作。)我喜欢你的方法,但发现它覆盖了任何 alpha 通道......所以我添加了一个 alphas 数组,然后将它们写回来。效果很好。代码:github.com/jaycrossler/django-gamification/blob/master/…
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    通常在服务器端执行诸如逐像素更改图像之类的操作,因为这对浏览器来说非常繁重。就 Acura 网站而言,没有什么棘手的问题 - 他们只是有一堆不同的 JPG。您也可以尝试查看 Processing.js。

    【讨论】:

    • 我没有逐个像素地绘制任何东西;我在现有图像上合成图像蒙版,这比每次查询后端进行颜色更改要快得多。讴歌所做的是我想要达到的结果,而不是过程。 Flash 可以很好地改变颜色/色调(它是即时的),但可悲的现实是,您不能在 iPad 上使用 Flash,这就是我正在寻找 HTML5 解决方案的原因。
    猜你喜欢
    • 2015-05-23
    • 2021-04-23
    • 2012-04-30
    • 1970-01-01
    • 2013-03-22
    • 2011-06-09
    • 2014-08-15
    • 1970-01-01
    • 2019-04-22
    相关资源
    最近更新 更多