Analysing image file make my browser stop working


#1

Hi,

I’m making a sketch that load an image, rotate it a bit and display it. The program works well on my code editor, but it is not working on my browser.

I first though there were some infinite loop, but after few research I noticed the problem is caused by my med() function, which is incredibly expensive in terms of memory. The role of the function is to return the average brightness value of a square in a specific area of an image.

How can I fix this ? Do you have any idea ? Thanks for your help !

You can try it on the p5 web editor:
http://alpha.editor.p5js.org/colin.thil@gmail.com/sketches/HkVLsbaeQ

function setup() {
  createCanvas(windowWidth, windowHeight);
  atelier_setup();
}

function draw() {
  background(0);
  image(scan, 0, 0, width, height);
}

var scan;

function preload() {
  scan = loadImage('assets/scan.jpg');
}

function atelier_setup() {
  scan = rotateScan(scan);
}

function rotateScan(img) {
  var v1 = 0;
  var v2 = 0;
  var w = img.width / 4;
  var h = img.height / 8;
  for (var i = 0; i < h; i++) {
    if (med(img, w, i, 1, 1) < 220) {
      v1 = i;
      break;
    }
  }
  for (var i = 0; i < h; i++) {
    if (med(img, img.width - w, i, 1, 1) < 220) {
      v2 = i;
      break;
    }
  }
  var p = createGraphics(img.width, img.height);
  p.translate(img.width / 2, img.height / 2);
  p.rotate(-(abs(v1 - v2) / (width / 2) * PI / 32));
  p.background(255);
  p.image(img, -img.width / 2, -img.height / 2);
  img = p;
  return img;
}

function med(img, cx, cy, w, h) {
  var t = 0;
  for (var x = 0; x < w; x++) {
    for (var y = 0; y < h; y++) {
      var c = img.get(int(cx + x - w / 2), int(cy + y - h / 2));
      t += (red(c) + green(c) + blue(c)) / 3;
    }
  }
  return t / (w * h);
}

#2

Find out that the p5 get() function can be very heavy for some browser, enough for make them crash when called in a loop. I Had to use them less, but it is still making my program very slow, if anybody have a solution I would be very grateful.


#3

Solved. If anyone get the same issue here is the fix.
The solution were to use pixels instead of get()

function setup() {
  createCanvas(windowWidth, windowHeight);
  atelier_setup();
}

function draw() {
  background(0);
  image(scan, 0, 0, width, height);
}

var scan;

function preload() {
  scan = loadImage('assets/scanr.jpg');
}

function atelier_setup() {
  scan = rotateScan(scan);
}

function rotateScan(img) {
  var v1 = 0.0;
  var v2 = 0.0;
  var w = float(img.width) / 4;
  var h = float(img.height) / 10;
  img.loadPixels();
  for (var i = 0; i < h; i++) {
    if (med(img, w, i) < 80) break;
    v1++;
  }
  for (var i = 0; i < h; i++) {
    if (med(img, img.width-w, i) < 80) break;
    v2++
  }
  var p = createGraphics(img.width, img.height);
  p.translate(img.width / 2, img.height / 2);
  p.rotate(-atan((abs(v1-v2)/(img.width/2))));
  p.background(255);
  p.image(img, -img.width / 2, -img.height / 2);
  img = p;
  return img;
}

function med(img, x, y) {
  var t = 0;
  var off = (y * img.width + x)*4*pixelDensity(); 
  return (img.pixels[off]+img.pixels[off+1]+img.pixels[off+2])/3;
}

#4

@colin thanks for sharing your solution.

get() being slower than pixels[] is described in the documentation for p5.js like this:

Getting the color of a single pixel with get(x, y) is easy, but not as fast as grabbing the data directly from pixels[]. – https://p5js.org/reference/#/p5/get

…and that this is also true for Processing (Java):

https://processing.org/reference/get_.html