2017-07-02 6 views
0

私は写真映像ショーとして context.putImageDataは間違っ

enter image description here

、貼り付けられた画像データが適切に設定されていないとして、100の長方形の各平均色を取得しようとしています座標。しかし、( ctx.getImageData()ctx.putImageData())のすべての座標パラメータは console.log絵と同じで、私は

enter image description here

それはバグです

を取り付けたのですか?それとも私は何かが恋しい?

convert(){ 
    let canvas = this.$el.querySelector('#pixel-art-canvas'), 
     image = this.$el.querySelector('#upload-image'), 
     ctx = canvas.getContext('2d'), 
     degree = 10, 
     img = new Image, 
     tiles = Math.pow(degree,2), 
     eachWidth,eachHeight; 

    img.src = image.src; 
    ctx.drawImage(img,0,0); 

    eachWidth= canvas.width/degree; 
    eachHeight= canvas.height/degree; 

    for(let k = 0; k < tiles; k++) { 
    let imgd,x,y, 
     rgb = {r:0,g:0,b:0}, 
     count = 0; 

    x = (k % degree) * eachWidth; 
    y = (k/degree) * eachHeight; 
    imgd = ctx.getImageData(x, y, eachWidth, eachHeight); 
    console.log('x: ' + x + ' , y:' +y+' , w: '+eachWidth + ' , h :' +eachHeight); 

    for (let i=0; i < imgd.data.length; i=i+4) { 
     rgb.r += imgd.data[i]; 
     rgb.g += imgd.data[i+1]; 
     rgb.b += imgd.data[i+2]; 
     count++; 
    } 

     rgb.r = ~~(rgb.r/count); 
     rgb.g = ~~(rgb.g/count); 
     rgb.b = ~~(rgb.b/count); 

    for (let j=0; j < imgd.data.length; j=j+4) { 
      imgd.data[j] = rgb.r; 
      imgd.data[j+1] = rgb.g; 
      imgd.data[j+2] = rgb.b; 
     } 

    ctx.putImageData(imgd, x, y, 0, 0, eachWidth, eachHeight); 
    console.log('x: ' + x + ' , y:' +y+' , w: '+eachWidth + ' , h :' +eachHeight); 
    }//end for 

} 

答えて

0

問題は、間違ってy座標を計算していることです。

は、あなたがそれを掛ける前に値を(床)を丸めるする必要があります(K /度)のための小数の結果が得られます

y = (k/degree) * eachHeight; 

を持っています。

// to fix the y coord. 
y = Math.floor(k/degree) * eachHeight; 
// or 
y = ((k/degree) | 0) * eachHeight; 

また、色の平均値が正しく表示されません。 RGB値はピクセルの強度の平方根を表します。したがって、128と256のRGB値の間の強度の差は、2倍ではなく4倍の明るさの差である。

RGB値を加算するだけで平均をとると、結果は暗くなります。

正しい方法は、RGB値の2乗の平均値を取得し、対数RGBに戻してキャンバスに戻すことです。あなたはまた、経由少しを最適化することができます

const rgb = {r:0,g:0,b:0}; 
var count = 0; 

for (let i=0; i < imgd.data.length; i=i+4) { 
    rgb.r += imgd.data[i] * imgd.data[i]; // Square the value 
    rgb.g += imgd.data[i + 1] * imgd.data[i + 1]; 
    rgb.b += imgd.data[i + 2] * imgd.data[i + 1]; 
    count++; 
} 
// Get mean and convert back to logarithmic 
// Also you do not need to floor the values with ~~(val) as 
// the array is of type Uint8ClampedArray which will floor and clamp the 
// values for you. 
// Also ~~(val) requires 2 operations, a quicker way the requires only one 
// operation is (val) | 0 
rgb.r = Math.sqrt(rgb.r/count); 
rgb.g = Math.sqrt(rgb.g/count); 
rgb.b = Math.sqrt(rgb.b/count); 

for (let j=0; j < imgd.data.length; j=j+4) { 
     imgd.data[j] = rgb.r; 
     imgd.data[j+1] = rgb.g; 
     imgd.data[j+2] = rgb.b; 
    } 

ctx.putImageData(imgd, x, y, 0, 0, eachWidth, eachHeight); 

をコーディング

変更。

const x = (k % degree) * eachWidth; 
const y = ((k/degree) | 0) * eachHeight; 
const imgd = ctx.getImageData(x, y, eachWidth, eachHeight); 
const rgb = {r : 0, g : 0, b : 0}; 
const count = imgd.data.length/4; 
var i = 0; 
while(i < imgd.data.length) { 
    rgb.r += imgd.data[i] * imgd.data[i++]; // square the value 
    rgb.g += imgd.data[i] * imgd.data[i++]; 
    rgb.b += imgd.data[i] * imgd.data[i++]; 
    i ++; 
} 
// need to round as we are not directly adding back to the buffer. 
rgb.r = Math.sqrt(rgb.r/count) | 0; 
rgb.g = Math.sqrt(rgb.g/count) | 0; 
rgb.b = Math.sqrt(rgb.b/count) | 0; 

// get a refer to 32 bit version of same data and set all values 
// the 0xFF000000 sets the alpha to 255 
// shift red 2 bytes (16 bits) 
// shift green 1 byte (8 bit) 
// blue is in the correct place. 
new Uint32Array(imgd.data.buffer).fill(
    0xFF000000 + (rgb.r << 16) + (rgb.g << 8) + rgb.b 
); 

// putImageData use 3 arguments imgd and the x, y if you are 
// copying all the data back to the canvas. 
ctx.putImageData(imgd, x, y); 
+0

ワウ..私はこのすべてのあなたの深い理解を信じることはできません...素晴らしいプログラマーです –