2

This is a specific problem so I'm going to do my best explaining it.

I have a single canvas on my page. The user uploads a batch of files taken from the same camera angle. The canvas displays one of the images and the user draws over the image in a way that depicts an area of interest. The program then goes over this area of interest and extracts relevant RGB data from the pixels inside the area.

Now, what I'm having an issue with is then switching the canvas over to the next image to process that one as well. I have the area of interest still specified as an array of indexes inside the area. But, when trying to obtain the RGB data from the rest of the images, it only gives me the info about the first image.

Below are some relevant code snippets as well as their function.

This function loads up the next image in the fileUpload to the canvas

function readNextImage(i) {
  if (fileUpload.files && fileUpload.files[i]) {
    var FR = new FileReader();
    FR.onload = function(e) {
      fabric.Image.fromURL(e.target.result, function(img) {
        img.set({
          left: 0,
          top: 0,
          evented: false
        });
        img.scaleToWidth(canvas.width);
        img.setCoords();
        canvas.add(img);
      })
    };
    FR.readAsDataURL(fileUpload.files[i]);
  }
}

This snippet loads up an array with the image data.

var imgData = context.getImageData(0,0,canvas.width,canvas.height);
var data = imgData.data;

So currently, I'm able to go through 'data' the first time and obtain the relevant RGB info I need. After I do that, I call the readNextImage() function, it loads it into the canvas, then I make another call to

var imgData = context.getImageData(0,0,canvas.width,canvas.height);
var data = imgData.data;

to hopefully load the arrays with the new values. This is where it seems to fail as the values are the same as the previous iteration.

Is there a chance the program isn't given enough time between loading the canvas with the new image and trying to get the new data values? Is there something else that's going on with the canvas that I'm unaware of?

Here's where I'm actually calling the readNextImage() function

for (var image_num=0; image_num<fileUpload.files.length; image_num+=1){
    imgData = context.getImageData(0,0,canvas.width,canvas.height);
    data = imgData.data;

    /*Lines of code that parses through the data object specified above*/

    readNextImage(image_num);
}

I'm hoping the problem is clear, let me know if anything is confusing.

1 Answers1

2

Edit 2:

links to articles about promises: promises 1 promises 2 promises 3

Edit: Instead of using a global canvas, use a local one created for each image instance:

    for (var image_num=0; image_num<fileUpload.files.length; image_num+=1){
    var canvas = document.createElement("canvas");
    var context = canvas.getContext("2d");
    readNextImage(image_num,canvas);
    imgData = context.getImageData(0,0,canvas.width,canvas.height);
    data = imgData.data;

    /*Lines of code that parses through the data object specified above*/
    }


function readNextImage(i,canvas) {
  if (fileUpload.files && fileUpload.files[i]) {
    var FR = new FileReader();
    FR.onload = function(e) {
      fabric.Image.fromURL(e.target.result, function(img) {
        img.set({
          left: 0,
          top: 0,
          evented: false
        });
        img.scaleToWidth(canvas.width);
        img.setCoords();
        canvas.add(img);
      })
    };
    FR.readAsDataURL(fileUpload.files[i]);
  }
}

The problem could be here (the previous image is still attached to the canvas):

canvas.add(img);

try removing the previous child(ren) before adding another one by replacing that line with:

while (canvas.firstChild) {
  canvas.removeChild(canvas.firstChild);
}
canvas.add(img);
canvas.getContext("2d").drawImage(img, 0, 0);
jshamble
  • 391
  • 2
  • 14
  • Just gave that a shot and it didn't seem to work. Doing `var imgData = context.getImageData(0,0,canvas.width,canvas.height); var data = imgData.data;` should just grab the canvas contents and shouldn't care what layers exist or not. It was worth a shot, though. Thanks. – Jake McClenny Jul 23 '18 at 05:21
  • Have you debugged and checked to make sure the filenames of the image files are different? – jshamble Jul 23 '18 at 05:34
  • When I run the function I can see the canvas cycling quickly through the various images I've uploaded, so I'm fairly confident the individual images are uploading correctly. – Jake McClenny Jul 23 '18 at 05:38
  • Can you edit and show more of the source code? Specifically the part where you call readNextImage() – jshamble Jul 23 '18 at 05:42
  • I just edited the original posting with the part where I call the function – Jake McClenny Jul 23 '18 at 05:48
  • try drawing the image to the canvas' context using canvas.getContext("2d").drawImage(img, 0, 0); see the edit I made above. – jshamble Jul 23 '18 at 05:59
  • gave that a shot as well and no luck – Jake McClenny Jul 23 '18 at 06:24
  • The only thing else I can think of is creating a new canvas element each time readNextImage is called; however, this may not be what you wanted, see my edit above for the modified code. – jshamble Jul 23 '18 at 20:30
  • Thanks for your help. I'll give this a shot when I have some time later! – Jake McClenny Jul 23 '18 at 23:51
  • I found something interesting that might change the problem that's happening. I added a short delay after the call to `readNextImage` in my original code. What I see happening now is that it iterates each time through the loop, but it only updates the image in the canvas to the next image after the loop is entirely finished running. So, it's only ever getting the data from the first image because the canvas is never actually updating to the next uploaded image. – Jake McClenny Jul 24 '18 at 23:44
  • javascript is asynchronous, so I think a possible fix is that you'll need is sequential logic for loading the images (you want the data of the original image fully read before moving onto the next image). You may want to look into sequential uses of promises and resolutions, I've edited my post above to include links for some ways you might want to try going about it. Run a few more tests and see if you can get something to work. – jshamble Jul 25 '18 at 03:06