我正在尝试制作网络工具,允许人们替换我正在销售的简单 2 色图像中的颜色。我使用的图像以 jpg 格式保存。我确实到处查看,并且确实想出了以下代码:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
img = new Image();
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img,0,0,canvas.width,canvas.height);
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var pixelArray = imageData.data;
var length = pixelArray.length / 4;
for (var i = 0; i < length; i++) {
var index = 4 * i;
var r = pixelArray[index];
var g = pixelArray[++index];
var b = pixelArray[++index];
var a = pixelArray[++index];
if (r === 0 && g === 0 && b === 0 & a === 255) {
pixelArray[--index] = 47;
pixelArray[--index] = 255;
pixelArray[--index] = 173;
}
}
context.putImageData(imageData, 0, 0);
}
img.src = "assets/images/tijana-mala.jpg";
不幸的是,我意识到许多像素不仅仅是“黑色或白色”,而且还有不同的色调。图像的复杂性相当简单,我出售报价:背景上的文本,使用各种字体。
有没有办法在我的代码之外做到这一点?
谢谢
附注我的竞争对手成功了: http://www.crownprintsart.com/color 用户名:您的电子邮件地址 密码:crownprintsdemo
最佳答案
将亮度传输到 Alpha channel
在我建议的方法中,我们可以首先根据颜色的“亮度”将黑色数据转换为 Alpha channel 。这将保留抗锯齿功能,这是边缘出现各种阴影的原因,并允许我们使用合成模式。
尽管没有说明,如果黑色不是纯黑色(即实际上是深灰色),我们可以通过组合使用简单的阈值来压缩范围。
然后使用 source-atop
合成模式为白色背景着色,最后使用 destination-atop
绘制新的黑色颜色(现在是 Alpha channel )合成模式。
使用合成模式可以更好地提高性能,因为您不必费心手动混合颜色。
使用阈值
另一种方法是使用阈值。如果颜色(灰色/亮度)高于某个值,则将其转换为颜色 A,如果低于某个值,则将其转换为颜色 B 等。
但是,这样做的问题是,抗锯齿边缘会失去其目的,并成为边缘的实心部分,这是不可取的,因为边缘最终会呈锯齿状,就像没有抗锯齿一样。我们可以通过使用非常高分辨率的原始图像来减少问题,然后将其缩小,但代价是需要迭代更多的数据。
手动混色
我们还可以手动混合颜色。使用其中一个 channel 的值作为归一化亮度/灰度值,并根据该值混合两种颜色(伪):
luma = redColor / 255; // or green/blue assuming image is grey-scale
newColor = Math.round(colorA * luma + colorB * (1 - luma));
使用组合模式的示例
此示例使用第一种技术。下面的灰色是浏览器背景色,用于显示 Alpha channel -
最终结果
var img = new Image,
ctx = c.getContext("2d");
img.onload = setup;
img.crossOrigin = "";
img.src = "https://i.imgur.com/ZJHabAD.jpg";
function setup() {
// draw in image (scaled for demo)
c.width = this.naturalWidth;
c.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
// create alpha channel from "black" pixels
var idata = ctx.getImageData(0, 0, c.width, c.height),
data = idata.data;
for(var i = 0, v; i < data.length; i += 4) {
v = data[i];
if (v < 30) v = 0; // compress grey to black (arbitrary threshold here)
data[i+3] = v;
}
ctx.putImageData(idata, 0, 0);
// replace white color
ctx.fillStyle = "#AF4979";
ctx.globalCompositeOperation = "source-atop";
ctx.fillRect(0, 0, c.width, c.height);
// replace "black" (alpha)
ctx.fillStyle = "#C6AF47";
ctx.globalCompositeOperation = "destination-atop";
ctx.fillRect(0, 0, c.width, c.height);
}
body {background:#777}
<canvas id=c></canvas>
关于javascript - 替换 Canvas 中的特定颜色及其阴影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37036631/