Problem for create a class

Hi, sorry for the mess, this forum is new for me and I don't know well the usages. I already created a thread for this question but it wasn't clear and I 'accidentally' mark some answer as a good answer without being able to cancel.

so, here is my main problem for the moment, I'm trying to port this code as a class

In fact, the selectFolder use a callback function : 'fileSelected'. but when I try to do that class conversion, it seems that I can't reach the callback method inside the class : "fileSelected() could not be found".

That's a thing which loose me a bit, I tried this.fileSelected but no luck.

How can I do ?

Also I'm not sure if I can't interrupt the draw() function from that class for draw a menu, in fact I can't figure out the ideal way for make it. I can't find any exemple that use a class loading a menu. Maybe this is simply a wrong approach ?

My final goal is to process image sequences, loading them , execute a process and save them inside a new folder.

Maybe that processing isn't a good environment for what I'm trying to do ? sorry, here is the working code that I'm trying to port as a class.

PImage    img;
PFont     f;

String[]  list_file;
String    seq_png_absolutepath;
int[]     possible_seq;

int       idx_png_seq_selected;

boolean   png_menu   = false;
boolean   png_render = false;

class png_file {
  String  name;
  int     check_sum;
  int     num;
  int     len_num;
  boolean zero_format;
  boolean part_of_seq;
}

class png_sequence {
  String  name;
  boolean zero_format;
  int     len_zerof;
  int     nbr_file;
  int     first_frame;
  int     last_frame;
}

// Array Object
png_file[]     list_png;
png_sequence[] png_final_array;


void setup() 
{
  size(400, 400); 
  if (frame != null) {
    frame.setResizable(true);
  }
  f = createFont("Consolas", 16, true);
  noLoop();
  selectFolder("Select a file to process:", "fileSelected");
}

void draw() 
{

  background(0);

  if (png_menu) {
    textFont(f);       
    fill(255);

    textAlign(LEFT);
    text("Choose a sequence : ", 5, 20 );
    text("-------------------", 5, 34 );
    //mouseY
    if (mouseY >= 36  && mouseY <= 36 + 14 * png_final_array.length) {
      //beginDraw();
      fill(255, 0, 0);
      rect(0, 36 + (round(mouseY - 36) / 14) * 14, width, 14);
    }
    fill(255);
    for (int i = 0; i < png_final_array.length; i++) {
      int size_seq = 1 + png_final_array[i].last_frame - png_final_array[i].first_frame;
      text(png_final_array[i].name + ", " + size_seq + " images", 5, 50 + i * 14);
    }
  }

  if (mousePressed && png_menu) { 
    png_menu = false;
    png_render = true;
    noLoop();
    idx_png_seq_selected = (round(mouseY - 36) / 14);

    img = loadImage(png_seq_recreate_name(idx_png_seq_selected, 3));
    println(png_seq_recreate_name(idx_png_seq_selected, 3));

    frame.setSize(img.width, img.height);
    println("img.width = " + img.width);
    image(img, 0, 0);
  }
}


void fileSelected(File selection) 
{
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
  } else {
    if (png_detect(selection)) {
      png_menu = true;
      loop();
    }
  }
}

String png_seq_recreate_name(int idx, int n_image) {
  //n_image is relativ, that means that it alwayz begin by zero. (n_image + first_frame)


  String a;
  String n;
  a = png_final_array[idx].name;
  n = Integer.toString(n_image + png_final_array[idx].first_frame);
  <del></del>
  if (png_final_array[idx].zero_format) {
    int zero_n = png_final_array[idx].len_zerof - n.length();
    for (int i = 0; i <  zero_n; i++) {
      println("i = " + i);
      n = "0"+ n;
    }
  }
  a = seq_png_absolutepath + "\\" + a + n + ".png";
  String b = Character.toString((char)92);

  println(b);
  println(b);
  println(b);
  println(a);
  a = a.replace("\\", "/");
  return a;
}


boolean png_detect(File selection) 
{
  String num;
  char   a  ;
  String ext;
  int    asc_l;
  int    len; 
  int    chk_sum;   
  int    png_count = 0;

  list_file = selection.list();
  seq_png_absolutepath = selection.getAbsolutePath();
  if (list_file == null) {
    println("Folder does not exist or cannot be accessed.");
  } else {

    list_png = new png_file[list_file.length];

    for (int i = 0; i < list_file.length; i++) {
      num = "";
      len = list_file[i].length();
      ext = list_file[i].substring(len - 4, len); 

      //match png 
      if (ext.equals(".png")) {
        png_count++;
        list_png[png_count - 1] = new png_file();


        //name and number
        for (int j = len - 5; j > 0; j--) {
          a      = list_file[i].charAt(j);
          asc_l  = (int) a;
          if (asc_l >= 48 && asc_l <= 57) {
            num = a + num;
          } else {
            list_png[png_count - 1].len_num = (len - 5) - j;
            list_png[png_count - 1].name    = list_file[i].substring(0, j + 1);
            break;
          }
        }


        if (num.length() > 0) {
          list_png[png_count - 1].part_of_seq = true;
          list_png[png_count - 1].num         = Integer.parseInt(num);
          list_png[png_count - 1].len_num     = num.length();

          if (num.length() > 1) {
            if (new String("0").equals(num.substring(0, 1))) {
              list_png[png_count - 1].zero_format = true;
            } else {
              list_png[png_count - 1].zero_format = false;
            }
          }
        } else {
          list_png[png_count - 1].part_of_seq = false;
        }  


        chk_sum = 0;
        for (int j = 0; j < len - 4 - num.length (); j++) {
          a = list_file[i].charAt(j);
          chk_sum += (int) a * (j + 1);
        }

        list_png[png_count - 1].check_sum = chk_sum;
      }
    }
  }




  possible_seq = new int[100]; 


  if (png_count > 0) {
    println("PNG files detected :" + png_count);
    boolean numbered_png = false;
    for (int i = 0; i < png_count; i++) {
      if (list_png[i].part_of_seq) { 
        numbered_png = true; 
        break;
      }
    }

    if (!numbered_png) { 
      println("Error : No numbered files detected !");
      return false;
    } else {
      int chk_count = 1;


      for (int i = 0; i < png_count; i++) {
        if (i == 0) { 

          for (int j = 0; j < png_count; j++) { 
            if (list_png[j].part_of_seq) {
              possible_seq[chk_count - 1] = list_png[j].check_sum;
              break;
            }
          }
        } else {

          if (list_png[i].part_of_seq) {
            boolean already_exist = false;

            for (int j = 0; j < possible_seq.length; j++) {
              if (possible_seq[j] == list_png[i].check_sum) {
                already_exist = true; 
                break;
              }
            }

            if (!already_exist) {
              chk_count++;
              possible_seq[chk_count - 1] = list_png[i].check_sum;
            }
          }
        }
      }


      png_final_array = new png_sequence[chk_count++];

      for (int i = 0; i < 100; i++) {
        if (possible_seq[i] == 0) {
          break;
        } else {

          for (int j = 0; j < png_count; j++) {

            if (possible_seq[i] == list_png[j].check_sum) {
              png_final_array[i]             = new png_sequence();
              png_final_array[i].name        = list_png[j].name;
              png_final_array[i].zero_format = false;
              png_final_array[i].len_zerof   = 0;

              for (int k = 0; k < png_count; k++) {
                if (possible_seq[i] == list_png[k].check_sum  && list_png[k].zero_format) {
                  png_final_array[i].len_zerof   =  list_png[k].len_num;
                  png_final_array[i].zero_format = true;
                  break;
                }
              }

              break;
            }
          }


          int min = 300000;
          int max = 0;

          for (int j = 0; j < png_count; j++) {
            if (list_png[j].check_sum == possible_seq[i]) {
              if (list_png[j].num < min) { 
                min = list_png[j].num;
              }
              if (list_png[j].num > max) { 
                max = list_png[j].num;
              }
            }
          }

          png_final_array[i].first_frame = min;
          png_final_array[i].last_frame  = max;
        }
      }
    }
  } else {
    println("There isn't PNG files in this folder");
    return false;
  }

  for (int i = 0; i < png_final_array.length; i++) {
    println("Seq "+ i + " : " + png_final_array[i].name + " Zf :" + png_final_array[i].zero_format + " len Zf " + png_final_array[i].len_zerof + ", first num : " + png_final_array[i].first_frame + ", last_frame : " + png_final_array[i].last_frame);
  }


  return true;
}

Answers

  • http://forum.Processing.org/two/discussion/12443/png-image-sequence-import

    I've closed your previous thread. Please avoid creating new 1s for the very same subject!
    No 1 cares whether a thread was marked as "answered". I believe most answerers would still check them out!

  • ok, thank you. This is the last time, I promise : )

  • _vk_vk
    edited September 2015

    Hello.

    selectInput uses java reflection. I don't really know about reflection. It appears to me that if the method to be called is inside a inner class (all calsses built in PDE are inner classes of the sketch class) you need to pass the object to selectInput

    Without really understand this I made some tries. This one seems to be working fine, but ~X( I didn't get all that is happening under the hood...

    Handler h;
    
    // The version of selectInput that takes an object also needs a File
    // I'm not quite sure about those, but passing this null File did it...
    // Sorry I hate to not understand what I'm doing...
    
    
    File f = null;
    
    
    void setup() {
    
      // instantiate a Handler
      h = new Handler();
    
      // pass the null file and the instance of Handler
      selectInput("Select a file to process:", "fileSelected", f, h);
    }
    
    
    
    // public must be explicit
    public class Handler {
      Handler() {
      }
    
      // public must be explicit
      public void fileSelected(File selection) {
        if (selection == null) {
          println("Window was closed or the user hit cancel.");
        } else {
          println("User selected " + selection.getAbsolutePath());
        }
      }
    }
    

    I hope someone can cast some light in this matter, so we can learn [-O<

  • edited September 2015

    Looking at selectInput()'s web reference below, it's easy to spot it got 4 overloaded signatures:
    https://Processing.org/reference/selectInput_.html

    Unfortunately it's no surprise at all they only explain the 1st signature,
    leaving the other 3 in a shroud of mystery! >:P

    Looking at its source code, we realize it's a chain of overloaded calls,
    where the signature method w/ less parameters call the next other w/ 1 more parameter:
    https://GitHub.com/processing/processing/blob/master/core/src/processing/core/PApplet.java#L6210

    If we call selectInput(), either w/ 2 or 3 parameters, it's assumed the 4th 1 is the sketch itself:

    public void selectInput(String prompt, String callback, File file) {
      selectInput(prompt, callback, file, this);//this references PApplet sketch itself
    }
    

    Therefore if the callback method belongs to another class, we gotta choose the signature which got callbackObject 4th parameter in it: selectInput(prompt, callback, file, callbackObject)

    Generally we don't care about the file parameter. So just pass null for it. :P
    And for callbackObject, just use this. Since it represents the class type current code context is. :-B

    P.S.: That mysterious file 3rd parameter is for when we wish to have some File pre-selected when the "chooser dialog" opens up. *-:)

  • edited September 2015

    vk, you did right there. You've passed to selectInput() an instance of Handler class as its callbackObject 4th parameter. And null as its file 3rd parameter. :-bd

    However, if we wanted to call selectInput() inside Handler class itself, we pass this instead. :ar!

    Remember that this keyword is contextual in Java. It always refers to the class type it is typed in. ~O)

  • edited September 2015
    // public must be explicit
    public class Handler {
      Handler() {
      }
    
      // public must be explicit
      public void fileSelected(File selection) {
    

    Actually we're obliged to use an explicit public for the class only.
    PDE's pre-processor parser automatically adds public keyword for all methods & fields still w/o 1.
    Strangely it doesn't do the same for classes & interfaces... 8-}

    And of course, an empty constructor is redundant when we got no other overloaded 1s. :P

    P.S.: For anonymous instantiations inside methods, PDE's parser forgets to place public keyword! 3:-O

  • _vk_vk
    edited September 2015

    Hey @GoToLoop, thanks for the amazing and complete explanation. I was counting on you :D. I didn't know that an empty constructor is redundant, among other things...

    cheers

    ^:)^

  • hehey, it seems that the question was more complex that what I was expecting for. Pretty interesting thread then and thank you for your answers, so I did this in order to have a handsome class :

    Handler h;
    
    // The version of selectInput that takes an object also needs a File
    // I'm not quite sure about those, but passing this null File did it...
    // Sorry I hate to not understand what I'm doing...
    
    
    File f = null;
    
    
    void setup() {
    
      // instantiate a Handler
      h = new Handler();
      h.openDiag();
      // pass the null file and the instance of Handler
    
    }
    
    
    
    // public must be explicit
    public class Handler {
      Handler() {
      }
      public void openDiag() {
        selectInput("Select a file to process:", "fileSelected", f, this);
      }
      // public must be explicit
      public void fileSelected(File selection) {
        if (selection == null) {
          println("Window was closed or the user hit cancel.");
        } else {
          println("User selected " + selection.getAbsolutePath());
        }
      }
    }
    
  • edited September 2015 Answer ✓

    No need to define some variable which only holds null. Merely passes null as 3rd argument: :P
    selectInput("Select a file to process:", "fileSelected", null, this);

  • edited September 2015

    hehe, I know but I use it for open the dialog alwayz at the right place where there is all my png sequences folders : p

    so my class work fine now, but the menu still managed inside the draw function of the main file. do you think that technically it should stay like that ? in fact it could be more confortable to just have to launch the openDiag method or lets say importSequence method for make it open that dialog and then draw a menu that allow to select a sequence in particular and voila. but that's maybe a bad idea I'm not sure about it

  • nevermind, I found about the registerDraw method, thank you all for your answers !

  • edited September 2015 Answer ✓

    @AnimalMystik, be aware that registerDraw() is @Deprecated since Processing 2. :-t
    And it's been completely removed in Processing 3 now! :-&
    Use registerMethod() instead: registerMethod("draw", this). *-:)

  • :-O , good to know !

    By the way, I'm not really done with this project.. in fact the OpenDiag method that I launch inside the main setup() function do not stop the process and it try to load the image before I even had the time to select a folder.

  • edited September 2015

    ok I've this now and I think that it's almost done, again if you see any stupid stuff, a thing that should be done differently, I'm opened to all your suggestions: )

    PImage         img;
    Import_seq_png seq1;
    int            png_idx = 0;
    boolean        process = false;
    
    void setup() {
        size(400, 400);
    
    
        if (frame != null) {
            frame.setResizable(true);
        }
    
        seq1 = new Import_seq_png();
        seq1.OpenDiag();
    }
    
    
    void draw() 
    {
        background(0);
        if (seq1.import_success && !seq1.process_init) {
            noLoop();
            //load the first image in order to change de frame size.
            img = loadImage(seq1.getPath(0));
            frame.setSize(img.width, img.height);
            seq1.process_init = true;
            seq_process();
        }
    
    
    }
    
    void seq_process(){
        for (int i = 0 ; i < seq1.len_idx; i++) {
            println("load : " + seq1.getPath(i));
            img = loadImage(seq1.getPath(i));
            image(img,0,0);
            //Process...
    
        }
    }
    
    
        //the class file : 
    
    
        public class Import_seq_png 
        {
            // file
            String[]  list_file;
            String    seq_png_absolutepath;
    
            //sequence
            int[]     possible_seq;
            int       idx_png_seq_selected;
            int       first_idx;
            int       last_idx;
            int       len_idx;
            boolean   import_success = false;
            boolean   process_init = false;
    
            //menu
            boolean   png_menu       = false;
            PFont     f;
    
            //Object Array
            png_file[]     list_png;
            png_sequence[] png_final_array;
    
    
            class png_file {
                String    name;
                int       check_sum;
                int       num;
                int       len_num;
                boolean   zero_format;
                boolean   part_of_seq;
            }
    
            class   png_sequence {
                String  name;
                boolean zero_format;
                int     len_zerof;
                int     nbr_file;
                int     first_frame;
                int     last_frame;
                int     len;
            }
    
            Import_seq_png() {
                f = createFont("Consolas", 16, true); 
                registerMethod("draw", this);
            }
    
            public void OpenDiag() {
                selectFolder("Choose a folder containing a PNG sequence...", "fileSelected", null,  this);
            }
    
            public void fileSelected(File selection) {
                if (selection == null) {
                    println("Window was closed or the user hit cancel.");
    
                } else {
                    if (png_detect(selection)) {
                        png_menu = true;
                    } else {
    
                    }
                }
            }
    
            public String getPath(int n_image) {
                //this is the method to use once the OpenDiag method has done it job
                //n_image is relative the first image will alwayz have the n_image 0
    
                String a;
                String n;
                a = png_final_array[idx_png_seq_selected].name;
                n = Integer.toString(png_final_array[idx_png_seq_selected].first_frame + n_image);
    
                //Add the zero if the sequence is numbered like that '0001', '002' , '03', etc...
                if (png_final_array[idx_png_seq_selected].zero_format) {
                    int zero_n = png_final_array[idx_png_seq_selected].len_zerof - n.length();
                    for (int i = 0; i <  zero_n; i++) {
                        n = "0"+ n;
                    }
                }
    
                a = seq_png_absolutepath + "\\" + a + n + ".png";
                a = a.replace("\\", "/");
    
                return a;
            }
    
    
            boolean png_detect(File selection) 
            {
                String num;
                char   a  ;
                String ext;
                int    asc_l;
                int    len; 
                int    chk_sum;            
                int    png_count = 0;
    
                list_file = selection.list();
                seq_png_absolutepath = selection.getAbsolutePath();
    
                if (list_file == null) {
                    println("Folder does not exist or cannot be accessed.");
                } else {
                    list_png = new png_file[list_file.length];
    
                    for (int i = 0; i < list_file.length; i++) {
                        num = "";
                        len = list_file[i].length();
                        ext = list_file[i].substring(len - 4, len); 
    
                        //match png 
                        if (ext.equals(".png")) {
                            png_count++;
                            list_png[png_count - 1] = new png_file();
    
    
                            //name and number
                            for (int j = len - 5; j > 0; j--) {
                                a      = list_file[i].charAt(j);
                                asc_l  = (int) a;
                                if (asc_l >= 48 && asc_l <= 57) {
                                    num = a + num;
                                } else {
                                    list_png[png_count - 1].len_num = (len - 5) - j;
                                    list_png[png_count - 1].name    = list_file[i].substring(0, j + 1);
                                    break;
                                }
                            }
    
                            //Detect if the sequence is numbered with zero like this : '0001', '0002' , '03', '000000005' ,etc...
                            if (num.length() > 0) {
                                list_png[png_count - 1].part_of_seq = true;
                                list_png[png_count - 1].num         = Integer.parseInt(num);
                                list_png[png_count - 1].len_num     = num.length();
                                //si num est plus long que 1 caractère et que le premier chiffre en partant de la gauche est un 0
                                if (num.length() > 1) {
                                    if (new String("0").equals(num.substring(0, 1))) {
                                        list_png[png_count - 1].zero_format = true;
                                    } else {
                                        list_png[png_count - 1].zero_format = false;
                                    }
                                }
                            } else {
                                list_png[png_count - 1].part_of_seq = false;
                            }  
    
                            //a kind of checksum
                            chk_sum = 0;
                            for (int j = 0; j < len - 4 - num.length (); j++) {
                                a = list_file[i].charAt(j);
                                chk_sum += (int) a * (j + 1);
                            }
    
                            list_png[png_count - 1].check_sum = chk_sum;
                        }
                    }
                }
    
                possible_seq = new int[100]; // if a day you have more than 100 differents png sequences, send me a mail...
    
                if (png_count > 0) {
                    println("PNG files detected :" + png_count);
                    boolean numbered_png = false;
                    for (int i = 0; i < png_count; i++) {
                        if (list_png[i].part_of_seq) { 
                            numbered_png = true; 
                            break;
                        }
                    }
    
                    if (!numbered_png) { 
                        println("Error : No numbered files detected !");
                        return false;
                    } else {
                        int chk_count = 1;      
    
                        //count the number of different checksums value
                        for (int i = 0; i < png_count; i++) {
                            if (i == 0) { 
    
                                for (int j = 0; j < png_count; j++) { 
                                    if (list_png[j].part_of_seq) {
                                        possible_seq[chk_count - 1] = list_png[j].check_sum;
                                        break;
                                    }
                                }
                            } else {
    
                                if (list_png[i].part_of_seq) {
                                    boolean already_exist = false;
    
                                    for (int j = 0; j < possible_seq.length; j++) {
                                        if (possible_seq[j] == list_png[i].check_sum) {
                                            already_exist = true; 
                                            break;
                                        }
                                    }
    
                                    if (!already_exist) {
                                        chk_count++;
                                        possible_seq[chk_count - 1] = list_png[i].check_sum;
                                    }
                                }
                            }
                        }
    
    
                        png_final_array = new png_sequence[chk_count++];
    
                        for (int i = 0; i < 100; i++) {
                            if (possible_seq[i] == 0) {
                                break;
                            } else {
    
                                for (int j = 0; j < png_count; j++) {
                                    //retreive the string associate to the checksum value
                                    if (possible_seq[i] == list_png[j].check_sum) {
                                        png_final_array[i]             = new png_sequence();
                                        png_final_array[i].name        = list_png[j].name;
                                        png_final_array[i].zero_format = false;
                                        png_final_array[i].len_zerof   = 0;
                                        // if at least one file is numbered with zero then it assume that the whole sequence if numbered with zero
                                        for (int k = 0; k < png_count; k++) {
                                            if (possible_seq[i] == list_png[k].check_sum  && list_png[k].zero_format) {
                                                png_final_array[i].len_zerof   =  list_png[k].len_num;
                                                png_final_array[i].zero_format = true;
                                                break;
                                            }
                                        }
    
                                        break;
                                    }
                                }
                                //first frame and last frame number
    
                                int min = 300000;
                                int max = 0;
    
                                for (int j = 0; j < png_count; j++) {
                                    if (list_png[j].check_sum == possible_seq[i]) {
                                        if (list_png[j].num < min) { 
                                            min = list_png[j].num;
                                        }
                                        if (list_png[j].num > max) { 
                                            max = list_png[j].num;
                                        }
                                    }
                                }
    
                                png_final_array[i].first_frame = min;
                                png_final_array[i].last_frame  = max;
                                png_final_array[i].len         = 1 + max - min;
                            }
                        }
                    }
                } else {
                    println("There isn't PNG files in this folder");
                    return false;
                }
    
                for (int i = 0; i < png_final_array.length; i++) {
                    println("Seq "+ i + " : " + png_final_array[i].name + " Zf :" + png_final_array[i].zero_format + " len Zf " + png_final_array[i].len_zerof + ", first num : " + png_final_array[i].first_frame + ", last_frame : " + png_final_array[i].last_frame);
                }
    
                return true;
            }
    
            void draw() {
                    if (png_menu) {
                        background(0);
                        textFont(f);       
                        fill(255);
                        textAlign(LEFT);
                        text("Choose a sequence : ", 5, 20 );
                        text("-------------------", 5, 34 );
                        //mouseY
                        if (mouseY >= 36  && mouseY <= 36 + 14 * seq1.png_final_array.length) {
                            //beginDraw();
                            fill(255, 0, 0);
                            rect(0, 36 + (round(mouseY - 36) / 14) * 14, width, 14);
                        }
    
                        fill(255);
                        for (int i = 0; i < seq1.png_final_array.length; i++) {
                            int size_seq = 1 + seq1.png_final_array[i].last_frame - seq1.png_final_array[i].first_frame;
                            text(seq1.png_final_array[i].name + ", " + size_seq + " images", 5, 50 + i * 14);
                        }
    
                        if (mousePressed) { 
                            png_menu = false;
                            idx_png_seq_selected = (round(mouseY - 36) / 14);
                            first_idx = png_final_array[idx_png_seq_selected].first_frame;
                            last_idx  = png_final_array[idx_png_seq_selected].last_frame;
                            len_idx   = 1 + png_final_array[idx_png_seq_selected].last_frame - png_final_array[idx_png_seq_selected].first_frame;
                            import_success = true;
    
                        }
                    }
            }
    
    
        }
    
Sign In or Register to comment.