创建此图像而不复制绿色或使绿色透明或从100X100 px左上方去除绿色的最快方法是什么
在这种情况下,我是否必须检查每个像素值? 这个过程太慢了,例如:对于100X100px,它需要40000个循环来检查所有rgba值
答案 0 :(得分:1)
在支持该功能的浏览器中,您可以使用svg过滤器来做到这一点:
这里是an other Q/A,它显示了一种针对固定颜色执行此操作的有趣方法。
在这里,我做了一个简单的辅助函数,该函数将为我们设置所需的tableValues
并具有一定的容差,然后我移除了<feFill>
,使所选颜色变为透明色(<feFill>
会污染Chrome中的画布)。
如果您希望替换颜色,仍然可以使用canvas的合成选项(以下代码段中的注释代码)来实现。
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = e => {
canvas.width = img.width;
canvas.height = img.height;
// update our filter
updateChroma([76, 237, 0], 8);
// if you wish to replace the color, uncomment followings
// ctx.fillStyle = "your_replaceColor";
// ctx.fillRect(0,0,img.width,img.height);
ctx.filter = 'url(#chroma)';
ctx.drawImage(img, 0, 0);
ctx.filter = 'none';
// ctx.globalCompositeOperation = 'destination-in';
// ctx.drawImage(img, 0,0);
};
img.src = "https://i.stack.imgur.com/hZm8o.png";
function updateChroma(rgb, tolerance) {
const sels = ['R', 'G', 'B'];
rgb.forEach((value, ind) => {
const fe = document.querySelector('#chroma feFunc' + sels[ind]);
let vals = '';
if (!value) {
vals = '0'
} else {
for (let i = 0; i < 256; i++) {
vals += (Math.abs(value - i) <= tolerance) ? '1 ' : '0 ';
}
}
fe.setAttribute('tableValues', vals);
});
}
canvas {
background: ivory
}
<svg width="0" height="0" style="position:absolute;visibility:hidden">
<filter id="chroma" color-interpolation-filters="sRGB"x="0" y="0" height="100%" width="100%">
<feComponentTransfer>
<feFuncR type="discrete"/>
<feFuncG type="discrete"/>
<feFuncB type="discrete"/>
</feComponentTransfer>
<feColorMatrix type="matrix" values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
1 1 1 1 -1" result="selected"/>
<feComposite in="SourceGraphic" in2="selected" operator="out"/>
</filter>
</svg>
<canvas id="canvas"></canvas>
我没有在很多设备上进行广泛的测试,但是启用了硬件加速功能后,由于它应该全部在GPU上完成,因此它的性能可能比任何像素循环都要好。
但是浏览器支持仍然不是很好...
因此,无论如何,您可能都需要回退到像素操作。
在这里,根据您要进行的色度的不同,可能需要牺牲一些质量来提高速度。
例如,在视频上,您可以在缩小的画布上执行色度,然后在主画布上进行合成后将其绘制回去,从而每帧赢得几次迭代。有关示例,请参见此previous Q/A。
答案 1 :(得分:0)
如果您检查每个像素值并去除绿色,则会留下带有孔的丑陋图像。预先计划是一种更容易实现且效果更好的方法。这是用帆布生产的。绘制图像时,您可以将每个圆圈保存在数组中,然后在排除绿色圆圈之后重新绘制所有内容。
在下一个示例中,单击颜色以选择颜色,或单击 D 以删除绿色圆圈。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width = 300,
cx = cw / 2;
var ch = canvas.height = 180,
cy = ch / 2;
var color = "blue";
var drawing = false;
var points= [];
class Point{
constructor(color,x,y){
this.color = color;
this.x = x;
this.y = y
}
draw(){
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x,this.y,5,0,2*Math.PI);
ctx.fill()
}
}
canvas.addEventListener('mousedown', function(evt) {
drawing = true;
}, false);
canvas.addEventListener('mouseup', function(evt) {
drawing = false;
}, false);
canvas.addEventListener("mouseout", function(evt) {
drawing = false;
}, false);
canvas.addEventListener("mousemove", function(evt) {
if (drawing) {
ctx.clearRect(0, 0, cw, ch);
m = oMousePos(canvas, evt);
var point = new Point(color,m.x,m.y);
//point.draw();
points.push(point);
points.forEach((p) =>{
p.draw()
})
}
}, false);
function oMousePos(canvas, evt) {
var ClientRect = canvas.getBoundingClientRect();
return {
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
colors.addEventListener("click", (e)=>{
if(e.target.tagName == "SPAN"){color = e.target.id;
}else if(e.target.id == "deleteGreen"){
ctx.clearRect(0,0,cw,ch);
points.forEach( p => {
if(p.color !== "green"){p.draw()}
})
}
})
body {
background-color: #eee;
}
#app {
display: block;
margin: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 300px;
height: 300px;
}
canvas {
background: #fff;
border-radius: 3px;
box-shadow: 0px 0px 15px 3px #ccc;
cursor: pointer;
}
#colors {
display: flex;
margin-top: 1em;
justify-content: space-between;
}
#colors span, #deleteGreen {
display: block;
width: 50px;
height: 50px;
border: 1px solid #d9d9d9;
}
#green {
background-color: green;
}
#gold {
background-color: gold;
}
#tomato {
background-color: tomato;
}
#blue {
background-color: blue;
}
#deleteGreen {
text-align: center;
line-height: 50px;
}
<div id="app">
<canvas id="canvas">:( </canvas>
<div id="colors" >
<span id="green"></span>
<span id="gold"></span>
<span id="tomato"></span>
<span id="blue"></span>
<div id="deleteGreen">D</div>
</div>
</div>