3

i'm facing a bug in my script that i don't understand. I try to modify a canvas imageData after modifying it's data. data is a Int32Array

var clampedArray = new Uint8ClampedArray(data);
var newImgData=ctx.createImageData( WIDTH, HEIGHT);
newImgData.data = clampedArray;
console.log(newImgData.data, clampedArray);
ctx.putImageData(newImgData,0 ,0);

This console.log() return :

 Uint8ClampedArray { 0=0, 1=0, 2=0, plus...} Uint8ClampedArray { 0=37, 1=54, 2=18, plus...}

So newImageData.data is not modify by this line :

newImgData.data = clampedArray;

What the hell? i should miss something, but what?

Scandinave
  • 1,388
  • 1
  • 17
  • 41

3 Answers3

3

The correct method of setting new image data is to use the set() method:

newImgData.data.set(clampedArray);
MacroMan
  • 2,335
  • 1
  • 27
  • 36
1

Swapping imageData.data with a different array has always been problematic--maybe because of the hidden cross-domain security safeguards built into canvas.

More reliable is copying each new data element into the imageData.data array:

http://jsfiddle.net/m1erickson/s9DA4/

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var WIDTH=canvas.width;
    var HEIGHT=canvas.height;

    var data=[];
    for(var i=0;i<WIDTH*HEIGHT;i++){
        data=data.concat([0,255,0,255]);
    }

    var newImgData=ctx.createImageData(WIDTH,HEIGHT);
    for(var i=0;i<newImgData.data.length;i+=4){
        newImgData.data[i+0]=data[i+0];
        newImgData.data[i+1]=data[i+1];
        newImgData.data[i+2]=data[i+2];
        newImgData.data[i+3]=data[i+3];
    }

    ctx.putImageData(newImgData,0 ,0);
markE
  • 102,905
  • 11
  • 164
  • 176
0

You can omit Uint8ClampedArray if your array use numbers - JS cast it to 0-255 integer numbers automagically e.g. data=[10.5,1000,-10,4] -> [10,255,0,4] so you can just write:

newImgData.data.set(data);
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345