2015-04-21 75 views
-1

我已經在JavaScript中創建了一個過濾器,它顛倒了圖像的顏色,即創建了一個負面圖像,現在,當我在瀏覽器中運行它時,需要時間來處理並返回最終的負面形象。我怎樣才能看到圖像的每個像素被倒置,而不僅僅是最終的倒像?我不希望代碼在整個像素數組上實現,然後看到其效果,我希望看到每個像素都被代碼更改爲最後一個像素。如何查看在畫布上更改的每個像素html5

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

回答

-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>

+0

應該變種X = N - Y *畫布。寬度,糾正後的邏輯是正確的,但仍然是圖片反轉非常快,所以我決定在每個像素更新後添加一個setTimeout,並更改了代碼,但這不起作用。我正在編輯代碼。 –

+0

感謝我的錯誤 - 我今天早上很匆忙!我已經發布了一個演示,首先完全顛倒「imageData.data」,然後使用這些轉換後的像素爲觀看者減緩曝光。祝你的項目好運! – markE

+0

謝謝,它幫了很多:) –

1

您需要使用異步「循環」,以便您可以更新s像素,讓顯示更新結果,然後繼續。

JavaScript是單線程的,所以在當前循環完成時沒有任何更新,因爲線程已被佔用。

看着油漆變幹

這裏有一個方法,你可以使用。您可以定義要反轉(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.67毫秒= 60幀速度更快)下面我們用128。像素每批

實例

請注意,批量值必須與圖像的寬度相匹配。 F.ex.如果您的圖像寬度爲640像素,則可以使用1,5,10,20,... 64,128等。

如果您希望寬度不一定除1或小數值之外的任何值,則必須執行一個簡單的計算來限制最後一批的一行爲getImageData()需要參數來定義圖像內的區域。或者,只是一行一行......

你也可以使用「批」的垂直瓷磚值(在這種情況下,框可能是一個更好的術語)。

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"); 
 
    } 
 
    })(); 
 
}
<canvas></canvas>

+0

解決方案非常好,但可以在不使用動畫的情況下完成嗎?我的意思是fillRect(x,y,1,1)方法將每個像素一個接一個地放在它的位置,如果我們添加一個延遲,那麼我們實際上可以看到每個像素被放置?我試圖做到這一點,我已經添加了一個新的代碼,但似乎有一些問題。 –