2016-09-24 6 views
0

イメージマップを高さマップに変換してキャンバスに表示しようとしています。しかし、私がこれをすると、私がテストしたすべての画像について、奇妙なことが現れます。ここでイメージマップを高さマップに変換しようとしています

は私のコードです:

window.onload = function() 
 
{ 
 
\t var canvas = document.getElementById('game'); 
 
\t if(!canvas) 
 
\t { 
 
\t \t alert("Impossible de récupérer le canvas."); 
 
\t \t return; 
 
\t } 
 
\t 
 
\t var context = canvas.getContext('2d'); 
 
\t if(!context) 
 
\t { 
 
\t \t alert("Impossible de récupérer le contexte du canvas."); 
 
\t \t return; \t \t 
 
\t } 
 
\t 
 
\t var img = new Image(); 
 
\t img.src = "noise.png"; 
 
\t 
 
\t var size = 250000; 
 
\t var data = new Float32Array(size); 
 
\t var pxlData = new Array(size); 
 

 
\t for (var i = 0; i < size; i ++) { 
 
     data[i] = 0 
 
    } 
 
\t 
 
\t for (var i = 0; i < size; i++) 
 
\t { 
 
\t \t pxlData[i] = new Array(4); 
 
\t \t pxlData[i][0] = 0; 
 
\t \t pxlData[i][1] = 0; 
 
\t \t pxlData[i][2] = 0; 
 
\t } 
 
\t 
 
\t img.onload = function() 
 
\t { 
 
\t \t context.drawImage(img, 0, 0); 
 
\t \t 
 
\t \t var imgd = context.getImageData(0, 0, 500, 500); 
 
\t 
 
\t \t context.clearRect(0, 0, canvas.width, canvas.height); 
 
\t \t 
 
\t \t var pix = imgd.data; 
 

 
\t \t var j=0; 
 
\t \t var x=0; 
 
\t \t var y=0; 
 
\t \t var i=0; 
 
\t \t 
 
\t \t for (var i = 0, n = pix.length; i < n; i += (4)) { 
 
\t \t \t var all = pix[i]+pix[i+1]+pix[i+2]; 
 
\t \t \t 
 
\t \t \t pxlData[j][0] = pix[i]; 
 
\t \t \t pxlData[j][1] = pix[i+1]; 
 
\t \t \t pxlData[j][2] = pix[i+2]; 
 
\t \t \t pxlData[j][3] = pix[i+3]; 
 
\t \t \t 
 
\t \t \t data[j++] = all/3; 
 
\t \t } \t \t 
 
\t \t 
 
\t \t var alpha; 
 
\t \t 
 
\t \t for(y = 0; y < 500; y++) 
 
\t \t { 
 
\t \t \t for(x = 0; x < 500; x++) 
 
\t \t \t { 
 
\t \t \t \t if(data[x * y] <= 100){ 
 
\t \t \t \t \t context.fillStyle = "blue"; 
 
\t \t \t \t }else if(data[x * y] >= 100){ 
 
\t \t \t \t \t context.fillStyle = "green"; 
 
\t \t \t \t } 
 
\t \t \t \t //context.fillStyle = 'rgba('+ data[x * y] +', '+ data[x * y] +', '+ data[x * y] +', 1)'; 
 
\t \t \t \t context.fillRect(x, y, 1, 1); 
 
\t \t \t \t 
 
\t \t \t \t // context.fillStyle = 'rgba('+ pxlData[x * y][0] +', '+ pxlData[x * y][1] +', '+ pxlData[x * y][2] +', '+ pxlData[x * y][3] +')'; 
 
\t \t \t \t // context.fillRect(x, y, 1, 1); 
 
\t \t \t } 
 
\t \t } 
 
\t }; 
 
\t 
 

 
}
<!DOCTYPE html> 
 
\t <html> 
 
\t \t <head> 
 
\t \t \t <link rel="stylesheet" href="style.css" type="text/css"> 
 
\t \t \t <script type="text/javascript" src="game.js"></script> 
 
\t \t \t <title>Génération de terrain</title> 
 
\t \t </head> 
 
\t \t <body> 
 
\t \t \t <canvas id="game" width="500" height ="500">Votre navigateur ne supporte pas les canvas.</canvas> 
 
\t \t </body> 
 
\t </html>

私はそれを実行したとき、それは次のように見ている何が:

canvas

+0

あなたはどのような効果を得ようとしていますか? – JonSG

答えて

0

エラーがどのようにインデックスをピクセル単位であります32ビット浮動小数点配列

data[x * y]は、0,0のピクセルがインデックス0 * 0 = 0にあり、ピクセルが0,100も0 * 100 = 0になり、他のすべてのインデックスが間違っていることを意味します。正しいピクセルアドレスを取得するには、1つのアイテムがピクセルである配列からインデックスを作成するときにx + y * widthを使用します。ピクセルデータ 'imageData.data'にインデックスを付けると各ピクセルは4つのアイテム(r、g、b、a)になりますので、data[x * 4 + y * canvas.width * 4]以上を使用してください。imageData.data[x + y * canvas.width * 4]

コードを見ると、あなたができることに比べて非常に遅く実行されます。私はあなたのコードを単純化しました。それは同じですが、すべてのオーバーヘッドがありません。コメントを追加してコードを削除し、同じことをする別の方法を提案しました。

最も大きな変化は、緑色と青色のループのレンダリングです。 context.fillRect(x,y,1,1);で各ピクセルを設定する場所は非常に遅いです。各ピクセルの矩形を描画するのではなく、取得したimageDataを使用し、高さを読み取った後に色を塗りつぶし、そのデータをキャンバスに戻します。 2つのtypeArrayビューを使用してデータを設定して読み込み、パフォーマンスも向上させました。

// convert r,g,b,a to 32 bit colour using correct little or big endian 
function create32Pixel(r, g, b, a){ // dont call this inside loops as very slow 
    var endianConvert = new Uint8ClampedArray(4); // use to convert to correct endian 
    var endianConvert32 = new Uint32Array(endianConvert.buffer); 
    endianConvert[0] = r; 
    endianConvert[1] = g; 
    endianConvert[2] = b; 
    endianConvert[3] = a; 
    return endianConvert32[0]; 
} 

window.onload = function() 
{ 
    var canvas = document.getElementById('game'); 
    if(!canvas) 
    { 
     alert("Impossible de récupérer le canvas."); 
     return; 
    } 

    var context = canvas.getContext('2d'); 
    if(!context) 
    { 
     alert("Impossible de récupérer le contexte du canvas."); 
     return;  
    } 

    var img = new Image(); 
    img.src = "noise.png"; 

    var size = 250000; 
    // Do you really need floats?? 16 bit unsigned int array can hold 255 * 3 and all javascript 
    // numbers are converted to 64 bit floats so you will not lose precision from original when manipulating the 16bit values. 
    // following array is not needed. 
    //var dataFloat = new Float32Array(size); 
    // following array is not needed. 
    //var pxlData = new Array(size); // bad way to create an array 
    //var pxlData = []; // create empty array and push onto it. 


    // can use dataFloat.fill() 
    /*for (var i = 0; i < size; i ++) { 
     dataFloat[i] = 0 
    }*/ 
    //dataFloat.fill(0); // but not needed as array is zeroed when created (not from an existing buffer) 

    // Very inefficient as you are creating a new array for every pixel. Use flat array instead. 
    /*for (var i = 0; i < size; i++) 
    { 
     pxlData[i] = new Array(4); 
     pxlData[i][0] = 0; 
     pxlData[i][1] = 0; 
     pxlData[i][2] = 0; 
    }*/ 
    // should do 
    /*var i; 
    while(i < size * 4){ 
     pxlData[i++] = 0; // array grows as you increase i; 
    }*/ 

    img.onload = function() 
    { 
     context.drawImage(img, 0, 0); 

     var imgd = context.getImageData(0, 0, canvas.width, canvas.height); 

     // don't need to clear 
     // context.clearRect(0, 0, canvas.width, canvas.height); 

     // make two views one 8bit and the other 32bit. Both point to the same data change one 
     // changes the other 
     var pixChannels = imgd.data; 
     var pixels = new Uint32Array(pixChannels.buffer); 

     var j,x,y,j; 
     j = x = y = i = 0; 


     // Create pixel colours. Need to ensure correct order as some systems 
     // use little edian and others big endian 
     // see https://en.wikipedia.org/wiki/Endianness for info. 
     var green = create32Pixel(0,255,0,255); 
     var blue = create32Pixel(0,0,255,255); 


     // use j as 32bit pixel index and i as 8bit index 
     // read the height and set pixel colour accordingly. 
     while(j < pixels.length){ 
      var height = pixChannels[i++] + pixChannels[i++] + pixChannels[i++]; 
      if(height <= 300){ // no need to divide by 3 just test for 3 time 100 
       pixels[j++] = blue; 
      }else{ 
       pixels[j++] = green; 
      } 
      i++; // skip alpha channel 
     } 
     context.putImageData(imgd,0,0); // put pixels back to canvas. 

    }; 



} 
関連する問題