Search code examples
javascriptcanvashtml5-canvas

Is there a way to rotate individual pixel from a ImageData data array?


With the following function I create seperate pixels and put them on the canvas:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;



function imageData() {
  var id = ctx.getImageData(0, 0, 50, 50);
  var pixels = id.data;

  for (var i = 0; i < 1000; ++i) {
    var x = Math.floor(Math.random() * canvasWidth);
    var y = Math.floor(Math.random() * canvasHeight);
    var r = Math.floor(Math.random() * 256);
    var g = Math.floor(Math.random() * 256);
    var b = Math.floor(Math.random() * 256);
    var off = (y * id.width + x) * 4;
    pixels[off] = r;
    pixels[off + 1] = g;
    pixels[off + 2] = b;
    pixels[off + 3] = 255;
  }
  ctx.putImageData(id, 0, 0);

}
<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>
<body onload="imageData()" >
  
  <canvas id="canvas" width="50" height="50">
  
  
</body>

</html>

Is there a way to rotate the individual pixels? I tried rotating the context in general, but this doesn't seem to work.


Solution

  • putImageData() will really "put" the pixels in place on the canvas buffer, ignoring all of the context's attributes when doing so: global-alpha, composite mode, transformation matrix, etc.

    To do what you want, you'll need to create a bitmap version of your ImageData object first.
    And to do so, the best is to use the createImageBitmap() method which returns a Promise that will resolve to an ImageBitmap object that you will be able to draw on your context using drawImage(), which is affected by the context's state.

    (async () => {
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var canvasWidth = canvas.width;
    var canvasHeight = canvas.height;
    const bmp = await createImageBitmap(imageData());
    let angle = 0;
    anim();
    
    function anim() {
      ctx.setTransform(1, 0, 0, 1, 0, 0);
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.translate(bmp.width/2, bmp.height/2);
      ctx.rotate(angle+=Math.PI/180);
      ctx.drawImage(bmp, -bmp.width/2, -bmp.height/2);
      requestAnimationFrame(anim);
    }
    
    function imageData() {
      var id = ctx.getImageData(0, 0, 50, 50);
      var pixels = id.data;
    
      for (var i = 0; i < 1000; ++i) {
        var x = Math.floor(Math.random() * canvasWidth);
        var y = Math.floor(Math.random() * canvasHeight);
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        var off = (y * id.width + x) * 4;
        pixels[off] = r;
        pixels[off + 1] = g;
        pixels[off + 2] = b;
        pixels[off + 3] = 255;
      }
     return id;
    
    }
    })().catch(console.error);
    <canvas id="canvas" width="50" height="50"></canvas>