Filepath Issue

edited July 2018 in Android Mode

Hi, I have a Android Processing sketch that used to work a few years ago but I need to update it and can't get it to run. It seems like there is a problem with having the path in the filename string but this used to work..

Any idea how to work around this problem? Ideally I would like to keep my code as is and figure out how to make it run on my device.

Thanks

Phil

 FATAL EXCEPTION: GLThread 787
    Process: processing.test.pixelpetal_v09, PID: 1579
    java.lang.IllegalArgumentException: File sequences/allseq_pixelData/pixelData00000.png contains a path separator
        at android.app.ContextImpl.makeFilename(ContextImpl.java:2366)
        at android.app.ContextImpl.getFileStreamPath(ContextImpl.java:1120)
        at android.content.ContextWrapper.getFileStreamPath(ContextWrapper.java:191)
        at processing.core.PApplet.sketchPath(Unknown Source)
        at processing.core.PApplet.createInputRaw(Unknown Source)
        at processing.core.PApplet.createInput(Unknown Source)
        at processing.core.PApplet.loadImage(Unknown Source)
        at processing.test.pixelpetal_v09.pixelpetal_v09.loadImageSequence(pixelpetal_v09.java:96)
        at processing.test.pixelpetal_v09.pixelpetal_v09.setup(pixelpetal_v09.java:116)
        at processing.core.PApplet.handleDraw(Unknown Source)
        at processing.opengl.PGLES$AndroidRenderer.onDrawFrame(Unknown Source)
        at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
        at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)

Answers

  • please note that there is a new forum now

    please ask there

    https://forum.processing.org/two/discussion/27995/new-forum

  • Are you using the environment from two years ago or are you using the latest Android mode in Processing? If using the latest, some of your code might need to be changed. You need to provide the code showing enough details about the operation that is failing.

    Kf

  • Thanks @kfajer, since I last had it working I have a new laptop and had to fully re-install Processing and the Android SDK.

    I believe that originally I may have used Processing 2.2 and this time I'm trying to use Processing 3.3.

    The code that seems to be causing the issue is below... specifically it's the "loadimage" that seems to error.

    Cheers Phil

    for (int i=0; i<numFrames; i++) { String imageName = "sequences/" + basename + "_pixelData/pixelData" + nf(i, 5) + ".png"; imageSequence[i] = loadImage(imageName); println("Image "+imageName+" was loaded as "+imageSequence[i]); }

  • Please add the code at the end of the this post to your sketch. This code will limit your sketch, so you can only run it in Processing android mode.

    The imports can be placed in the top of your file. This function can be placed at the end of your pde file AND in the same scope as setup() and draw(). This is a quick solution to overpass the error of the file separator that is observed when accessing these resources the way you do.

    Note, your pictures need to be place under the data folder:

    Your sketch folder should look like this:

    sketch01
    ****sketch01.pde
    ****code
    ****data
    *******sequences
    **********allseq_pixelData
    **************pixelData0000.jpg

    I use this loadImage like this:

    final String PPATH="sequences/allseq_pixelData/";
    final String FN="pixelData00000.jpg";
    imageName = PPATH+FN;
    PImage img = loadImage(imageName);  
    

    Kf

    import java.io.*;
    import android.graphics.*;
    //https://github.com/processing/processing-android/blob/master/core/src/processing/core/PApplet.java#L3982
    @Override 
      public PImage loadImage(String filename) { //, Object params) {
      //    return loadImage(filename, null);
    
      println("Processing CUSTOM loading image....");
    
      InputStream stream=null;
      try {
        stream =  surface.getAssets().open(filename); //new FileInputStream(filename);//createInput(filename);
      }
      //catch(FileNotFoundException e) {}
      catch(IOException e) {}
    
    
      if (stream == null) {
        System.err.println("Could not find the image " + filename + ".");
        return null;
      }
      //    long t = System.currentTimeMillis();
      Bitmap bitmap = null;
      try {
        bitmap = BitmapFactory.decodeStream(stream);
      } 
      finally {
        try {
          stream.close();
          stream = null;
        } 
        catch (IOException e) {
        }
      }
      //    int much = (int) (System.currentTimeMillis() - t);
      //    println("loadImage(" + filename + ") was " + nfc(much));
      if (bitmap == null) {
        System.err.println("Could not load the image because the bitmap was empty.");
        return null;
      } else {
        PImage image = new PImage(bitmap);
        image.parent = this;
        return image;
      }
    }
    
  • edited July 2018

    @philspitler I forgot to mention, you need the above override function if you want to keep your folder structure:

    String imageName = "sequences/" + basename + "_pixelData/pixelData" + nf(i, 5) + ".png";

    However, if you drop the folders, you can place all the images inside the data folder and the standard call to loadImage() should work without any modification.

    Kf

  • edited July 2018

    Thanks Kfrajer, I tried the code and got errors while compiling...

    3. ERROR in /private/var/folders/71/whbl6c5x08gczcqq00k33m4w0000gn/T/android317694126990055572sketch/src/processing/test/pixelpetal_v09/pixelpetal_v09.java (at line 354)
        stream =  surface.getAssets().open(filename); //new FileInputStream(filename);//createInput(filename);
                  ^^^^^^^
    surface cannot be resolved
    ----------
    3 problems (1 error, 2 warnings)
    
    BUILD FAILED
    /var/folders/71/whbl6c5x08gczcqq00k33m4w0000gn/T/android317694126990055572sketch/build.xml:15: The following error occurred while executing this line:
    /var/folders/71/whbl6c5x08gczcqq00k33m4w0000gn/T/android317694126990055572sketch/build.xml:28: Compile failed; see the compiler error output for details.
    
    Total time: 1 second
    

    And here is my sketch....

    Any ideas?

    Thanks again.

    Phil

    `
    import com.heroicrobot.dropbit.registry.*;
    import com.heroicrobot.dropbit.devices.pixelpusher.Pixel;
    import com.heroicrobot.dropbit.devices.pixelpusher.Strip;
    import java.util.*;
    import controlP5.*;
    import java.io.*;
    import android.graphics.*;
    
    
    Button myButton1;
    Button myButton2;
    Button myButton3;
    Button myButton4;
    Button myButton5;
    Button myButton6;
    Button myButton7;
    Button myButton8;
    Button myButton9;
    Button myButton10;
    Button myButton11;
    
    
    boolean noStrips = true;
    int buttonYpos = 0;
    
    ControlP5 cp5;
    
    // Set this to true to enable a debug display of the current frame.
    boolean onscreenDebug = true;
    
    int currentFrame = 0;
    
    // setup file path a durations for the image sequences
    
    String[] pathBases = {"null", "black", "grad", "buddah", "wipe", "orange", "embers", "psych", "petals", "sunrise", "smoke", "allseq"};
    int[] durations =     {0,   1,   2000,  1500, 1250, 750, 500, 1000, 1000, 1000, 240,  9704};
    int[] buttonOffsets = {0,   250, 350,   450,  550,  650, 750, 850,  950,  1050, 1150, 1250};
    
    String pathBase = pathBases[1]; // set start patern to "all off"
    int numFrames = durations[1];
    int whichMovie=1;
    
    PImage mainMovie;
    
    
    
    DeviceRegistry registry;
    PusherObserver observer;
    PGraphics offScreenBuffer;
    PImage bg;
    PImage errorScreen;
    PImage loadingScreen;
    
    
    // flags to control whether we redraw the UI
    boolean uiChanged = true;
    
    int Yoffset = -50; // this helps me quickly modify the position of the buttons 
    
    ArrayList<PImage[]> imageSequences;
    
    
    PImage[] loadImageSequence(String basename, int numFrames) {
      // create the array of references
      println("Loading image sequence "+basename+", "+numFrames+" frames.");
      PImage[] imageSequence = new PImage[numFrames];
    
      // now loop over the sequence loading them
      for (int i=0; i<numFrames; i++) {
        String imageName = "sequences/" + basename + "_pixelData/pixelData" + nf(i, 5) + ".png";
        imageSequence[i] = loadImage(imageName);
        println("Image "+imageName+" was loaded as "+imageSequence[i]);
      }
      return imageSequence;
    }
    
    void setup() {
      size(800, 1280, P3D); // Must be first in setup()
    
      // Load all our images.  
    
      imageSequences= new ArrayList<PImage[]>();
      // Add a null object to compensate for the 1-based numbering.
      imageSequences.add(null);
    
      // Load each image sequence and add it to the ArrayList  
      for (int i=1; i<pathBases.length; i++) {
        imageSequences.add(loadImageSequence(pathBases[i], durations[i]));
      }
    
      bg = loadImage("UI_Background.jpg");
      errorScreen = loadImage("noLEDSs.jpg");
      loadingScreen = loadImage("noLEDSs.jpg");
    
      stroke(255);
      noFill();
      strokeWeight(4); 
    
      cp5 = new ControlP5(this); // 
    
      cp5.setAutoDraw(false);
    
      frameRate(24);
    
      // create a new buttons for the UI
    
      myButton1 = cp5.addButton("alloff")
    
        .setCaptionLabel("All Off")
          .setValue(0)
            .setPosition(100, 250+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton2 = cp5.addButton("grad")
    
        .setCaptionLabel("Color Grad")
          .setValue(0)
            .setPosition(100, 350+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton3 = cp5.addButton("buddah")
    
        .setCaptionLabel("Pink Buddah")
          .setValue(0)
            .setPosition(100, 450+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton4 = cp5.addButton("colorwipe")
        .setCaptionLabel("Color Wipe")
          .setValue(0)
            .setPosition(100, 550+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton5 = cp5.addButton("orange")
        .setCaptionLabel("Orange Blossom")
          .setValue(0)
            .setPosition(100, 650+Yoffset)
              .setSize(500, 60)
    
                ;
    
    
    
      myButton6 = cp5.addButton("rustySwirl")
        .setCaptionLabel("Embers")
          .setValue(0)
            .setPosition(100, 750+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton7 = cp5.addButton("psych")
        .setCaptionLabel("psychedelic blue")
          .setValue(0)
            .setPosition(100, 850+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton8 = cp5.addButton("petals")
        .setCaptionLabel("rainbow petals")
          .setValue(0)
            .setPosition(100, 950+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton9 = cp5.addButton("sunrise")
        .setCaptionLabel("Sunrise")
          .setValue(0)
            .setPosition(100, 1050+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton10 = cp5.addButton("smoke")
        .setCaptionLabel("Ice Drops")
          .setValue(0)
            .setPosition(100, 1150+Yoffset)
              .setSize(500, 60)
    
                ;
    
      myButton11 = cp5.addButton("allSeq")
        .setCaptionLabel("All Sequences")
          .setValue(0)
            .setPosition(100, 1250+Yoffset)
              .setSize(500, 60)
    
                ;
    
    
      whichMovie=1; //default
    
      offScreenBuffer = createGraphics(326, 7);// offscreen buffer to hold the pattern
      registry = new DeviceRegistry();
      observer = new PusherObserver();
      registry.addObserver(observer);
      registry.setAntiLog(true);
      registry.setAutoThrottle(true);
    } 
    
    
    
    
    void draw() {
      if (!uiChanged)
        cp5.draw();        // we must do this every frame, or the event handler never fires.
    
      if (uiChanged) {
        buttonYpos = buttonOffsets[whichMovie] + Yoffset;
        background(bg);
        cp5.draw();
        pushMatrix();
        translate(0, buttonYpos);
        rect (100, 0, 500, 60); // selection state for the buttons
        popMatrix();
    
        numFrames = durations[whichMovie];
    
        uiChanged = false;
      }
    
      currentFrame = (currentFrame+1) % numFrames;  // Use % to cycle through frames and loop
      mainMovie = (imageSequences.get(whichMovie))[currentFrame];      // we just reference the images we loaded earlier.
    
      if (noStrips) {
        image(errorScreen, 000, 0, 800, 1280);
        uiChanged = true;
      } // display error if there are no strips detected
    
      if (onscreenDebug)
        image(mainMovie, 0, 0); // blit it so we can see what's happening
      offScreenBuffer.beginDraw();
      offScreenBuffer.image(mainMovie, 0, 0);
      //println(mainMovie);
      scrape(); // scrape the offscreen buffer 
      offScreenBuffer.endDraw();
    
    }
    
    
    
    
    
    // UI selections
    public void controlEvent(ControlEvent theEvent) {
      uiChanged = true;
      println("Took control event.");
      currentFrame = 0;
    }
    
    // ControlP5 automatic event handler methods.
    public void alloff(int theValue) {
      whichMovie = 1;
    }
    
    public void grad(int theValue) {
      whichMovie = 2;
    }
    
    
    
    public void buddah(int theValue) {
      whichMovie = 3;
    }
    
    public void colorwipe(int theValue) {
      whichMovie = 4;
    }
    
    public void orange(int theValue) {
      whichMovie = 5;
    }
    
    public void rustySwirl(int theValue) {
      whichMovie = 6;
    }
    
    public void psych(int theValue) {
      whichMovie = 7;
    }
    
    public void petals (int theValue) {
      whichMovie = 8;
    }
    
    
    public void sunrise(int theValue) {
      whichMovie = 9;
    }
    
    public void smoke(int theValue) {
      whichMovie = 10;
    }
    
    
    public void allSeq(int theValue) {
      whichMovie = 11;
    }
    
    
    void displayLoading() {
    
      loadingScreen = loadImage("noLEDSs.jpg");
      image(loadingScreen, 000, 0, 800, 1280);
    
    }
    
    
    
      public PImage loadImage(String filename) { //, Object params) {
      //    return loadImage(filename, null);
    
      println("Processing CUSTOM loading image....");
    
      InputStream stream=null;
      try {
        stream =  surface.getAssets().open(filename); //new FileInputStream(filename);//createInput(filename);
      }
      //catch(FileNotFoundException e) {}
      catch(IOException e) {}
    
    
      if (stream == null) {
        System.err.println("Could not find the image " + filename + ".");
        return null;
      }
      //    long t = System.currentTimeMillis();
      Bitmap bitmap = null;
      try {
        bitmap = BitmapFactory.decodeStream(stream);
      } 
      finally {
        try {
          stream.close();
          stream = null;
        } 
        catch (IOException e) {
        }
      }
      //    int much = (int) (System.currentTimeMillis() - t);
      //    println("loadImage(" + filename + ") was " + nfc(much));
      if (bitmap == null) {
        System.err.println("Could not load the image because the bitmap was empty.");
        return null;
      } else {
        PImage image = new PImage(bitmap);
        image.parent = this;
        return image;
      }
    }`
    
  • Not sure why that is happening in your case. Surface is one of the internal java classes that should be present in the core.jar. I have few suggestions:

    Go into your sketch folder and rename your manifest file. Build your code again and Processing should regenerate a new manifest.

    A second suggestion: If you run a simple sketch, similar to: https://android.processing.org/tutorials/getting_started/index.html does it work?

    Finally, try this: stream = getActivity().getAssets().open(filename);

    Kf

  • Amazing.... we are getting much closer...

    Regenerating the manifest didn't help...

    Running the sample code did work.

    And then modifying the stream as you suggested got us much closer.

    The app launches on the device for a moment and then errors and quits with the following message...

    FATAL EXCEPTION: GLThread 1202 Process: processing.test.pixelpetal_v09, PID: 12673 java.lang.NullPointerException: src == null at java.lang.System.arraycopy(Native Method) at processing.opengl.PGraphicsOpenGL.setImpl(Unknown Source) at processing.core.PImage.set(Unknown Source) at processing.opengl.PGraphicsOpenGL.backgroundImpl(Unknown Source) at processing.core.PGraphics.background(Unknown Source) at processing.core.PApplet.background(Unknown Source) at processing.test.pixelpetal_v09.pixelpetal_v09.draw(pixelpetal_v09.java:247) at processing.core.PApplet.handleDraw(Unknown Source) at processing.opengl.PGLES$AndroidRenderer.onDrawFrame(Unknown Source) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)

  • edited July 2018

    Actually I went back to a previous version of my sketch, applied your new code and it doesn't give me those errors any more... We are REALLY close now...

    The issue now is with font rendering and CP5

    My font code looks like this..

    `    
    
     cp5 = new ControlP5(this); // 
     PFont pfont = createFont("Arial", 24, true);
     ControlFont font = new ControlFont(pfont, 24);`
    

    And the error I get is:

    Inefficient font rendering: use createFont() with a TTF/OTF instead of loadFont().

  • Actually... the above message is just a warning and I "think" that things are working correctly.... I will know more tomorrow when I get test again...

    HUGE thanks...

    Phil

  • @Phil It is great to know what it is working. Thxs for keeping us updated. I will see you in the new forum as this one will go offline anytime soon.

    All the best,

    Kf

  • @kfrajer, thanks so much for your help... this works perfectly...

    I'm very curious why this changed since I wrote my original sketch but I'm VERY happy it's working again..

    Phil

Sign In or Register to comment.