Problem loading random images and interactivity

Hello! I’m new to Processing but have experience with other bits and bats of coding, but feel I’m really banging my head against the wall here.

All I want is to draw a canvas that loads a random background image and another random image overlaying that at a set of coordinates, then on the mouse button being pressed it redraws the whole thing. I’ve read and reread various tutorials and posts, rewritten my code a few times and feel a bit flummoxed. I feel like this should be quite straightforward but think I’ve confused myself.

Any guidance would be deeply appreciated.

// LOAD IMAGES INTO ARRAY
PImage[] head = new PImage[10];
PImage[] eyes = new PImage[2];
int rand;

void setup() {
  size(600, 800);
 background(0);
 rand = int(random(0,9));  //CREATES RANDOM NUMBER
 takerandomimage("head_" + nf(rand, 3) + ".jpg");  //APPLIES R NUMBER TO FILENAME
}

// THIS IS THE FUNCTION
void takerandomimage(String fn) {
   head = loadImage(fn); //LOAD RANDOM IMAGE
   image(head,0,0,600,800);//DISPLAY RANDOM HEAD
   image(eyes,250,250,200,200);//DISPLAY RANDOM EYES
}

//IF MOUSE PRESSED RELOAD RANDOM IMAGES ONTO CANVAS
mousePressed(redraw) {
}
}

1 Like

Hey!

First of all, I see you’re creating an array of images with 10 spaces right off the bat and another array with 2 images.
Be aware that this doesn’t actually load any images into the array, which is a collection of variables. running new PImage[10] simply allows the memory allocation of 10 null PImage objects.
headisnull

Second, you did a good job creating your setup! the first two lines are good.
I can see you then generate an int between 0 and 9. Good job on that too. Be aware though that flattening the number using int will mean that you have an extremely low chance of getting a 9. You’ll be generating a number between 0 and 9 but then cutting off the decimal. A good way to fix this might be to change the line to rand=int(random(0,9.9)) so it can include numbers up to 10 (but not including)

I then see that you generate a string with a typical format of something like “head_004.jpg” for example. You don’t explain what files you have and where they’re stored so I can’t help you with that (you may want to consider including something like that in your problem next time). If that’s an example for what the file name looks like but you also might want to verify the path as well. More on that in a moment.

Enter the takerandomimage function…
The first line is off to a bit of a bad start. loadImage() takes in a string but returns a single image. You’re setting the value of head to a single image but since head is an array, you’ll have a type incompatibility. You can’t put an image into a box full of empty spaces, you have to put an image into a box expecting a single image. Changing the first line of the program to simply PImage head; will fix this issue.

Still on this line however, you’re taking the filename earlier and putting it into this function. To ensure your file will open you will want to make sure you are referencing its path properly. An easy way to do this is to save your processing project somewhere, make a folder in the same directory as your main .pde files called ‘data’ and place your images in there. Then, make sure that whenever you’re running loadImage() to enter a string that starts with data/
if you have a file called head_005.png inside of your data folder and you run that line after making the other change above, this line should work.
I recommend reading the first few lines in the description of the loadImage() documentation page if you’d like to learn more.

The next two lines in takeRandomimage should work after making those changes.

mousePressed(redraw) will do nothing since you don’t have a draw function and you haven’t called noLoop. I recommend either
a. making a draw function and putting your takerandomimage and rand= lines in there and running noDraw() and redraw() in setup(), and then changing the final lines of your program to
void mouseClicked(){
redraw();
}

or
b. putting your takerandomimage and rand lines and putting them in a new function and calling them from a mouseclicked function such as

void newFace(){
background(0);
the rand= line
the takerandomimage line
}

void mouseClicked(){
newFace();
}

I see you stringing together a bunch of concepts that can easily be found from guides on the internet but there’s not a lot of comprehension or reading the publicly available documentation. I recommend you try watching a few processing instructional videos on the coding train or checking out some of processing’s really good documentation.

Good luck!

2 Likes

a link to

helps,
so usually a

rand = int(random(10));                 //  creates random number 0 .. 9

with even probability.


thanks for helping, pls not angry, but
also for small code sniplets in posts i recommend the

</>

code formatter ( not the “” quote formatter as it damages code )
and you will see your above post will look so much better ( esp. on the dark theme )

1 Like

Thanks kll! I would have linked to more reference pages in my answer were new users to this forum not limited to 2 links per post. I feel like mouseClicked is another page I would have referenced. Knowing when to use it over mousePressed and mouseReleased is very useful.

2 Likes

Thanks a bunch Jack and kll, managed to get it working now! Very much appreciated, I’ve spent hours going round in circles. (Usually I would learn coding from the ground up but this project has to be handed in shortly - I will go back and go through the tutorials again, walk before you can run and all that.)

The new code is below. I’ll need to create the images but when that’s done I’ll post the finished thing. Thanks again!

// DECLARE YOUR GLOBAL VARIABLES HERE.
PImage head;
PImage eyes;
int rand;

void setup() {
 noLoop();
 redraw();
 size(600, 800);
 background(0);
 rand = int(random(10)); //RAND FUNC
 takerandomimage("head_" + nf(rand, 3) + ".jpg");
 takerandomimage("eyes_" + nf(rand, 3) + ".jpg");//FINDS FILE
}

// THIS IS THE FUNCTION
void takerandomimage(String fn) {
   head = loadImage(fn); //LOAD RANDOM IMAGE
   eyes = loadImage(fn); //LOAD RANDOM IMAGE
}

void draw(){
  background(0);
  rand = int(random(0,9.9));
  takerandomimage("head_" + nf(rand, 3) + ".jpg");
  image(head,0,0,600,800);
  takerandomimage("eyes_" + nf(rand, 3) + ".jpg");
  image(eyes,200,250,200,200);
}

void mouseClicked(){
redraw();
}
2 Likes

Good stuff!

By the way, since you have noLoop() and redraw() once in your setup, it’s inherent that the contents of draw will run once. Therefore you can remove the last three lines of your setup function.

noLoop() tells draw not to continue running and redraw(); tells draw to run once.

Everything else looks so good so far!

as much i like modularisation,
++like your function

takerandomimage (file)

to me it looks like that you load the head_* and eyes_ files
8 times and
show the image head and eyes what both contain the last
"eyes_" + nf(rand, 3) + ".jpg"
picture?
or do i miss some thing?

more easy structure:

// DECLARE YOUR GLOBAL VARIABLES HERE.
PImage head;
PImage eyes;
int rand;

void setup() {
  //  noLoop();
  //  redraw();
  size(600, 800);
  //  background(0);
  //  rand = int(random(10)); //RAND FUNC
  //  takerandomimage("head_" + nf(rand, 3) + ".jpg");
  //  takerandomimage("eyes_" + nf(rand, 3) + ".jpg");//FINDS FILE
  takerandomimage();
}

// THIS IS THE FUNCTION
void takerandomimage() {
  rand = int(random(10));                           //RAND FUNC
  head = loadImage("head_" + nf(rand, 3) + ".jpg"); //LOAD RANDOM IMAGE
// enable for mix       rand = int(random(10));                           //RAND FUNC
  eyes = loadImage("eyes_" + nf(rand, 3) + ".jpg"); //LOAD RANDOM IMAGE
}

void draw() {
  background(0);
  //  rand = int(random(0, 9.9));
  //  takerandomimage("head_" + nf(rand, 3) + ".jpg");
  image(head, 0, 0, 600, 800);
  //  takerandomimage("eyes_" + nf(rand, 3) + ".jpg");
  image(eyes, 200, 250, 200, 200);
}

void mouseClicked() {
//  redraw();
  takerandomimage();
}

2 Likes

I think kll has a point, you have a mismatch between your function name and what it does.

the function called takerandomimage takes in an already randomized string and then loads in the same image into both the head and the eyes variable.

this can easily be construed as not the right behavior for a function of that name.

i recommend either
a. have the function do as its told (give it a string for the prefix [either head or eyes]) and have it do the rest based on which one you put in.
b. make two functions that do each separate job that takerandomimage is currently doing, such as one called assignHead and assignEyes, each simply taking in the full path for a referable file and loading the image for it into its own variable
or c. have the function do the full job and replace all of the logic in your draw function with one function call which would result in draw calling background(0); and takerandomimage(); and having takerandomimage generate the filenames randomly (with a random number for the head and the eyes separately, which you’re also not currently doing), load in their corresponding images and assign them to their respective variables, finally adding image() lines for both head and eyes.

a final program could look something like this:

// DECLARE YOUR GLOBAL VARIABLES HERE.
PImage head;
PImage eyes;
int rand;

void setup() {
  size(600, 800);
  noLoop();
  redraw();
}

// THIS IS THE FUNCTION
void takerandomimage() {
  rand = int(random(10));
  head = loadImage("head_" + nf(rand, 3) + ".jpg"); //LOAD RANDOM IMAGE
  rand = int(random(10));
  eyes = loadImage("eyes_" + nf(rand, 3) + ".jpg"); //LOAD RANDOM IMAGE
}

void draw(){
  background(0);
  takerandomimage();
  image(head,0,0,600,800);
  image(eyes,200,250,200,200);
}

void mouseClicked(){
redraw();
}```
1 Like