Preloading Many Images in Preload

I was trying to preload around 200 1MB images in my local sketch with loadImage() but found p5 to be stuck in preload().

I have replicated the issue here. To note, it will stall initially in the web editor due to fetching, which I anticipated (preload is only running after the first console output). But after everything is fetched, 2-3 images will not resolve their loadImage call, making p5 not call setup at all. It is also different images every time. I tried reducing the number of images, but the issue persists even when the image count is around 100 (sometimes works at ~50).

NOTE: the issue seemed to be resolved in the web editor after clearing my cache, but still wouldn’t work in my locally hosted sketches. Please let me know if you encounter the error when running the web editor sketch.

I’ve added some retry callbacks for failed images which tracks down loadCount & retryCount variables:

// https://Discourse.Processing.org/t/preloading-many-images-in-preload/42372/2
// 2023-Jul-08

'use strict';

const
  IMAGES = 200,
  DIGITS = 4,

  RETRIES = 1,

  FOLDER = 'data/',
  EXT = '.png',

  PATHS = Array.from({ length: IMAGES },
    (_, idx) => FOLDER + p5.prototype.nf(idx + 1, DIGITS) + EXT
  ),

  images = Array(IMAGES).fill(),
  
  Callback = {
    load(path, idx) {
      ++loadCount;
      images[idx] = loadImage(path, Callback.success, Callback.failure);
    },

    success() {
      --loadCount || Callback.audit();
    },

    failure(evt) {
      console.error(evt);
      Callback.success();
    },

    audit() {
      retryCount++ < RETRIES && images.forEach(Callback.retry);
    },

    retry({ height }, idx) {
      if (height <= 1) {
        console.warn('Retry', retryCount, 'for path', PATHS[idx]);
        Callback.load(PATHS[idx], idx);
      }
    },

    badFilter({ height }) {
      return height <= 1;
    }
  };

var loadCount = 0, retryCount = 0;

window.preload = function() {
  print(PATHS);
  PATHS.forEach(Callback.load);
};

window.setup = function() {
  createCanvas(400, 500).mousePressed(redraw);
  noLoop();

  print('Failed image(s):');
  console.warn(images.filter(Callback.badFilter));
};

window.draw = function() {
  image(random(images), 0, 0, width, height);
};
1 Like