0

I have been working on a project in Javascript and after a certain development stage, the code stopped working. I've narrowed the problem down to creating and indexing "multi-dimensional" arrays in Javascript. I've included code just to test creating arrays of arrays, assigning color values to the arrays, and then a test if the values can be displayed on-screen via a loop that iterates through the "multi-dimensional array".

I've tried just about every method of creating arrays of arrays in Javascript -- some code snippets from answers even here -- but nothing has worked.

function setRGB(image, width1, x1, y1, r, g, b, a) {
  var t1 = y1 * width1 * 4 + x1 * 4;
  image.data[t1] = r;
  image.data[t1 + 1] = g;
  image.data[t1 + 2] = b;
  image.data[t1 + 3] = a;
}

function draw() {
  var pixels = [];
  for (var i = 0; i < height; ++i) {
    var row = [];
    for (var j = 0; j < width; ++j) {
      row[j] = 0;
    }
    pixels[i] = row;
  }

  var k = 12;
  var j = 29;
  console.log(pixels[12][29].toString());

  var canvas = document.getElementById('test');
  var width = 500;
  var height = 500;
  canvas.width = width;
  canvas.height = height;
  var ctx = canvas.getContext('2d');
  var canvasImage = ctx.getImageData(0, 0, width, height);
  var testImage = ctx.createImageData(width, height);

  for (var y = 0; y < height; ++y) {
    for (var x = 0; x < width; ++x) {
      pixels[y][x] = Math.round(Math.random() * 255);
    }
  }

  for (y = 0; y < height; ++y) {
    for (x = 0; x < width; ++x) {
      console.log(pixels[y][x].toString());
    }
  }

  for (var y = 0; y < height; ++y) {
    for (var x = 0; x < width; ++x) {
      setRGB(testImage, width, pixels[y][x], pixels[y][x], pixels[y][x], 255);
      ctx.putImageData(testImage, 0, 0);
      canvasImage = testImage;
      ctx.putImageData(canvasImage, 0, 0);
    }
  }
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <title>Array test</title>
</head>

<body onload="draw();">
  <canvas id="test">Sorry, but your browser doesn't support the 'canvas' element.</canvas>
</body>

</html>

In Google Chrome, nothing is displayed on-screen and the web console shows the error :

array-plot-test-1.html:26 Uncaught TypeError: Cannot read property '29' of undefined
    at draw (array-plot-test-1.html:26)
    at onload (array-plot-test-1.html:60)

even though the array of arrays is indexed in its creation loop.

The first time the array is indexed outside its creation loop consists of the test code :

var k = 12;
var j = 29; 
console.log(pixels[12][29].toString());

In Mozilla Firefox, I get the error :

TypeError: pixels[12] is undefined[Learn More] array-plot-test-1.html:26:3
    draw file:///[censored]/[censored]/[censored]/array-plot-test-1.html:26
    onload file:///[censored]/[censored]/[censored]/array-plot-test-1.html:1

I've rewritten the array test code about a dozen different times, at least, using "solutions" provided by sites such as Stack Overflow, but nothing has worked so far. I expect there is some basic error that I've made.

Curiously, if I create a "multi-dimensional array" in Javascript like so

array1 = [];
for (var i=0; i < max; ++i) {
  var temp = [1, 2, 3];
  array[i] = temp;
}

with a pre-defined array, then Javascript "multi-dimensional arrays" work fine, but I need arrays of arrays of arbitrary size which is why I can't use the above code snippet.

Barmar
  • 741,623
  • 53
  • 500
  • 612
jdb2
  • 101
  • 6
  • 1
    Could it be that your array just does not have `29` items in it? – Titulum Jun 25 '19 at 17:58
  • It doesn't matter what the size of my array is : when I create *any* array of arrays, using any size for the rows and columns, then indexing the array ie. a[1][2], generates an error. In other words, the error doesn't seem to depend on the array size. And yes, my array has 500 rows and 500 columns, so I don't know what is causing the error. – jdb2 Jun 25 '19 at 18:06
  • 1
    But you are using the variables `width` and `height` before they are initialized. Please use `let` instead of `var` and these issues will be avoided in the future. – Titulum Jun 25 '19 at 18:08
  • Use `push()` method when adding an array-row to your array – Kate Orlova Jun 25 '19 at 18:11
  • I tried changing the array creation code by replacing it by : `var pixels = new Array(height); for (i=0; i < height; ++i) { var a1 = new Array(width); pixels[i] = a1; }` – jdb2 Jun 25 '19 at 18:12
  • HAHA! XD I can't believe a made such a stupid mistake and how I overlooked it :) Thanks so much titulum :D – jdb2 Jun 25 '19 at 18:19

2 Answers2

1

You defined width and height after using them. You need to define them before using them.

You also were not passing x and y to setRGB

I suggest you learn how to use the debugger in your browser.

Not sure why you had this

ctx.putImageData(testImage, 0, 0);
canvasImage = testImage;
ctx.putImageData(canvasImage, 0, 0)

inside your loop. You’re drawing the same thing twice plus your drawing both of those 500x500 times. You won’t see the result until your draw function exits so there’s no reason to do that inside the loop. Just moved it after the loop.

Also, put

“use strict”;

at the top of your JavaScript and never use var, use const and let as they will help you find these kinds of issues.

function setRGB(image, width1, x1, y1, r, g, b, a) {
  var t1 = y1 * width1 * 4 + x1 * 4;
  image.data[t1] = r;
  image.data[t1 + 1] = g;
  image.data[t1 + 2] = b;
  image.data[t1 + 3] = a;
}

function draw() {
  var width = 500;
  var height = 500;
  var pixels = [];
  for (var i = 0; i < height; ++i) {
    var row = [];
    for (var j = 0; j < width; ++j) {
      row[j] = 0;
    }
    pixels[i] = row;
  }

  var k = 12;
  var j = 29;
  console.log(pixels[12][29].toString());

  var canvas = document.getElementById('test');
  canvas.width = width;
  canvas.height = height;
  var ctx = canvas.getContext('2d');
  var testImage = ctx.createImageData(width, height);
  for (var y = 0; y < height; ++y) {
    for (var x = 0; x < width; ++x) {
      pixels[y][x] = Math.round(Math.random() * 255);
    }
  }

  for (var y = 0; y < height; ++y) {
    for (var x = 0; x < width; ++x) {
      setRGB(testImage, width, x, y, pixels[y][x], pixels[y][x], pixels[y][x], 255);
    }
  }
  ctx.putImageData(testImage, 0, 0);
}

draw();
<canvas id="test"></canvas>
gman
  • 100,619
  • 31
  • 269
  • 393
  • AHA! :D Another stupid typo with not passing x and y to setRGB() :) . I've been programming for a long time and of course I know that variables need initialization ( most of the time ), but, for some reason, I overlooked the bug :/ . As for the `ctx.putImageData(testImage, 0, 0); canvasImage = testImage; ctx.putImageData(canvasImage, 0, 0)`, they'e just there from cruft I accidentally imported from another one of my Javascript code snippets from which I had copied and pasted some of the above code :) – jdb2 Jun 25 '19 at 18:52
  • If you'd have used `const` instead of `var` you'd have gotten an error. Also if you'd stepped through in the debugger you'd have seen it immediately. – gman Jun 25 '19 at 18:53
  • Thanks gman! :D I was in a rush and not thinking when I wrote the above code and made some absent-minded errors :) "Also, put 'use strict'; at the top of your JavaScript and never use var, use const and let as they will help you find these kinds of issues" Thanks for the suggestions :) I use similar coding practice in Perl, but for some reason I forgot in the case of the above code :) – jdb2 Jun 27 '19 at 17:04
0

Seems the problems were caused by some dumb errors including accidentally not noticing that the width and height variables hadn't been declared yet and also my failure to pass setRGB() its x and y values.

Thanks to all who helped :)

jdb2

jdb2
  • 101
  • 6