Error in displaying a image

Im facing an error: Console

TypeError: this._renderer is undefined
🌸 p5.js dice: 
[p5.js, line 95593] Cannot read property of undefined. Check the line number in error and make sure the variable which is being operated is not undefined.

 + More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong 
┌[https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.1/p5.js:95593:70] 
	 Error at line 95593 in [329]</_main.default.prototype.image()
â””[blob:https://preview.p5js.org/767b5e79-144f-42c6-ac01-7784a1a1dfdf:31:8] 
	 Called from line 31 in handleImage()
â””[https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.1/p5.js:94646:34] 
	 Called from line 94646 in [329]</_main.default.prototype.loadImage/</img.onload()

Dont know why…im following : loadImage

let myimg;
let gameBoard  = [ [0,0,1,1],
                   [1,0,1,0],
                   [0,0,0,1],
                   [1,1,1,1]];
let gameBoard2  = [1,0,1,1];

// Load an image and create a p5.Image object.
function preload() {
 
  myimg = loadImage('roca.png', handleImage,handleError);
}

function setup() {
  createCanvas(400, 400);
  background(150);
  let arrayRocas = gameBoard.filter( (filaActual) => {
    let result = filaActual.filter( (columnaActual) => columnaActual == 1 );
    console.log(result);
  } );
  console.log(arrayRocas);



  describe('A red brick wall.');
}

// Display the image
function handleImage(myimg) {
  
  image(myimg, 0, 0);

  describe('Image of the underside of a white umbrella and a gridded ceiling.');
}

// Log the error.
function handleError(event) {
  console.error('Oops!', event);
}

The error is in image in the handleImage when calling image

Any help ?

Try deleting the preload function and loading the image from setup():
myimg = loadImage('roca.png', handleImage,handleError);

That call to image() is gonna happen before setup() had even started!
Move that into draw() callback instead!

1 Like

But you go to the link i made and there are two or three examples … with handleimage and handle error the same as i did…@svan and @GoToLoop

https://p5js.org/reference/p5/loadImage/

The only example using preload() doesn’t invoke image() in its callback.

2 Likes

Your code doesn’t look like this:

function setup() {
  // Call handleImage() once the image loads or
  // call handleError() if an error occurs.
  loadImage('/assets/laDefense.jpg', handleImage, handleError);
}

// Display the image.
function handleImage(img) {
  image(img, 0, 0);

  describe('Image of the underside of a white umbrella and a gridded ceiling.');
}

// Log the error.
function handleError(event) {
  console.error('Oops!', event);
}

There is nothing wrong with this code and loading an image in preload rather than setup is preferred.

As @GoToLoop pointed out the preload is executed before setup so the two methods for success and failure will be executed before setup so you cannot use any p5js methods inside them. Using console is obviously OK

1 Like

The tutorial i pointed out seems that work ok…how can i handle then the error and success of the loading of a image…

https://p5js.org/reference/p5/loadImage/

It works in that example because loadImage is execute in setup so the canvas exists to be drawn on.

Notice the example that uses preload does not have a success function so no problems.

1 Like
  • You have myimg as a global variable.
  • Then you initialize it in preload().
  • When execution reaches setup(), the image loading either succeeded or failed.
  • So you can use myimg within setup() or draw() and check its width or height properties.
  • If the image loading had succeeded, expect both width & height to be greater than 1.
  • Well, at least that was the old behavior. Dunno if they had changed that though.
var myimg;

function preload() {
  myimg = loadImage('wrong-name.png', console.info, console.warn);
}

function setup() {
  createCanvas(400, 400);

  # Logs "Image's dimensions: 1 x 1":
  print("Image's dimensions:", myimg.width, "x", myimg.height);
}
2 Likes

So perhaps is a bug…because its recommended to load all images and audios and so “heavy” elements in preload function…

This works, loading image in setup:

let img;
function preload() {

  //img= loadImage('pac.png', handleImage, handleError);
}
function setup() {
  // Call handleImage() once the image loads or
  // call handleError() if an error occurs.
  //
  img= loadImage('pac.png', handleImage, handleError);
}

function draw(){
  background(150);
  image(img, 0, 0);

}

// Display the image.
function handleImage(img) {
  image(img, 0, 0);

  describe('Image of the underside of a white umbrella and a gridded ceiling.');
}

// Log the error.
function handleError(event) {
  console.error('Oops!', event);
}

But the “same” code loading image in preload, as should be …fails with the error in first post:


let img;
function preload() {

  img= loadImage('pac.png', handleImage, handleError);
}
function setup() {
  // Call handleImage() once the image loads or
  // call handleError() if an error occurs.
  //
 // img= loadImage('pac.png', handleImage, handleError);
}

function draw(){
  background(150);
  image(img, 0, 0);

}

// Display the image.
function handleImage(img) {
  image(img, 0, 0);

  describe('Image of the underside of a white umbrella and a gridded ceiling.');
}

// Log the error.
function handleError(event) {
  console.error('Oops!', event);
}

I think most images at loading should have these callbacks just in case a image cant be loaded for whatever reason… as some of you know im developing a pacman game, so if an image of pacman or walls or dots doesnt load…the game or program has nosense to continue…So my idea is loading all the images in preload function and test if there is any error.

Again, you’re still keeping the same bug I’ve pointed out in my 1st reply.
That image(img, 0, 0); will run before setup() callback even starts!
Meaning, the sketch’s canvas hadn’t been created at the moment image(img, 0, 0); is invoked!

1 Like

Yes i understand your point of view, but this some how shoudl be fixed…because if you use preload function to loading media, then you want to handle possible errors…if you put all the loadimage in setup then the performance will go down and time to load game would increase…some dev in my opinion could give this a solution…

Another solution im thinking is in handleImage put an console.log info, and in handleError some kind of alert and exiting the program…and then put image( myimg, 0,0) in the draw function…so id load the media in preload, and perhaps dont get the error

  • Why would you need to access the canvas before setup()?
  • In order to handle any loading errors, we don’t actually need to draw anything to the canvas.
  • When your code reaches setup(), you can check if any errors happened by checking width or height from an image object.
  • Then you may decide to display some message on the now existing canvas.
  • Both success & fail handlers happen before setup() when we load inside preload().
1 Like

You’re on the right track!

This tutorial on program flow on the archived version of the p5.js website has a good explanation for what you are trying to do. See in particular the “Asynchronicity in p5.js”, “Introduction to Preload”, and “Loading with a Callback” sections.

The last part in particular is relevant to your approach. You can use the success callback to draw the image to the canvas but then you have to call loadImage() in setup(). This is because preload() stops the flow of the program, therefore the canvas does not exist yet at that point.

Here is what the tutorial in question says about callbacks:

An alternative to preload() is to use a callback function . A callback function is a function that is passed as an argument to a second function, and that runs after the second function has completed. The following example illustrates this technique.

And the example provided:

function setup(){
  createCanvas(100, 100);
  loadImage("/assets/learn/program-flow/images/clouds.jpg", drawImage);
  noLoop();
}

function draw(){
  background(200);
}

function drawImage(img){
  image(img, 0, 0);
}
1 Like

This is definitely, definitely not a bug!

The problem is that you are attempting to draw an image to a canvas object that hasn’t been created yet. In your code you had

let img;
function preload() {

  //img= loadImage('pac.png', handleImage, handleError);
}
function setup() {
  // Call handleImage() once the image loads or
  // call handleError() if an error occurs.
  //
  img= loadImage('pac.png', handleImage, handleError);
}

function draw(){
  background(150);
  image(img, 0, 0);

}

// Display the image.
function handleImage(img) {
  image(img, 0, 0);

  describe('Image of the underside of a white umbrella and a gridded ceiling.');
}

// Log the error.
function handleError(event) {
  console.error('Oops!', event);
}

but what is the point of displaying the image in handleImage when in a few milliseconds it is going to be displayed in draw()?

The advantage of preload is that the resources are fully loaded before setup is executed so you can safely use them once the sketch is initialized and the canvas is created.

4 Likes

The argument in the function handleImage is the same name as the variable myImg.

Anyways, the handleError thing is actually useless.
If your sketch encounters an error, it won’t run anyways.

Try this instead:

function handleImage(what) {
  image(what, 0, 0);
  describe('Image of the underside of a white umbrella and a gridded ceiling.');
}

Im a teacher in vocational eduction, and we are learning Front Web Development, trying to implement some kind of Pacman game. So if for any reason the pacman image or rock image cant be loaded…you must give a “clean and controlled exit” to user. Also learning good programming practices.

I also have tried;

  //img= loadImage('pac.png', handleImage, handleError);

in the preload, and handle image:

// inform the image has loaded without problems.
function handleImage(img) {
  console.log("Image loaded without any issue");
  describe('Image of the underside of a white umbrella and a gridded ceiling.');
}

So perhpas at preload should be some kind of loadimage return value or anything to let test if a image or audio have loaded right, and give option to exit program in a clean way…

Thanks

My previous example inspects the loaded image’s dimensions inside setup() already:

So, it’s just a matter of displaying an error message and end the sketch if image’s dimension are just 1, indicating failure:

const FILENAME = 'wrong-name.png';
var myimg;

function preload() {
  myimg = loadImage(FILENAME, console.info, console.warn);
}

function setup() {
  createCanvas(400, 400);

  # Logs "Image's dimensions: 1 x 1":
  print("Image's dimensions:", myimg.width, "x", myimg.height);

  if (myimg.width <= 1) {
    console.error(FILENAME, 'failed to load!');
    remove(); // destroy the sketch!
    draw = null; // make sure draw() callback won't be run
  }
}

function draw() {
  image(myimg, 0, 0);
}
2 Likes

Consider executing the following lines

let img = loadImage('pac.png');
let n = 999;
// at this point img is undefined and n has the value 999

The first line is executed asynchronously so the second line is executed before loadImage has completed. So the return value from loadImage cannot be used because we don’t know when it will be set. This is why we have callback function to be executed if it succeeds or fails,=.

This sketch code demonstrates one way to gracefully handle loading errors. It attempts to load three images but only the first one exists (at least on my system)

let nbrLoaded = 0, expected;
let errors = [];
let img0, img1, img2;

function preload() {
    expected = 3;
    img0 = loadImage('bug0.png', handleImage, handleError);  // exists
    img1 = loadImage('bug1.png', handleImage, handleError);  // non-existant
    img2 = loadImage('bug2.png', handleImage, handleError);  // non-existant
}

function setup() {
    createCanvas(640, 160);
    if (nbrLoaded != expected) {
        console.log(`Only ${nbrLoaded} out of ${expected} resources loaded`);
        draw = drawError; // change the draw method
    }
}

draw = function () {
    background(230);
    image(img0, 100, 100);
}

drawError = function () {
    background(255, 192, 192);
    fill(0); textSize(16).textAlign(LEFT, CENTER);
    let y = 30;
    errors.forEach(e => { text(e, 10, y); y += 24; });
}

function handleImage(img) {
    nbrLoaded++;
}

function handleError(event) {
    errors.push(`### Unable to find ${event.target.src} ###`);
}

The output lists the loading errors in the webpage.

2 Likes