web-dev-qa-db-ja.com

キャンバスとJavaScriptで画像をピクセル化する方法

私はcanvas要素で少し実験していて、効果を引き出す方法に興味がありました。

チュートリアルとデモのコレクションから探しているものがいくらかありますが、残りの部分をそこに到達させるためにいくつかの支援が必要です。私が探しているのは、mouseoverで画像をピクセル化し、次にmouseoutで画像を再フォーカス/ピクセル化解除することです。メインカルーセルの下にあるブロックの上にマウスを置くと、 http://www.cropp.com/ で効果の良い例を見ることができます。

ここに フィドルへのリンク 私が始めました。クロスドメインイメージ(womp womp)を使用できないため、フィドルは機能しませんが、これまでのところ、私のコードは表示されています。キャンバスオブジェクトにマウスを合わせると、画像をピクセル化できますが、取得しようとしているものとは逆になります。どんな助けやアドバイスも大歓迎です。

var pixelation = 40,
    fps = 120,
    timeInterval = 1000 / fps, 
    canvas = document.getElementById('photo'),
    context = canvas.getContext('2d'),
    imgObj = new Image();

imgObj.src = 'images/me.jpg';
imgObj.onload = function () {    
    context.drawImage(imgObj, 0, 0);
};

canvas.addEventListener('mouseover', function() {
    var interval = setInterval(function () {
        context.drawImage(imgObj, 0, 0);

        if (pixelation < 1) {
            clearInterval(interval);
            pixelation = 40;
        } else {
            pixelate(context, canvas.width, canvas.height, 0, 0);
        }
    }, timeInterval);
});

function pixelate(context, srcWidth, srcHeight, xPos, yPos) {

    var sourceX = xPos,
        sourceY = yPos,
        imageData = context.getImageData(sourceX, sourceY, srcWidth, srcHeight),
        data = imageData.data;

    for (var y = 0; y < srcHeight; y += pixelation) {
        for (var x = 0; x < srcWidth; x += pixelation) {

            var red = data[((srcWidth * y) + x) * 4],
                green = data[((srcWidth * y) + x) * 4 + 1],
                blue = data[((srcWidth * y) + x) * 4 + 2];

            for (var n = 0; n < pixelation; n++) {
                for (var m = 0; m < pixelation; m++) {
                    if (x + m < srcWidth) {
                        data[((srcWidth * (y + n)) + (x + m)) * 4] = red;
                        data[((srcWidth * (y + n)) + (x + m)) * 4 + 1] = green;
                        data[((srcWidth * (y + n)) + (x + m)) * 4 + 2] = blue;
                    }
                }
            }
        }
    }

    // overwrite original image
    context.putImageData(imageData, xPos, yPos);
    pixelation -= 1;
}
21
brandongray

ピクセル化効果を作成するためにピクセルバッファを繰り返す必要はありません。

画像のスムージングをオフにして、画像の小さなバージョンをキャンバスに拡大するだけです。これは、任意の画像をソースとして使用できることも意味します(CORSに関して)。

例:

フィドルデモ

// get a block size (see demo for this approach)
var size = blocks.value / 100,
    w = canvas.width * size,
    h = canvas.height * size;

// draw the original image at a fraction of the final size
ctx.drawImage(img, 0, 0, w, h);

// turn off image aliasing
ctx.msImageSmoothingEnabled = false;
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;

// enlarge the minimized image to full size    
ctx.drawImage(canvas, 0, 0, w, h, 0, 0, canvas.width, canvas.height);

デモでは、この効果をアニメーション化して、ブラウザーがコンパイル済みコードの内部で「ピクセル化」を処理するため、ピクセル反復方法と比較してパフォーマンスが非常に優れていることを確認できます。

39
user1693593

同じ効果を発揮するjavascriptライブラリがいくつかあることを覚えておいてください。たとえば、 pixelate または close-pixelate です。

6
Alexey B.