我在javascript中创建了一个过滤器,它反转了图像的颜色,即创建了一个负片图像,现在当我在浏览器中运行它时需要时间来处理,然后返回最终的负片图像。如何才能看到图像的每个像素都被反转而不仅仅是最终的反转图像?我没有等待代码在整个像素阵列上实现然后看到它的效果,而是希望看到每个像素都被代码更改,直到最后一个像素。
var imgData = ctx.getImageData(0,0,x.width,x.height);
var d = imgData.data;
for (var i=0; i< d.length; i+=4) {
d[i] = 255 - d[i];
d[i+1] = 255 - d[i+1];
d[i+2] = 255 - d[i+2];
}
ctx.putImageData(imgData,0,0);
新代码
invert(d,0);
function invert(d,i){
if(i < d.length){
d[i] = 255 - d[i];
d[i+1] = 255 - d[i+1];
d[i+2] = 255 - d[i+2];
d[i+3] = d[i+3];
//alert(i);
var n=i/4;
var h=parseInt(n/x.width);
var w = n - h*x.width;
ctx.fillStyle='rgba('+d[i]+','+d[i+1]+','+d[i+2]+','+d[i+3]/255+')';
ctx.fillRect(w,h,1,1);
//if(i>91000){alert(i);}
setTimeout(invert(d,i+4),50);
}
else{return ;}
}
答案 0 :(得分:0)
您需要使用异步&#34;循环&#34;所以你可以更新一些像素,让显示更新结果,然后继续。
JavaScript是单线程的,所以在线程被占用之前,当前循环完成之前不会更新任何内容。
您可以使用以下方法。您定义了一个&#34;批次&#34;要反转的像素数的大小(如果要查看每个像素,则1有效,但这可能需要很长时间:
ie. 16.67ms x total number of pixels.
因此,如果您想要显示每个像素更新的图像为640x400(如下面的演示),则需要:
640 x 400 x 16.67ms = 4,267,520 ms, or more than an hour
要记住的事情(显示器的更新速度不能超过16.67ms = 60 fps)。下面我们每批使用128个像素。
请注意,批次值必须与图像的宽度匹配。 F.ex.如果您的图像宽度为640像素,则可以使用1,5,10,20 ...... 64,128等。
如果你想要的宽度不一定除1或小数值以外的任何值,你必须做一个简单的计算来限制一行的最后一批,因为getImageData()
需要参数来定义一个区域内的区域。图片。或者,一行一行......
你也可以使用&#34;批次&#34;垂直图块的值(在这种情况下,框可能是一个更好的术语)。
var img = new Image();
img.crossOrigin = "";
img.onload = painter;
img.src = "http://i.imgur.com/Hl3I0cx.jpg";
function painter() {
// setup canvas and image
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d");
// set canvas size = image size
canvas.width = this.naturalWidth; canvas.height = this.naturalHeight;
// draw in image
ctx.drawImage(this, 0, 0);
// prepare loop
var batch = 128,
x = 0, y = 0,
w = canvas.width - batch,
h = canvas.height;
(function asyncUpdate() {
// do one batch only
var idata = ctx.getImageData(x, y, batch, 1), // get a bacth of pixels
data = idata.data,
i = 0, len = data.length;
while(i < len) { // invert the batch
data[i] = 255 - data[i++];
data[i] = 255 - data[i++];
data[i] = 255 - data[i++];
i++
}
ctx.putImageData(idata, x, y); // update bitmap
x += batch;
if (x > w) { // check x pos
x = 0;
y++;
}
if (y < h) { // new batch?
requestAnimationFrame(asyncUpdate); // let display update before next
}
else {
// use a callback here...
console.log("Done");
}
})();
}
&#13;
<canvas></canvas>
&#13;
答案 1 :(得分:-1)
你可以在画布上context.fillRect
每个新更改的像素进行计算。
这样的事情(警告:未经测试的代码,可能需要tweeks!):
var n=i/4;
var y=parseInt(n/canvas.width);
var x=n-y*canvas.width;
context.fillStyle='rgba('+d[i]+','+d[i+1]+','+d[i+2]+','+d[i+3]/255')';
context.fillRect(x,y,1,1);
这是演示代码,首先进行反演,然后显示随时间变化的影响:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var nextTime=0;
// a new line of converted image will be displayed
// after this delay
var delay=1000/60*2;
var y=0;
var imgData,d;
var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/sun.png";
function start(){
cw=canvas.width=img.width;
ch=canvas.height=img.height;
ctx.drawImage(img,0,0);
imgData=ctx.getImageData(0,0,cw,ch);
d=imgData.data;
for (var i=0; i< d.length; i+=4) {
d[i] = 255 - d[i];
d[i+1] = 255 - d[i+1];
d[i+2] = 255 - d[i+2];
}
requestAnimationFrame(animate);
}
function animate(time){
if(time<nextTime){requestAnimationFrame(animate); return;}
nextTime=time+delay;
for(var x=0;x<cw;x++){
var i=(y*cw+x)*4;
ctx.fillStyle='rgba('+d[i]+','+d[i+1]+','+d[i+2]+','+d[i+3]/255+')';
ctx.fillRect(x,y,1,1);
}
if(++y<ch){
requestAnimationFrame(animate);
}else{
ctx.putImageData(imgData,0,0);
}
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>