我正在尝试制作一个网络工具,让人们可以在我销售的简单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";
不幸的是,我意识到许多像素不仅仅是“黑色”或“白色”。但它有不同的色调。图像的复杂性相当简单,我卖报价:背景文字,使用各种字体。
除了我的代码之外,还有办法做到这一点吗?
谢谢
P.S。我的比赛在那里进行: http://www.crownprintsart.com/color 用户名:您的电子邮件地址 密码:crownprintsdemo
答案 0 :(得分:2)
在方法中我建议我们可以先根据&#34;亮度&#34;将黑色数据转换为alpha通道。的颜色。这将保持抗锯齿,这是沿着边缘的各种阴影的原因,并允许我们使用合成模式。
虽然没有说明,如果黑色不是纯黑色(即实际上是深灰色),我们可以通过组合使用简单的阈值来压缩范围。
然后使用source-atop
合成模式为白色背景着色,最后使用destination-atop
合成模式为黑色(现在是Alpha通道)绘制新颜色。
使用合成模式可以提高性能,因为您不必手动混合颜色。
另一种方法是使用阈值。如果颜色(灰色/亮度)高于某个值,则将其转换为颜色A,如果颜色为B,则将其转换为颜色A.
然而,问题在于抗锯齿边缘将失去其目的并成为边缘的实心部分,这是不可取的,因为边缘将最终锯齿状,就像没有消除锯齿一样。我们可以通过使用一个非常高分辨率的原始文件来减少这个问题,我们后来缩小它们但是惩罚是有更多的数据需要迭代。
我们也可以手动混合颜色。使用其中一个通道的值作为标准化亮度/灰度值,并根据此值混合两种颜色(伪):
luma = redColor / 255; // or green/blue assuming image is grey-scale
newColor = Math.round(colorA * luma + colorB * (1 - luma));
此示例使用第一种技术。下面的灰色是显示Alpha通道的浏览器背景颜色 -
最终结果
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);
}
&#13;
body {background:#777}
&#13;
<canvas id=c></canvas>
&#13;
答案 1 :(得分:0)
您可以检查颜色是否接近特定值,而不是检查确切的值。可能有更好的方法,但这是我的解决方案:
var precision = 10;
var replaceColor = {
r: 0,
g: 0,
b: 0,
a: 255,
};
var isInRange = (
r >= replaceColor.r - precision &&
r <= replaceColor.r + precision &&
g >= replaceColor.g - precision &&
g <= replaceColor.g + precision &&
b >= replaceColor.b - precision &&
b <= replaceColor.b + precision &&
a >= replaceColor.a - precision &&
a <= replaceColor.a + precision
);
if(isInRange) {
}
希望这有帮助