Loading images from a local path

Hi, I use this code in processing to load images of a local path

loadimages.pde :

    PImage [] loadImages(String stub, String extension, int numImages)
    {
      PImage [] animals = new PImage[0];
      for(int i =0; i < numImages; i++)
      {
        PImage img = loadImage(stub+i+extension);
        if(img != null)
        {
          animals = (PImage [])append(animals,img);
        }
        else
        {
          break;
        }
      }
      return animals;
    }

And then calling this function above with this code:

animals = loadImages("animals/animal", ".jpg", numberLoadAnimals);

How can I traslate it to p5.js? Any help will be apreciate

SALUD...

Answers

  • I would try to help you out if the code you provided above was correct! [-(

  • edited November 2014

    OK you were right. I hope this time it will be more clear

    pictures.pde

     PImage [] animals;
     int numberLoadAnimals = 9;
     void setup() {
        size(1024, 680);
        animals = loadImages("animals/animal", ".jpg", numberLoadAnimals);
     }
    
    void draw() {
      //visualizar el marcador ( el fondo del marcador)
      fill(204);
      noStroke();
      image(animals[number], onSeeX, marginY, animals[0].width, animals[0].height);
    }
    

    loadImages.pde

        PImage [] loadImages(String stub, String extension, int numImages)
        {
          PImage [] animals = new PImage[0];
          for(int i =0; i < numImages; i++)
          {
            PImage img = loadImage(stub+i+extension);
            if(img != null)
            {
              animals = (PImage [])append(animals,img);
            }
            else
            {
              break;
            }
          }
          return animals;
        }
    
  • Leave a blank line either side of the code block. Blank lines are needed between paragraphs. I have done this for you in your first post above.

  • edited November 2014

    A little better, but still very incomplete Java Mode code! :-&
    In JavaScript, loading heavy resources like images, sounds and videos don't happen at once.
    What can be done is request the loading and specify a callback function which will be invoked when it's done.

    In your case, you expect animals[] to be length = numberLoadAnimals when it's successful.
    For each image loaded, it is push()ed into animals[]. Here's my attempt: :(|)

    // forum.processing.org/two/discussion/8272/
    // loading-images-from-a-local-path
    
    const animals = [], QTY = 9;
    const PATH = 'animals/animal', EXT = '.jpg';
    
    function setup() {
      createCanvas(1024, 680);
      background(0);
      requestImages(PATH, EXT, QTY);
    }
    
    function draw() {
      if (animals.length < QTY)  return;
    }
    
    function requestImages(path, ext, qty) {
      for (var i = 0; i != qty; 
        loadImage(path + i++ + ext, getImage));
    }
    
    function getImage(img) {
      animals.push(img);
    }
    
  • edited November 2014

    Hi GoToLoop

    some question: getImage is the callback function, with quotes?

    this my own attempt that.... doesnt works :((

    var numOfAnimals = 9;
    var animals = [];
    var stub, extension, num;
    var currentAnimal = 0;
    function setup() {
      createCanvas(1024, 680);
      animals = Animal("animals/animal", ".jpg", numOfAnimals);
    }
    function draw() {
      background(0);
      image(animals[currentAnimal], 20, 100);
    }
    function Animal(stub, extension, num) {
      for (var i = 0; i < numOfAnimals; i++) 
      {
        var animalName = loadImage(stub + i + extension, 'getImage');
      }
    }
    function getImage(img) {
      animals.push(img);
    }
    

    And... how do you declare a new array in p5.js like this ?:

    PImage [] animals = new PImage[0];

    Thanks in advance SALUD...

  • I guess you didn't get the part that resources doesn't load immediately in JS:
    http://p5js.org/reference/#/p5/loadImage

    How do you declare a new array in p5.js like this ?

    P5.JS doesn't provide any arrays, but the JS language itself! :-@
    If we dunno its length, just an [] is enough to create an array.
    But it's more efficient doing this way: Array(QUANTITY). *-:)

  • edited November 2014

    My own work v2. What do you think about it?

    var numOfAnimals = 9;
    var animals = [];
    var stub, extension, num;
    var currentAnimal = 3; //example
    
    function setup() {
      createCanvas(1024, 680);
      animals = Animal("animals/animal", ".jpg", numOfAnimals);
    
    }
    function draw() {
      background(128);
      image(animals[currentAnimal], 20, 100);
    }
    function Animal(stub, extension, num) {
      for (var i = 0; i < numOfAnimals; i++) 
      {
        var animalName = loadImage(stub + i + extension);
        animals = append(animals,animalName);
      }
      return animals;
    }
    
  • What do you think about it?

    Well, we can't run it b/c we don't have your image files! Anyhow, you tell us! ;;)
    Is it working or not? W/o a callback for loadImage(), you take the risk of getting null in animalName! #-o

  • edited November 2014

    Well... is it working but... not perfectly... :((

    I have extend the sketch to include 9 photos and one of the problems is that if i use this code to load images, the first always an the second sametime does not appear, the same case with processing.js, perhaps is the lack of callback function :

    var animalName = loadImage(stub + i + extension);
    animals = append(animals,animalName);
    

    And if I use some os your code, the photos appear but if i refresh the browser the photos change the position in particular the third line of photos, in this case i think i have badly use your code. Also i get this error: 2225: Uncaught TypeError: Cannot read property 'canvas' of undefined

    Here you can see a live example scual.es Like always any help will be appreciate

    function Animal(stub, extension, num) {
      for (var i = 0; i < numberOfAnimals; i++) {
        loadImage(stub + i + extension, getImage);
        print(stub + i + extension);
      }
      return animals;
    }
    function getImage(img) {
      animals.push(img);
    }
    

    The whole code:

    /////////////////////
    //cpb 24nov2014
    /////////////////////
    
    /////////////////////////////////////////////////
    var h = 0; //future global variable 
    var score = 0;
    ////////////////////////
    var numberOfAnimals = 9; // number of photos to show
    var numberIndice = 8; // 0,1,2....
    var numberLoadAnimals = 9; // number of photos to choose
    var animals = [];
    var stub;
    var extension;
    var num = 0;
    /////////////////////////////////////////////////
    var margin = (1024 / 100) * 2;
    var visualizePhoto = true; // switch show photos
    
    var currentPhoto = 0; // index arrays de photos
    var onSeeX = margin;
    var onSeeY = margin;
    var widthX = 300; //width photo de cada foto
    var heightY = 169; //height photo
    var marginY = 100;
    //fin_fotos
    /////////////////////////////////////////////////
    function setup() {
      createCanvas(1024, 680);
      background(255);
      animals = Animal("animals/animal", ".jpg", numberOfAnimals);
    
    }
    
    function draw() {
    
      //display photo
      displayPhoto();
    
      //display score
      fill(0);
      textSize(28);
      text("SCORE: " + score, margin, margin * 2);
    
    }
    
    function Animal(stub, extension, num) {
      for (var i = 0; i < numberOfAnimals; i++) {
        loadImage(stub + i + extension, getImage);
        print(stub + i + extension);
        //var animalName = loadImage(stub + i + extension);
        //animals = append(animals,animalName);
    
      }
      return animals;
    }
    
    function getImage(img) {
      animals.push(img);
    }
    
    function displayPhoto() {
      if (visualizePhoto) {
        //print(" numero de fotos: " + currentPhoto + " h:" + h);
        //print(visualizePhoto);
    
        //image(animals[numbers[h]], onSeeX, marginY, animals[0].width, animals[0].height);
        image(animals[h], onSeeX, marginY, widthX, heightY);
        //print(onSeeX)
        //print(marginY);
        h++;
        onSeeX += (widthX + margin);
        if ((onSeeX + widthX) >= (width - margin)) {
          onSeeX = margin;
          marginY += (heightY + margin);
        }
        currentPhoto += 1;
        if (currentPhoto == numberOfAnimals) {
          visualizePhoto = !visualizePhoto;
          //print(visualizePhoto);
          marginY = 100;
        }
      }
    }
    
  • edited November 2014

    And if I use some of your code, the photos appear but if I refresh the browser the photos change position,

    My sample code doesn't even use image(). It only loads them w/ callback! [-(
    However, I noticed that you don't clear the canvas w/ background()! Might be it... dunno! :-??

    You've gotta understand that in JS, images and other similar resources take some time to load!
    So while that process is taking place, the sketch advances and doesn't wait for it to get finished! :-SS
    That's why we should check whether some p5.Image got added to our array before using image() on it! :-B
    For example, before displaying animals[5], we should check if animals.length > 5just to make sure!

    1 more tip: @ #31 animals = Animal("animals/animal", ".jpg", numberOfAnimals);
    Why are you reassigning animals. Wasn't it initialized w/ [] at the beginning already?! :-?
    And since your Animal() returns animals @ #55, that ends up being the same as animals = animals! ~:>

    1 last advice: Don't capitalize variables as you did w/ Animal()!
    Unless of course it's supposed to be a constructor for a "class". Please rename it to animal(). o->

  • beautiful code... =)

  • edited November 2014

    Hi GoToLoop

    First of all I greatly appreciate your advices. This code runs perfectly in pure Processing, and... I thought it will be easy in p5.js and jump to the web but...

    Well

    _ I noticed that you don't clear the canvas w/ background()_

    the boolean visualizePhoto make that the photos load only one time

    _ before displaying animals[5], we should check if animals.length > 5 just to make sure_

    Sorry, I dont know how to do that

    the last two tips have been corrected

    Current code:

    /////////////////////////////////////////////////
    var h = 0; //future variable global indice del sistemas de eleccion, 
    var score = 0;
    ////////////////////////
    var numberOfAnimals = 9; // number of photos to show
    var numberIndice = 8; // 0,1,2....
    var numberLoadAnimals = 9; // number of photos to choose
    
    //eleccion del indice de  fotos/sonidos
    var animals = [];
    var stub;
    var extension;
    var num;
    /////////////////////////////////////////////////
    //photos animals  positions
    var margin = (1024 / 100) * 2;
    var visualizePhoto = true; // switch show photos
    
    var currentPhoto = 0; // index arrays de photos
    var onSeeX = margin;
    var onSeeY = margin;
    var widthX = 300; //width photo de cada foto
    var heightY = 169; //height photo
    var marginY = 100;
    //end_photos
    /////////////////////////////////////////////////
    function setup() {
      createCanvas(1024, 680);
      //background(255);
      animal("animals/animal",".jpg",numberOfAnimals);
    }
    
    function draw() {
      //background(255);
      //display photo
      displayPhoto();
      //display score
      fill(0);
      textSize(28);
      text("SCORE: " + score, margin, margin * 2);
    }
    
    function animal(stub, extension, num) {
      for (var i = 0; i < numberOfAnimals; i++) {
        loadImage(stub + i + extension, getImage);
        //print(stub + i + extension);
      }
    }
    
    function getImage(img) {
      animals.push(img);
    }
    function displayPhoto() {
      if (visualizePhoto) {
        print(" numero de fotos: " + currentPhoto + " h:" + h);
        //print(visualizePhoto);
    
        image(animals[h], onSeeX, marginY, widthX, heightY);
        h++;
        onSeeX += (widthX + margin);
        if ((onSeeX + widthX) >= (width - margin)) {
          onSeeX = margin;
          marginY += (heightY + margin);
        }
        currentPhoto += 1;
        if (currentPhoto >= numberOfAnimals) {
          visualizePhoto = !visualizePhoto;
          //print(visualizePhoto);
          marginY = 100;
        }
      }
    }
    
  • edited November 2014

    boolean visualizePhoto makes sure photos load only once.

    All photos are already loaded by callbacks at the beginning and transfered to animals[] 1 by 1.
    Display already loaded images via image() isn't the same as load images via loadImage()!

    Since draw() is invoked @ 60 FPS by default, you end up image() them in a fraction of a second.
    Rather relying on visualizePhoto, you coulda issued noLoop() once currentPhoto == numberOfAnimals.

    Sorry, I don't know how to do that.

    1st of all, seems like variables h & currentPhoto are the same thing in your sketch. @-)
    Both represents animals[]'s current index. You should scrap 1 of them to make your sketch more concise! =:)

    As mentioned, in order to avoid any unpleasant surprise of failing to image() a photo not loaded yet,
    we've gotta check whether the current index we're about to display is less than animals.length.
    Otherwise it'd mean that index wasn't push()ed to animals[] yet! In short, needs more time to get loaded! 8-X

    function displayCurrentPhoto() {
      if (currentPhoto >= animals.length)  return;
      image(animals[currentPhoto++], onSeeX, marginY, widthX, heightY);
    
      onSeeX += widthX + margin;
      if (onSeeX + widthX >= width - margin)  marginY += heightY + (onSeeX = margin);
    
      if (currentPhoto == numberOfAnimals)  noLoop();
    }
    

    Now some extra tips: If all fonts in your sketch is always textSize(28) or the ink is always fill(0), etc.
    they should all go into setup(). No need to repeat it @ 60 FPS over & over inside draw(), right? ;;)

    function setup() {
      createCanvas(1024, 680);
      textSize(28), fill(0), background(255);
      animal('animals/animal', '.jpg', numberOfAnimals);
    }
    
  • edited November 2014

    Hi GoToLoop

    I have corrected the improves of your last comments but the problem remain. I think i am not trying to do any odd, just load severals images in a array and then display it.

    what other options do we have?

    Current code:

    /////////////////////////////////////////////////
    var score = 0;
    ////////////////////////
    var numberOfAnimals = 9; // number of photos to show
    var numberIndice = 8; // 0,1,2....
    var numberLoadAnimals = 9; // number of photos to choose
    
    //array
    var animals = [];
    var stub;
    var extension;
    var num;
    /////////////////////////////////////////////////
    //fotos animales , posiciones
    var margin = (1024 / 100) * 2;
    
    var currentPhoto = 0; // index arrays photos
    var onSeeX = margin;
    var onSeeY = margin;
    var widthX = 300; //width photo
    var heightY = 169; //height photo
    var marginY = 100;
    //fin_fotos
    /////////////////////////////////////////////////
    function setup() {
      createCanvas(1024, 680);
      fill(0);
      textSize(28);
      background(255);
      animal("animals/animal",".jpg",numberOfAnimals);
    }
    
    function draw() {
      //background(255);
      //display photo
      displayPhoto();
      //display score
      text("SCORE: " + score, margin, margin * 2);
    }
    
    function animal(stub, extension, num) {
      for (var i = 0; i < numberOfAnimals; i++) {
        loadImage(stub + i + extension, getImage);
        print(stub + i + extension);
      }
    }
    
    function getImage(img) {
      animals.push(img);
    }
    function displayPhoto() {
    
      if (currentPhoto >= animals.length) return;
    
        print("number of photos: " + currentPhoto +" and " + animals.length);
    
        image(animals[currentPhoto++], onSeeX, marginY, widthX, heightY);
    
        onSeeX += (widthX + margin);
        if ((onSeeX + widthX) >= (width - margin)) {
          onSeeX = margin;
          marginY += (heightY + margin);
        }
        if (currentPhoto == numberOfAnimals) {
          marginY = 100;
         noLoop();
        }
    }
    
  • What other options do we have?

    Since I can't run your code due to lack of images, I'm sorry I can't help you out further! 8-|
    If page is refreshed, it should display those images at the same place since everything is re-initialized to their initial values! :(|)

  • edited November 2014

    Hi GoToLoop

    This code with the images (and sounds) are in GITHUB, you can download it. If you have time of course, time is gold... Anyway, thank you very

    https://github.com/CharlyPascual/P5/tree/master/gameLucasp5

  • I've just tested your "P5-master/gameLucasp5/index.html" in Firefox 33, QupZilla 1.8.4 & Opera 12.16.
    And I didn't spot any issues when reloading the page w/ those animal photos! :-@

  • edited December 2014

    Hi GoToLoop

    I feel a little bit stupid (don´t worry about that ) maybe I am missing out, but.. I disagree with you, if you refresh the browser the images change their position, sure, I have tested with FF33 and CHrome 39.

    Of course all animal photo are showed but pay attention to the location of the photos, it change¡ not in all refreshing of the browser, but happends.

    I have tested in local and in http://www.guarderia-nuevavida.org/scual/index.html

  • edited December 2014 Answer ✓

    So sorry! Somehow I thought you meant the position images were placed after each page refresh! X_X
    Turns out it's the order they're being displayed that's troubling you! (~~)
    Since I've tested your sketch w/o a server, simply double-clicked the ".html" file, I had no issues about it!

    Well, that's the very nature of async loading: 1st finished loading, 1st push()ed into animals[]!
    As you've noticed, the speed each image takes to load varies every time, therefore their order changes! #-o

    Easiest way of avoiding all that headache is relying on P5JS's preload() callback.
    But I was afraid that feature would have problems in dealing w/ loadings from a loop + string substitutions.
    Well, if you wanna take the risk, here's a preload() attempt I just did: >:)

    // forum.processing.org/two/discussion/8272/
    // loading-images-from-a-local-path
    
    const QTY = 9, animals = Array(QTY);
    const PATH = 'animals/animal', EXT = '.jpg';
    
    function preload() {
      for (var i = 0; i != QTY; print("Idx: #" + i)
        , animals[i] = loadImage(PATH + i++ + EXT));
    }
    
    function setup() {
      createCanvas(500, 400);
      background(0);
      frameRate(1);
    }
    
    function draw() {
      const idx = frameCount%QTY;
      background(animals[idx]);
      print(idx);
    }
    
  • Don´t worry GoToLoop, for me this thread have been a master-class¡¡

    I have open another branch https://github.com/CharlyPascual/P5/tree/Preload/gameLucasp5

    And tested the preload() also loading sound, now I think I can finish the game.

    Thank you very much :-h

Sign In or Register to comment.