javascript - Canvas 像素化 - 调整像素大小

标签 javascript canvas html5-canvas

我有一个循环遍历图像的脚本。图像开始像素化,然后当它们出现在视野中时,变得非像素化。我通过使用 requestAnimationFrame

调用该函数 x 次来实现这一点
Images.prototype.setPixels = function() {
    var sw          = this.imageWidth,
        sh          = this.imageHeight,
        imageData   = this.context.getImageData( 0, 0, sw, sh ),
        data        = imageData.data,
        y, x, n, m;

    for ( y = 0; y < sh; y += this.pixelation ) {
        for ( x = 0; x < sw; x += this.pixelation ) {

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

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

    this.context.putImageData( imageData, 0, 0 );
}

问题:如何使单个像素 block 比现在更大。现在它们非常小,而且效果有点不和谐。我希望通过减少屏幕上的像素 block 并使其更大来解决这个问题。

我希望这是有道理的,我对 Canvas 还很陌生,所以你能做的任何事情来为我指明正确的方向都会很棒!

最佳答案

实现这种效果的最佳方法是简单地使用 drawImage并让浏览器通过最近邻抗锯齿算法来处理像素化,该算法可以通过更改imageSmoothingEnabled来设置属性为 false。

然后,它就变成了一个两步过程,以任意像素大小对图像进行像素化:

  • 以其原始大小/像素大小绘制全质量图像(或 Canvas /视频...)。
    在这个阶段,每个“像素”都是一个像素大。

  • 再次绘制这个小图像,但按像素大小放大。为此,您只需在 Canvas 上绘制 Canvas 即可。
    现在每个像素的 pixel_size 都很大。

我们可以通过使用 ctx.scale() 方法来轻松处理缩放,而不是处理难以读取的drawImage的许多参数。

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

function drawPixelated( source, pixel_size ) {
  // scale down
  ctx.scale(1 / pixel_size, 1 / pixel_size)
  ctx.drawImage(source, 0, 0);
  // make next drawing erase what's currently on the canvas
  ctx.globalCompositeOperation = 'copy';
  // nearest-neighbor
  ctx.imageSmoothingEnabled = false;
  // scale up
  ctx.setTransform(pixel_size, 0, 0, pixel_size, 0, 0);
  ctx.drawImage(canvas, 0, 0);
  
  // reset all to defaults
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.globalCompositeOperation = 'source-over';
  ctx.imageSmoothingEnabled = true;
}

const img = new Image();
img.onload = animeLoop;
img.src = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";

let size = 1;
let speed = 0.1;
function animeLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  size += speed;
  if(size > 30 || size <= 1) {
    speed *= -1
  }

  drawPixelated( img, size );

  requestAnimationFrame(animeLoop);
}
<canvas id="canvas" width="800" height="600"></canvas>

现在,对于那些真正需要使用 ImageData 的人,例如因为它们正在生成像素艺术,那么知道您可以简单地使用相同的技术:

  • 放置您的 ImageData,每个像素大小为 1 像素。
  • 将上下文缩放至 Pixel_size
  • 在 Canvas 上绘制放大的 Canvas

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

function putPixelated( imageData, pixel_size ) {
  ctx.putImageData(imageData, 0, 0);
  // make next drawing erase what's currently on the canvas
  ctx.globalCompositeOperation = 'copy';
  // nearest-neighbor
  ctx.imageSmoothingEnabled = false;
  // scale up
  ctx.setTransform(pixel_size, 0, 0, pixel_size, 0, 0);
  ctx.drawImage(canvas, 0, 0);
  
  // reset all to defaults
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.globalCompositeOperation = 'source-over';
  ctx.imageSmoothingEnabled = true;
}

const img = new ImageData(16, 16);
crypto.getRandomValues(img.data);

let size = 1;
let speed = 0.1;

animeLoop();

function animeLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  size += speed;
  if(size > 30 || size <= 1) {
    speed *= -1
  }

  putPixelated( img, size );

  requestAnimationFrame(animeLoop);
}
<canvas id="canvas" width="800" height="600"></canvas>

关于javascript - Canvas 像素化 - 调整像素大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57598915/

相关文章:

javascript - 如何在提交时更改表单数据?

javascript - 将一个整数分成两个(几乎)相等的部分

javascript - 在android中将文件作为图像文件写入sd卡

javascript - 动画 gif 不能在 html5 下的浏览器中播放

html - 为什么我的文本淡入但我的 html Canvas 对象不会?

javascript - 在 HTML5 Canvas 中绘制任意形状

php - 我怎样才能加快 Bootstrap 工具提示

javascript - 使用 javascript 返回上一页

javascript - 有没有办法在 Canvas 路径上平铺背景图像?

javascript - HTML5 Canvas 形状从圆形到三 Angular 形