Reading pixels from an image

Hi.
I’m having a problem with what I thought would be a a very simple piece of code.
There’s not much point posting any of my attempts as I’m confused enough as is.

Ultimately I have something more complex in mind, but what I would like is a simple example of loading an image into a variable (e.g. img = loadImage(‘data/imagefile.jpg’); ) and then reading each pixel one at a time and plotting them onto the screen.

Now I know I can do this in one step with image(img,0,0), but I want to do some processing of the pixel data eventually. For the moment, I just want exactly what the image function does, but one pixel at a time.

The other thing I tried was actually putting the image on the screen with image(img,0,0) and then trying to read pixels from there and copy pixel by pixel to another part of the canvas (which I had made large enough to do so). Again, I could not get this to work.

This would be an easy exercise in other languages I have used but I am at a total loss as to why I can’t do so with p5.js. I’ve no doubt it can be done but obviously I’m doing something wrong.

If someone could provide an example of both of these approaches, I would be greatly appreciative.

Kind regards,

Richard

Hello, @Kiliad, and welcome to the Processing Forum!

Let’s begin by loading an image and displaying each pixel.

Here’s an image:

polar_bear
Photo by Sandy Richard
Bronx Zoo
June 15, 2013
Link to original: Tundra, the polar bear.

Save it as polar_bear.jpg, in the same folder or directory as your code.

Here’s the code:

let img;

function preload() {
  img = loadImage("polar_bear.jpg");
}

function setup() {
  createCanvas(253, 320);
}

function draw() {
  w = img.width;
  h = img.height;
  for (let x = 0; x < w; x+=1) {
    for (let y = 0; y < h; y+=1) {
      s = img.get(x, y);
      stroke(s);
      point(x, y);
    }
  }
}

See p5.js Reference: get().

EDIT (August 6, 2021):

Now, let’s instead display the image first, copy pixels from the canvas, and display them elsewhere on the canvas:

let img;

function preload() {
  img = loadImage("polar_bear.jpg");
}

function setup() {
  createCanvas(653, 320);
}

function draw() {
  image(img, 0, 0);
  w = img.width;
  h = img.height;
  for (let x = 0; x < w; x+=1) {
    for (let y = 0; y < h; y+=1) {
      s = get(x, y);
      stroke(s);
      point(x + 300, y);
    }
  }
}

Also see p5.js Reference: loadPixels(), including the example. Once you load the pixels, you can manipulate them.

Thanks @javagar.
Well something is clearly not right.
The first piece of code is essentially the same as I have been trying but it doesn’t work.
All I get is a blank screen.
Perhaps its something to do with the app I’m using. Its the version 3.5.4 Processing app running in p5.js mode.

So, if you copy the first example exactly as it is, and place the image in the same folder or directory as the JavaScript code, do you get a blank screen? If so, let’s try the basic technique to see if it works on your computer. Copy this exactly as is, and let us know what happens:

let img;

function preload() {
  img = loadImage("polar_bear.jpg");
}

function setup() {
  createCanvas(253, 320);
}

function draw() {
  image(img, 0, 0);
}

Yes, that works fine. I have been able to load an display images without any issue.
It’s trying to read pixel data and then put it somewhere else that has been the problem.

Could we have an example of your code that didn’t work, exactly as you have it, so we can try it on our systems?

Ok, here is one attempt.

let img;
let x;
let y;

function setup() {
createCanvas(720, 400);
img = loadImage(‘data/moonwalk.jpg’);

}

function processit() {

for (let x = 0; x < 720; x++) {
for(let y = 0;y < 400; y++) {
col=img.get(x,y);
stroke(col);
point(x,y);

  }

}
}

function draw() {

}

You forgot to call the processit function.

Try this:

function draw() {
  processit();
}

Woops!
Yes, I have had the processit() function in draw() but had removed it to try something else.
It doesn’t work when put back in… at least not properly.
I have been experimenting a bit all this time and I have noticed the browser (Firefox) is struggling a bit.
I ran the code with procvessit() in draw() and I still don’t get the image. Usually the screen is blank but occasionally the canvas is turned black. So it seems the point(x,y) is being executed but isn’t getting the right information.

OK, let’s try another piece of code with the polar_bear.jpg file:

let img;

function preload() {
  img = loadImage("polar_bear.jpg");
}

function setup() {
  createCanvas(653, 320);
  noLoop();
}

function draw() {
  img.loadPixels();
  for (let i = 0; i < img.pixels.length; i += 4) {
    img.pixels[i + 1] = 0;
    img.pixels[i + 2] = 0;
  }
  img.updatePixels();
  image(img, 0, 0);
}

If you run it exactly as is, you should see the image with only its red component. Please let us know what happens.

It is best to format code when you post it. See Guidelines—Asking Questions. It includes information on formatting code.

Ok, now that worked as expected… the picture with just the red component.

1 Like

It’s not clear to me why the other examples did not work, since they executed correctly on my own system. Perhaps other members of the Processing Community can respond here with suggestions.

In the meantime, the most recent example demonstrates that you can load and manipulate individual pixels. With that example as a starting point, feel free to experiment, have fun, post formatted code, and ask us questions.

Yes, a bit of a head scratcher.
I will play around with it and report back.
Thank you for your help. Much appreciated.

1 Like

Maybe your browser is sluggish, and we need to prevent the draw() function from executing repeatedly.

Let’s try the following …

Begin with the code that you posted here.

Add this to the setup() function:

  noLoop();

Be sure to include this in the draw() function:

  processit();

Also move this to a preload() function:

img = loadImage('data/moonwalk.jpg');

What is the result?

EDITED on August 6, 2021 to correct a typographical error.

Hello,

I tried your code in the p5.js editor with processit() in draw() with some modifications so it loaded only once and this worked:

let img;
let x;
let y;

function setup() {
  createCanvas(720, 400);
  img = loadImage("data/Schmitt_moonwalk.jpg");
  //noLoop();
}

function processit() {
  for (let x = 0; x < 720; x++) {
    for (let y = 0; y < 400; y++) {
      col = img.get(x, y);
      stroke(col);
      point(x, y);
    }
  }
}

function draw() {
  print(frameCount);
  if (frameCount == 1) processit();
}

I prefer the online editor because it gives me Console data and I can use print().

I was only examining your code as is.

It also worked in Processing p5.js mode using the latest Google Chrome browser.

Have fun!

:)

1 Like

@javagar
Your suggestion didn’t work. Just gave the usual blank white screen.

@glv
Unfortunately the online editor gave the same result.
Also tried it in an alternative browser (MS Edge) and it didn’t work in that either.

Thanks for your input however.

It did not work in my other browsers with Processing p5.js Java mode.

Give Google Chrome a try and report back.

:)

@glv
OK… using Google Chrome did work in that it produced the correct image, but then the browser froze up and wouldn’t respond.
This is starting to look more like an issue with my computer system… perhaps the video card?
Anyone have any thoughts on that possibility?

Well just out of curiosity I disabled the AdGuard AdBlocker I had installed in Firefox and suddenly it works.
Good grief! The amount of hair I’ve lost… I could knit myself a wig.
I will test this thoroughly and report further.

Regards,

2 Likes