We are about to switch to a new forum software. Until then we have removed the registration on this forum.
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 : )
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 toselectInput
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...
I hope someone can cast some light in this matter, so we can learn [-O<
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:
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. :PAnd for callbackObject, just use
this
. Since it represents the class type current code context is. :-BP.S.: That mysterious file 3rd parameter is for when we wish to have some File pre-selected when the "chooser dialog" opens up. *-:)
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. :-bdHowever, 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)Actually we're obliged to use an explicit
public
for theclass
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:-OHey @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 :
No need to define some variable which only holds
null
. Merely passesnull
as 3rd argument: :PselectInput("Select a file to process:", "fileSelected", null, this);
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 !
@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.
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: )