如何在画布html5上看到每个像素被更改

时间:2015-04-21 10:50:49

标签: javascript html5 algorithm image-processing canvas

我在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 ;}
    }

2 个答案:

答案 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;垂直图块的值(在这种情况下,框可能是一个更好的术语)。

&#13;
&#13;
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;
&#13;
&#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>