javascriptp5.js

p5js Image width always returning 1


I have a very basic p5js script where I need to resize an image taken from the user via an input. I need to resize it by a percentage, so I need to know the original dimentions. For some reason, both the width and height properties of the image are 1.

The image is a valid image and I can display it properly. I can even resize it, and after that the width and height properties are ok.

Can you help me identify what's wrong? It looks like a p5js bug to me. Maybe it does not load the properties when the image is loaded via base64, but maybe I am missing something.

Also I noticed that the resize and the filters are not applied unless I call them inside the draw function, which does not make sense to me, as this methods mutate the original image so after the next draw iteration they should take effect, however in the example I put them in the handle image function so that you can see the console log just once

I put the snipped below, my image is nothing special so I thing the error should happen with any png image

Any help is appreciated

let inputElement;
let userImage;

function setup() {
  createCanvas(500, 500)
  inputElement = createFileInput(handleFile);
  inputElement.position(0, 0);
}

function draw() {
  background(255);

  if (!userImage) {
    return;
  }

  image(userImage, 0, 0, 500, 500);
}


function handleFile(file) {

  if (file.type === 'image') {
    userImage = loadImage(file.data);
    console.log(userImage.width); // outputs 1 (error)
    userImage.resize(100, 0);
    userImage.filter(GRAY);
    console.log(userImage.width); // outputs 100 as expected
  } else {
    userImage = null;
  }
}
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.0/lib/p5.min.js"></script>


Solution

  • loadImage is asynchronous, so you can't rely on the image width being available until the callback fires, which indicates the image data is actually loaded into memory.

    Setting the width by hand appears to work because it doesn't rely on the image having loaded, but your pre-load resize will be overwritten once the image's actual size is loaded in later on.

    let inputElement;
    
    function setup() {
      createCanvas(500, 500)
      inputElement = createFileInput(handleFile);
      inputElement.position(0, 0);
    }
    
    function handleFile(file) {
      if (file.type !== "image") {
        userImage = null;
        return;
      }
    
      loadImage(file.data, userImage => {
        console.log(userImage.width);
        userImage.resize(100, 0);
        userImage.filter(GRAY);
        image(userImage, 0, 0, 500, 500);
      });
    }
    <script src="https://cdn.jsdelivr.net/npm/p5@1.11.0"></script>