How do I load an image with the file selector, and resize the window

edited August 2015 in Questions about Code

Attempt 1:

    PImage img;

    void setup() {
      selectInput("Select a file to process:", "fileSelected");
      size(img.width,img.height); //this returns a null pointer exception
    }
    void draw(){
      background(img);
    }

    void fileSelected(File selection) {
      if (selection == null) {
        println("Window was closed or the user hit cancel.");
      } else {
        println("User selected " + selection.getAbsolutePath());
        img = loadImage(selection.getAbsolutePath());
        }

    }

Why should I get a null pointer exception? Isn't "img" a global variable? Its set in the function "filelected"

Attempt2:

PImage img;

void setup() {
  frame.setResizable(true);
  selectInput("Select a file to process:", "fileSelected");

}
void draw(){
  background(img); // This returns a null pointer exception
}

void fileSelected(File selection) {
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
  } else {
    println("User selected " + selection.getAbsolutePath());
    img = loadImage(selection.getAbsolutePath());
    size(img.width,img.height);
    }

}

Another nullpointer exception.

Attempt 3 :

PImage img;

void setup() {
  frame.setResizable(true);
  selectInput("Select a file to process:", "fileSelected");

}
//void draw(){
//  background(img);
//}

void fileSelected(File selection) {
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
  } else {
    println("User selected " + selection.getAbsolutePath());
    img = loadImage(selection.getAbsolutePath());
    size(img.width,img.height);
    background(img);
    }

}

This kind of works believe it or not. At least is gets to the file selector and actually displays the picture. But if I uncomment the draw(), it turns black. What is going on here? Intuitively is seems the global "img" would be set in the function "fileSelected" and shouldn't be throwing a null pointer exception.

Edit: this looks awful when it posts. There's no way to format the code in the post?

Answers

  • I found this code in this comment thread :

    http://forum.processing.org/two/discussion/comment/42788/#Comment_42788

    This works and the only thing I can figure is draw() is running while file selected is running. In other words, the program doesn't wait for fileSelected() to complete before doing its stuff. It begins immediately . Are all these functions running simultaneously like in different threads?

    Here's the code that works and the only thing it does different make sure img has been assigned a value:

    PImage img = null; 
    boolean imageSelected = false;  // marker 
    
    
    void setup() {
      frame.setResizable(true);
      size(660, 660);
      selectInput("Select a file to process:", "fileSelected");
    } // func
    
    void draw() {
      // eval marker 
      if (!imageSelected) {
        // wait
      } else {
        // show it
        image(img, 0, 0);
      }
    } // func 
    
    void fileSelected(File selection) {
      if (selection == null) {
        println("Window was closed or the user hit cancel.");
      } else {
        println("User selected " + selection.getAbsolutePath());
    
        img = loadImage( selection.getAbsolutePath());
        imageSelected = true;
      }
    } // func
    //
    
  • Answer ✓

    Are all these functions running simultaneously like in different threads?

    Yes, exactly.

  • I also had a problem when I referenced img in setup() after the selectinput() call. So I assume everything starts at once even before setup() completes?

  • edited August 2015

    I also found this. I haven't seriously programmed in about 20 years and if there was multi threading it was in its infancy. I found this :

    extern "C"
     {
        #include <pthread.h>
        #include <unistd.h>
     }
    #include <iostream>
    
    
    using namespace std ;
    
    void  * function1(void * argument);
    void  * function2(void * argument);
    
    int main( void )
    {
        pthread_t t1, t2 ; // declare 2 threads.
        pthread_create( &t1, NULL, function1,NULL); // create a thread running function1
        pthread_create( &t2, NULL, function2,NULL); // create a thread running function2
    
        // Because all created threads are terminated when main() finishes, we have
        // to give the threads some time to finish. Unfortunately for function1, main()
        // will give only 1 second, but function1 needs at least 2 seconds. So function1 will
        // probably be terminated before it can finish. This is a BAD way to manage threads.
        sleep(1);
    
        return 0;
    }
    
    void * function1(void * argument)
    {
        cout << " hello " << endl ;
        sleep(2); // fall alseep here for 2 seconds...
        return 0;
    }
    
    void * function2(void * argument)
    {
        cout << " world "  << endl ;
        return 0;
    }
    

    Its a whole new world. I'm so used to functions occurring in order, this will take some practice. K&R must be spinning.

  • you wrote

    running while file selected is running. In other words, the program doesn't wait for fileSelected() to complete before doing its stuff.

    but the code does exactly this: draw() runs and while there is no image selected , it runs doing nothing (it waits)

    The marker imageSelected controls this behaviour (the ! sign means not).

    but this is how you do it: let draw() run on empty till the other thread is done and is signalling this by setting imageSelected to true

    void draw() {
      // eval marker 
      if (!imageSelected) {
        // wait
      } else {
        // show it
        image(img, 0, 0);
      }
    } // func 
    

    Chrisir

  • _vk_vk
    edited August 2015

    Here an old code that do load and resize the window to fit the image size:

    //no error handling for non image files!
    
    PImage img;
    int newCanvasWidth  = MIN_WINDOW_WIDTH;  // made global to  use in draw
    int newCanvasHeight = MIN_WINDOW_HEIGHT;
    String path ="";
    
    
    java.awt.Insets insets;  //"An Insets object is a representation of the borders of a container"
    //from: docs.oracle.com/javase/1.4.2/docs/api/java/awt/Insets.html
    
    void setup()
    {
      size(400, 200);
      frame.pack();     //frame.pack() ... plus insets
      insets = frame.getInsets();
      frame.setResizable(true);
    
      /// for debuging, system dependent, at least screen is...
      print("MIN_WINDOW_WIDTH = " + MIN_WINDOW_WIDTH);
      print("   MIN_WINDOW_HEIGHT = " + MIN_WINDOW_HEIGHT);
      print("   screenWidth = " + displayWidth);
      println("    screenHeight = " + displayHeight);
    
      // simple instruction : )
      text("click window to load an image", 10, 100);
    }
    
    
    void draw()
    {
    
      if (img != null)
      {
    
        image(img, 0, 0, newCanvasWidth, newCanvasHeight);
      }
    }
    
    void getImageAndResize()
    { 
      selectInput("select an image", "handleImage");
    }
    
    
    void handleImage(File selection) {
    
      if (selection== null)
      {
        println ("nono");
      } 
      else
      {
        path = selection.getAbsolutePath();
        img = loadImage(path);
    
        // a temp variable for readability 
        int widthInsets =insets.left + insets.right;
        int heightInsets =insets.top + insets.bottom;
    
        // constrain values between screen size and minimum window size
        int newFrameWidth  = constrain(img.width + widthInsets, MIN_WINDOW_WIDTH, displayWidth);
        int newFrameHeight = constrain(img.height + heightInsets, MIN_WINDOW_HEIGHT, displayHeight);
    
        // Canvas should consider insets for constraining? I think so...
        newCanvasWidth  = constrain(img.width, MIN_WINDOW_WIDTH - widthInsets, displayWidth - widthInsets);
        newCanvasHeight = constrain(img.height, MIN_WINDOW_HEIGHT - heightInsets, displayHeight - heightInsets);
    
    
        // set canvas size to img size WITHOUT INSETS
        // set frame size to image + Insets size
        setSizes(newCanvasWidth, newCanvasHeight, newFrameWidth, newFrameHeight);
    
        //// for debuging
        println(path);
        println(" ");
        print("imgW      = " + img.width);
        println("   imgH       = " + img.height);
        print("width+ins = " + widthInsets);
        println("      height+ins = " + heightInsets);
        print("nFrameW   = " + newFrameWidth);
        println("   nFrameH    = " + newFrameHeight);
        print("nCanvasw  = " + newCanvasWidth);
        println("   nCanvsH    = " + newCanvasHeight);
        println(" ------  ");
      }
      println(width + "  "+ height);
    }
    
    void setSizes (int canvasX, int canvasY, int frameX, int frameY)
    {
      // set canvas size to img size WITHOUT INSETS
      setSize(canvasX, canvasY);
    
      // set frame size to image + Insets size
      frame.setSize(frameX, frameY);
      println(width + "  "+ height);
    }
    
    void mouseClicked()
    {
      img = null;
      getImageAndResize();
    }
    
  • @_vk, thanks for the example. That does perfectly something I've wanted to do for a long time.

  • :) good!

Sign In or Register to comment.