-1

I'm trying to translate an iteration over two arrays into one that's 4 times the size of the combined arrays, to make an image,

example input => [[1][0]]
expected output=> [[255][255][255][255][0][0][0][255]]

the ((height*width+index)*4) (i have tried with and without the *4) is what I have understood to be the formula for translating that to the rgba of the ImageData().data;

I'm writing only the latest row, will slice/join/slice the ImageData.data so that I only write one line per draw.

the expected visual is a visualization of a 2-d cellular automata rule, drawn 1 line at a time.

the actual: weird circuit bend-y, pulsating patterns.

     draw(){
          if(this.height<this.lineNum){ //lineNum is the current y draw line
               this.image.data = this.image.data.slice(this.width*4).join(this.image.data.slice(0,this.width*4)); //cut the begining, put it at the end, then write over it so it moves
          }
          this.nodes.forEach((node,x)=>{ 
               const state = node.lastState(); 
               const index = (((Math.min(this.lineNum,this.height))*x + (node.index))*4);
               this.image.data[index+0]=state?255:0;
               this.image.data[index+1]=state?255:0;
               this.image.data[index+2]=state?255:0;
               this.image.data[index+3]=255;     
          })
          this.ctx.putImageData(this.image ,0,0);  
     }

here's the full code, but I am sure that I have this formula wrong somehow.

the snippet above is from line 61's draw function.

https://codepen.io/altruios/pen/QWEoYXz?editors=1010

Edit

const index = (((Math.min(node.state.length-1,this.height))*this.width + (node.index))*4);

produces something more 'stable' but still incorrect.

so I think that formula may be correct, and there is some state update logic not happening correctly.

altruios
  • 986
  • 1
  • 10
  • 29
  • 1
    `x` is the index of your node in the list, I doubt it's what you want. You would want to multiply the current row index per the width of your canvas (maybe `this.width`?) Also, using `const arr = new Uint32Array( this.image.data.buffer );` you can then replace the 4 assignments to a single `arr[ index ] = state ? 0xFFFFFFFF : 0xFF000000;` where `index` doesn't need the `* 4` multiplication. – Kaiido Nov 17 '20 at 07:02
  • x and node.index are the same value. I think it's what I want, it represents the x-axis of the canvas, no? and I'll give that a try with the new array assignment every draw frame. – altruios Nov 17 '20 at 07:20
  • 1
    If you have row_index and column_index, the flatten index is `(row_index * image_width) + column_index`. – Kaiido Nov 17 '20 at 07:28
  • I get the translation up the Uint32, but don't you need to go back down to a clamped 8 if you make a new image? – altruios Nov 17 '20 at 07:31
  • 1
    No, TypedArrays are just views over the ArrayBuffer. So when we do `new Uint32Array( this.image.data.buffer )` and modify that array, the ArrayBuffer gets modified, and so the `this.image.data` Uint8ClampedArray view reflects that change too. – Kaiido Nov 17 '20 at 07:38
  • oh, so it mutates the image? interesting... – altruios Nov 17 '20 at 15:37
  • 1
    Well... it does mutate the ImageData's buffer. However this ImageData is not linked to the canvas's buffer anymore, so it doesn't mutate what's drawn on the canvas. – Kaiido Nov 18 '20 at 07:51

1 Answers1

0

the strange behavior is fixed. as it turns out, it was partially this error that was fixed in the edit, but in addition, there was mutation happening to the array as it was being calculated, thus - the fix was to make sure to always process the state always on the exact index, instead of just the last index.

altruios
  • 986
  • 1
  • 10
  • 29