View Full Version : FilterMeister - General Info Cameraken 02-10-2006, 07:27 AM (byRo: this thread was split from another much longer one - so some posts may seem out of context)
FilterMeister (FM) is a plug-in for Adobe Photoshop®-compatible graphics programs with the ability to create professional plug-in filters which can be distributed on a royalty-free basis.
It’s available here
http://www.filtermeister.com
There are loads of samples and documentation at the site and there is a User group here.
http://groups.yahoo.com/group/FMML/
we can share filters and ideas and perhaps learn the C+ style language.
Ken A question...
How many folks aroud here already have experience with FilterMeister?
I started messing around in Filter Factory, but the interface was sooo ugly that I lost interest.
Now I'm getting fired up again.
Rô I must start reading that manual.I just did!
Something I picked up. is that the Border code done this way is very inefficient.
You will be testing every single pixel in the image, to just alter a few of them which happen to be the border area.
Much quicker, in terms of execution time, would be to set up some loops to change only the borders.
(Although, admittedly, in this case, it probably isn't really worth it).
Talking of execution speed...
I've been tearing apart the "Recursive Gaussian Blur" code.
I noticed that the author does not use X and Y, but instead uses x_start, x_end, y_start and y_end.
I, thinking how clever I was :tired: , substituted the X and Y into the code - which then ran 6 times slower.
Stroker? Help! What's going on?
Rô Stroker 02-17-2006, 12:59 PM When you have an image in FM, the dimensions are 0 to X and 0 to Y. Actually, I think it's X-1 and Y-1.
Now, the preview can only show so much. The viewable part of the image in the preview is x_start to x_end and y_start to y_end. When you use these, you are only processing only what is in the preview instead of the entire image.
The suck part is when using isTilable=False. This is going to be the case when using recursive Gauss. When previewing with rG, just the preview is processed and all is fine. However, once you click Okay, the entire image is now one big tile instead of little chunks. Add buffer usage and memory can sky rocket. This means that rG will bog down with bigger images when you click Okay, but should be fine while previewing.
Make sense?
edit:
Just found out my 8 year old is being taught French in school (public). Her reading level is very advanced, so she is in a special class. Just had to share that. Now, the preview can only show so much. The viewable part of the image in the preview is x_start to x_end and y_start to y_end. When you use these, you are only processing only what is in the preview instead of the entire image.That explains it PERFECTLY! Thanks. :bigthmb:
Just found out my 8 year old is being taught French in school (public). Her reading level is very advanced, so she is in a special class. Just had to share that.Pleased to hear -you must be very proud!
(I hated French whan I was at school, but that's probably because I HAD to take it - now I speak Portuguese all day!)
Rô OK, stroker, here's some to start....
1) The "OnCtl" handler gets activated whenever something happens in a control (or in the dialog?). The "ForEveryTile" also gets activated. If I set a control to "no event" (or something like that) can I avoid the "ForEveryTile";
2) It seems that every time the ForEveryTile starts, the image buffers (pget / tget / t2get) get cleared. Right?
3) Inside the "OnFilterStart" handler, I don't have access to x_start etc. (OK, that's pretty obvious) but can I still access the source pixels (src(x,y,z))?
4) If I want to do an initial one-off transformed image (like in my equalization plugin) and don't want to keep on recalculating the same thing needlessly, I imagine (based on question 2 and 3) that I could calculate the "transform" in the "OnFilterStart" handler and then would have to store in an array (memory). Right?
5) Seems that the scope of variables is only within the handler. If I want to pass a value between handlers (or iterations) the options would be:
a) A control on the dialog;
b) Use the variable array ( get(), put()) - assuming that this doesn't get cleared every time. Does it?
c) Stored in memory.
6) Seems that I remember you sneaked in something like "extendedui", what's that?
7) Where's your secret supply of FM info?
OK, you don't have to reply to 7) if it really is a secret, OK?
Rô Stroker 03-01-2006, 05:05 PM 1. I'm not sure. I'll look into this.
2. See #1, but I'm fairly sure buffers are cleared.
3. You should have access to those variables. Try this:
%ffp
OnFilterStart:{
Info("%d %d",x_start,x_end);
return false;
}
If you zoom in/out and pan, you should get x_start et al.
4. This one is kind of tricky. Currently it has to be hacked using a system global variable.
%ff
OnFilterStart:{
if (i9==0){
i9=123456;
// more code here to run once
}
return false;
}
OnCtl(n):{
if ((n==CTL_CANCEL || n==CTL_OK) && e==FME_CLICKED) i9=0; //RESET IT
return false;
}
It's an ugly hack, but it works. If you plan on moving ctl_preview, ctl_zoom, or ctl_progress, you have to use this hack and setCtlPos().
A truly run once structure is in the works. I think it is called OnFilterInit. Personally, I'm partial to OnFilterAlpha.
5. A common method is to use a control and hide it. I'm pretty sure get() and put() are global. Arrays ala allocArray() are global. There are some named variables that are global, like i9 k0 str0, but I don't know too much about these.
6. "extendedui" is for drop-down lists. Combobox, I believe. I can't remember what it does off the top of my head, but I know I like it so I just use it automatically. Should be in UserGuide.pdf.
7. The docs (HTML and PDF), FMML archive, source codes, and lots of time reading. I also keep a notebook - a honker 3' D-ring by my right elbow. I've been at it for close to a year and I'm only just starting to feel the groove.
Roland, you should check out the FM Mailing List (FMML). Lots of good FM users there including the developers. Sounds like you might be getting too big for my breaches and you will need their help more than mine soon enough. Kudos. Thanks, Stroker, really appreciate the help. :bigthmb: :bigthmb:
I've just done a couple of hours wandering around FMML, what a pity it isn't all neat and organized like RetouchPRO.
I'll be setting up some test codes for the points still in doubt. Get back to you later.
Rô Cameraken 03-01-2006, 07:31 PM Question 7.
Google “FilterMeister Code”. Apart from FilterMeisters own Web page you get straight back here.
Thanks to Stroker this thread IS THE best supply of FM info.
Ken. 5. A common method is to use a control and hide it. I'm pretty sure get() and put() are global. Arrays ala allocArray() are global. There are some named variables that are global, like i9 k0 str0, but I don't know too much about these.
I made up this little test routine (using ctl(0) as the run-once flag):
%ffp
ctl(0): CHECKBOX , "Initialize" , pos=(285,50), size=(40,12), Val = 1
ctl(1): PUSHBUTTON, "GO" , pos=(285,70), size=(40,12)
ForEveryTile:{
if (ctl(0)) { //Initialize the filter
i0 = 199; // init i0
put( 199, 0); // init i(0)
allocArray(0,1,0,0,1);
putArray(0,0,0,0,199); // init array()
setCtlVal(0,0); // end of initialize routine
}
//Normal tile processing
Info( "Values \ni0 is %i \nget(0) is %i \narray is %i", i0, get(0), getArray(0,0,0,0));
i0++; //increment i0
put(get(0)+1,0); //increment i(0)
putArray(0,0,0,0,getArray(0,0,0,0)+1); //increment array()
return true;
}
First time through all get set to 199 by the initialize routine, next time (pressing "GO") the i0 and array get incremented, but the get(0) just returns zero.
So, yes, i0 (up to i9) and arrays are global, the "put/get array" is not.
A truly run once structure is in the works. I think it is called OnFilterInit. I had been thinking that the OnFilterStart is what would do this function, however maybe combining this with an initialize flag I can get it to work like OnFilterInit. NancyJ 03-04-2006, 05:06 AM is it just me or do none of the examples in the tutorials compile? I managed to get the blur example to compile by changing 'true' to return true... but some of them are like for(y=0; y and then they go onto the next line so I cant fill in the blanks because I dont know what they should be Cameraken 03-04-2006, 06:28 AM Hi Nancy.
It’s nice to see you here.
I have never had a problem compiling any of the examples I have tried (I have not tried them all)
The ‘Border Code’ (Post 8) is straight from the manual.
I have tried most of the example source code which is downloaded with FilterMeister, and again, never had a problem.
One problem I have had occasionally is in the formatting of the code.
Try this.
Instead of copying and pasting straight to FM. First paste the code to Notepad. Then copy the code from Notepad and Paste this to FM.
If that does not help then can you give a specific example of code that is not compiling.
Ken NancyJ 03-04-2006, 08:04 AM This is straight out the manual - for blend and labelled example
%ffp
//This example blends the image with a mirrored version of itself
ctl(0): "Ratio",range=(0,255),val=128
ctl(1): combobox(vscroll),action=preview, color=#FFFFFF,fontcolor=#0000ff, size=(50,200),
text="Normal\nDissolve\nThreshold\nThreshold 2\nMultiply\nScreen\nOverlay\nSoft Light\nHard Light\nDodge\nBurn\nDarken\nLighten\nExclusion\nDifference\nNegDif 1\nNegDif 2\nSubtract\nAdd\nExpose",
val=0
ForEveryTile:
{
for (y=y_start; y
updateProgress(y,y_end);
for (x=x_start; x
for (z=0; z
pset(x, y, z, blend (src(x,y,z), src(X-x,Y-y,z) , z, ctl(1),ctl(0)) );
}}}
return true;
}
The for loops are incomplete
This example is one from the tutorials
%ffp
Category: "FM Tutorial"
Title: "Blur II"
Author: "Ilyich the Toad"
ctl[0]:"Blur &Width",range=(2,scaleFactor*X/2),val=3,pagesize=3,linesize=1
ctl[1]:"Blur &Height",range=(2,scaleFactor*Y/2),val=3,pagesize=3,linesize=1
ForEveryTile:
{
int kernelheight; int kernelwidth;
int xlook; int ylook;
int sum; int amount; int progress;
setCtlRange(0,2,scaleFactor*X/2); setCtlRange(1,2,scaleFactor*Y/2);
kernelheight=max(ctl(1)/scaleFactor, 1); //avoiding zero kernel on small preview
kernelwidth=max(ctl(0)/scaleFactor, 1); //avoiding zero kernel on small preview
progress=0;
// --------------------------------
// Blur - first pass (along X-axis)
// --------------------------------
for (y=0; y < Y; y++) {
if(updateProgress(progress,2*Y)) break;
progress++;
for (x=0; x < X; x++) {
for (z= 0; z < Z; z++) {
sum=0; amount=0;
for (xlook=0; xlook<kernelwidth; xlook++)
{
sum+= src((x+xlook-kernelwidth/2),y,z);
amount++;
}; //accumulate pixels in a raw
tset(x,y,z,sum/amount); //divide the sum onto kernel size
}
}
}
// ---------------------------------
// Blur - second pass (along Y-axis)
// ---------------------------------
for (y=0; y < Y; y++) {
if(updateProgress(progress, 2*Y)) break;
progress++;
for (x=0; x < X; x++) {
for (z= 0; z < Z; z++) {
sum=0; amount=0;
for (ylook=0; ylook<kernelheight; ylook++)
{
sum+= tget(x,(y+ylook-kernelheight/2),z);
amount++;
}; //accumulate pixels in a column
pset(x,y,z,sum/amount); //divide the sum onto kernel size
}
}
}
updateProgress(0, 100);
true;
}
It doesnt compile because the last line says 'true' instead of 'return true'. Hi, Nancy, good to see you around here.
Working with Filtermeister is a bit like trying to get into Deep Paint - very little organized information at all. You just have to keep reading around and trying to piece the stuff together.
Stroker and I, can probably help out with most things if you need.
This is the first one corrected:
%ffp
//This example blends the image with a mirrored version of itself
ctl(0): "Ratio",range=(0,255),val=128
ctl(1): combobox(vscroll),action=preview, color=#FFFFFF,fontcolor=#0000ff, size=(50,200),
text="Normal\nDissolve\nThreshold\nThreshold 2\nMultiply\nScreen\nOverlay\nSoft Light\nHard Light\nDodge\nBurn\nDarken\nLighten\nExclusion\nDifference\nNegDif 1\nNegDif 2\nSubtract\nAdd\nExpose",
val=0
ForEveryTile:
{
for (y=y_start; y<y_end; y++) {
updateProgress(y,y_end);
for (x=x_start; x<x_end; x++) {
for (z=0; z<Z; z++) {
pset(x, y, z, blend (src(x,y,z), src(X-x,Y-y,z) , z, ctl(1),ctl(0)) );
}}}
return true;
}
As for the second one - the final line should be "return true;" (which basically means that this part of the code is going to affect the output image)
Anything else you need, your wish is my command. :classic:
Rô Cameraken 03-05-2006, 09:40 AM Craig (Kraellin) requested a masking filter here
http://www.retouchpro.com/forums/showthread.php?t=12957
I can’t find any way to make this selection in one go.
The magic wand will select the painting quite easily using a setting of 10 and making several ‘Adds’
Using colour range or Hue/sat will not work.
Any Ideas?
Ken.
Ctl(0): "Red Min", Pos=(280,10),val=255,track
Ctl(1): "Red Max", Pos=(280,20),val=255,track
Ctl(2): "Green Min", Pos=(280,30),val=255,track
Ctl(3): "Green Max", Pos=(280,40),val=255,track
Ctl(4): "Blue Min", Pos=(280,50),val=255,track
Ctl(5): "Blue Max", Pos=(280,60),val=255,track
R: ctl(1) > ctl(0) & r > ctl(0) & r < ctl(1)? A=255 :r
G: ctl(3) > ctl(2) & g > ctl(2) & g < ctl(3)? A=255 :g
B: ctl(5) > ctl(4) & b > ctl(4) & b < ctl(5)? A=255 :b NancyJ 03-06-2006, 04:44 AM 'y_end', ofcourse, why didnt I think of that ;) It just seems strange that examples in the documentation dont work.
Something I noticed running the lab desat code Stroker posted was that it introduced a lot of compression artifacts - I assume thats because of the ForEveryTile rather than ForEveryPixel, I tried altering the code but then it became so slow. I've noticed that with other code examples, it takes quite a while to do and recreates the preview everytime you move a slider or press a button etc. NancyJ 03-06-2006, 06:29 AM Ok, I think I'm getting to grips with what does what... but how do you set the tile size? 'y_end', ofcourse, why didnt I think of that ;) It just seems strange that examples in the documentation dont work. Don't worry. you'll get used to it.
Something I noticed running the lab desat code Stroker posted was that it introduced a lot of compression artifactsSeems that you are using an image that has been through JPEG compression somewhere along the line.
JPG compression applies different parameters to Luminosity and Colours - basically using an 8 x 8 pixel base for Luminosity and 16 x 16 for Colours. Also, I believe, JGP will discard a lot more Colour information than Luminosity when you lower the quality. This is done because we perceive the artifacts much less in the colours.
Now, if you are going to make use of the (noisy) colour information to make your new Luminosity then the artifacts will be more visible.
I've noticed that with other code examples, it takes quite a while to do and recreates the preview everytime you move a slider or press a button etc.Yes, that's the (default) way it works. your code gets processed again every time you touch something. For a simple filter that's fine. When processing takes longer then it's a good idea to take some control over this.
but how do you set the tile size?Dunno, don't think you do. Never had to worry about this, seems that when you start using src(), pget(), pset() etc. the tile is just the whole image. As I understand it, this would only be a worry for a very big image in a very complex filter.
hope this helped,
Rô NancyJ 03-06-2006, 08:42 AM Just seems to me that if the tile is the whole image then the function is moot.
A lot of the examples I've seen start with ForEveryTile then for(z) for (y) for(x), which is equivalent to ForEveryPixel, surely? Well, yes, sortta, not quite.
Sweeping through the (preview) image is automatic and happens every time you alter anything.
As FM is doing this this, it will run parts of your code as identified by "handlers".
The name of the handler (good word to remember) tells you when it will be called.
OnFilterStart: Just once at the start
ForEveryTile: Once for each tile
ForEveryPixel: Once for each pixel
OnFilterEnd: Just once at the end
OnCtl(n): Every time you touch a control.
So, if you use ForEveryPixel, then you don't need to (well, "should not", actually) use any looping, 'cuz FM is already doing that for you. (Which is probably what happened to you - for every pixel, you code was looping through the whole tile.)
If the tile is the whole image, then OnFilterStart and ForEveryTile are just about the same thing.
As posted somewhere above, there is no handler for when your filter is first activated - the OnFilterStart runs once every time you touch something. If you want to initialize (as I did) then you need a flag. As in stroker's suggestion, you can use one of the pre-definied global integers (i0...i9) which are initalized as 0. Just test for 0, and set it to 1 after initializing the filter.
OnCtl(n) is used for administration of the dialog. You can test for n to discover which control was actioned.
A lot of the examples I've seen start with ForEveryTile then for(z) for (y) for(x), which is equivalent to ForEveryPixel, surely?For the simplest filters, yes, that works. Although I read, somewhere, that ForEveryPixel is not the recommended method.
Hope that explained it.
If you have any more doubts, please ask.
Rô Kraellin 03-30-2006, 01:34 PM well, true to my nature, i couldnt stand to wait and read through 100 pages of docs. so, i just jumped in and started editing :) i used the 'adjustsaturation.ffp' file that came with the program and remmed out the ctl(0) and ctl(1) and wrote my own for those based on what i was talking about in the last post. this was just a test. it worked :) .... sort of.
i dont understand all the rest of that code that came with that ffp, but my little test did take the image from 0 to 255 saturation using the first slider, instead of what was originally there. and it also seemed to move the other range, the 8-15 one, up and down a bit.
this was just a simple test and by no means what i'm fully after here, but ok. been a long while since i played with code.
i shld also mention that even though this desired filter is meant for grays, i do want to primarily have it work on 8 bit grays, not grayscale. fine if it also works on grayscale, but mostly i convert any true grayscale i'm working on into 8 bit grays anyways before actually working on it. so the filter shld primarily be for 8 bit rgb mode.
attached is an image of the pic i worked on and the code i adjusted. the adjusted code is highlighted in red. the rest is what was there in the filter to begin with.
craig ...so, here's my first question. when you compile an ffp you get the filter in a working form immediately. but, can you save these out as .8bf's and not have to compile them each time when you want to use one? You don't need to compile to .8bf's unless you intend to share with / sell to other people. Just like any software coding you can go "open source" and post source code for everyone, or compile to .8bf and distribute the executable.
If you are going to use the same filter many times then a .8bf is better, if you're doing a one-off then no need.
The license for creating .8bf's is around US$20.
Rô Kraellin 03-31-2006, 12:15 PM thanks Ro,
going on what you said, i hit the 'make' button to see what it would do, and you get a blurb about registering at filtermeister.com. so, ok :)
craig ....so, some questions on that code. what does 'track' do? When a slider is specified as "track" your code will be re-executed with every movement of the slider. For simple (i.e. quick) processes that works fine.
If your code ain't so fast, it won't be able to keep up with the slider and the preview will be choppy. In this case better without track, then the code will be executed only at the end of the slider movement.
also, in another piece of code, not stroker's piece here, i ran into 'rv', 'gv', and 'bv' as variables, i would think. but i couldnt find any definition for them in the docs. and they seem to be reserved variables. i tried changing them and got an error message that it basically didnt know what these were now that i changed them. so, what do they stand for and what do they do?I don't think they are reserved. Maybe you forget that all variables have to be declared before using. If you wish to change the variable's name, you must update the declaration too.
...and the docs just refuse to tell me what i want to know when i want to know it ;) :D That's why it's fun :D A Magical Mystery Learning Experience ;)
Or...just ask here! I'm sure Stroker and I will have some good answers.
Rô Kraellin 04-02-2006, 08:29 AM Ro,
thanks.
so, this line: "int r,g,b,Gray, rv,gv,bv;" is the line that defines-declares-initializes the variables? looks like it. so 'rv', 'gv', and 'bv' are just arbitrary variable names the person used in the code and not pre-set or reserved. ok.
then why are 'R', 'G' and 'B' not declared in some programs? and the same with 'r', 'g', 'b', 'x', and 'y'? are those reserved?
also, in going over stroker's last piece of code posted, the line: number=floor(workingfloat+0.5); has a variable that doesnt seem to be declared as well, 'floor'. or is this a function? lol. gotta do more reading.
i'm going to also assume in that code that 'float', up near the top, just under the 'int' line, means: 'make these next items floating point variables'. that right? the docs, or my ability to find things, seems to be woefully lacking here as far as definitions of things and what they do.
i do recognize a few things from having studied C briefly a few years back, but technical writing has always been my bane in learning things like this. the writer knows certain given things and seems to always think i know them also. heh...i dont. and that's fine if you're teaching others that have that background of basics already down pat, but again, i dont. i need 'filtermeister for dummies' :)
ah well, i'll keep looking.
oh, and i also did find out that 'standard' means simply, 'use the default control, the slider or scrollbar'. :)
craig Kraellin 04-02-2006, 08:54 AM ceil(u), floor(v)
These two functions take the term u respectively v and return the whole numbers directly above respectively
below the actual term.For example, in the number 5.3, the ceiling is equal to 6 and the floor is equal
to 5.Both functions return floating point values. ok, found 'floor'. seems to be a rounding off function, along with 'ceil'. floor rounds down, ceil rounds up, and both give these as floating point values.
so ok, i'm curious here; why did stroker use floating point values at all in that last piece of code? because of the division done in that one formula? and i'm completely lost as to the purpose of this line: avg=r*0.30 + g*0.59 + b*0.11; he seems to be weighting the r g b values differently, but why? why not just use the //avg=(r+g+b)/3; line which he remmed out?
craig Stroker 04-02-2006, 09:49 AM Real quick and I'm off to bed.
Integers are number without decimals places or fractional parts.
int a=1, b=10, c=257;
Floats and doubles can have decimals places.
float pi=3.14159;
I used floats in the last code because I needed percentages. You know, numbers between 0 and 1. This is to weight the sliders from 0% to 100%. I'll get into this later.
and i'm completely lost as to the purpose of this line: avg=r*0.30 + g*0.59 + b*0.11; he seems to be weighting the r g b values differently, but why? why not just use the //avg=(r+g+b)/3; line which he remmed out?
Personal preference. The way I weighted the RGB values is how Photoshop weights RGB for Luminosity as it uses it in the Luminosity blending mode. Kraellin 04-02-2006, 12:57 PM stroker,
ah, ok. int does equal integer then. wasnt sure if it was integer or initialize or something else. so, just adding 'int' tells the following items that they are now integer type variables. cool. and the same with 'float', only that makes them floating points. ok.
and yes, forgot about the percentages. i see that now. thanks :) sorry, it's been quite a while since i played with code.
seems a bit of an odd way to weight the values, but i'm guessing that has to do with how luminosity is stored in the various channels, so ok. it works, so cant argue much with that.
ok, i altered your code to make it 32 bands/ranges. i also upped the percentage values in the ctl(x) lines to (-1000,1000). this allows me to take most values to complete black or complete white rather than just percentages of the original. i mean, they're still percentages, but now they just go further. and yes, i changed the divide by 51 accordingly. with 16 bands i changed it to 16. with 32, i changed it to 8.
also, the 'standard' thing was causing the sliders to write over each other with this many sliders, so i changed back to the longhand way.
i've still got to figure out how to resize the interface window. it currently doesnt want to hold all my sliders in view when you first compile the code. they are there, but the window has to be opened up more to see them completely.
and, i think i saw a piece of code in the docs about a 'reset' button. gonna need that too. setting 32 sliders back to 0, each having a range of -1000 to 1000 is a bit of a task. so, gotta do that too.
this is cool stuff. i just posted a pic in the photo art forum i did with this new filter. it's in the 'red flower' section/post. i mean, why limit your creativity to just using other folk's plugins and programs.... make your own! very cool.
craig ....so, this line: "int r,g,b,Gray, rv,gv,bv;" is the line that defines-declares-initializes the variables?Yes to definition, not sure about initialization. Maybe the variables get initialized to 0 (zero) but I wouldn't count on that (ever ;) ).
then why are 'R', 'G' and 'B' not declared in some programs? and the same with 'r', 'g', 'b', 'x', and 'y'? are those reserved?Yes, exactly. R, G and B (capital letters - it does make a difference) are reserved variables represententing the R, G, B values when using FM in the Filter-Factory-type mode. In "programming" mode you would use src(x,y,z) to read the channel value and pset(x,y,z) to set it.
i'm going to also assume in that code that 'float', up near the
top, just under the 'int' line, means: 'make these next items floating point variables'. that right? You got it.
..the docs, ......, seems to be woefully lacking here as far as definitions of things and what they do.Yes, that's half the fun :rolleyes: :dizzy:
... so, just adding 'int' tells the following items that they are now integer type variables. cool. and the same with 'float', only that makes them floating points. ok.Not quite. Adding (int) and (float) does not change the type of variable. It defines what sort of arithmetic to use. With int all fractional results get thrown away. With float the arithmetic is precise but takes longer.
...seems a bit of an odd way to weight the values, but i'm guessing that has to do with how luminosity is stored in the various channels, ...No, actually it's exactly the other way round. These are the relative weights that our eyes attribute to the R, G, B channels. Thus if we set up this mix (30/59/11) of the three channels the result corresponds to the "luminosity" that we (humans) see. Like stroker said about Photoshop luminosity plus... JPG images have the Luminosity stored separate to the colours - guess the R/G/B percentages used!
Philosophical aside
This Luminosity stuff exists only in our heads. In Nature there is just a mixture of different wavelengths, nothing separated into greyscale / Colour information.
Our eyes are, mostly, sensitive to two basic wavelengths corresponding to (what we call) Green and Red. Why? Because, for a very long time, those are the two colours that really mattered as a question of life or death. The Blue information was always more hazy and gets included as a filler.
/Philosophical aside
Resize the dialog. Inlcude this and you'll have a nice big dialog.
OnFilterstart:{
setCtlPos(CTL_OK, 420,280, -1, -1);
setCtlPos(CTL_CANCEL, 460,280, -1, -1);
setCtlPos(CTL_PREVIEW, 5, 5,245,265);
setCtlPos(CTL_ZOOM, 200,285, 50, 10);
setCtlPos(CTL_PROGRESS, 5,285,185, 10);
return false;
}
Rô .....his secret for writing good manuals is, he NEVER writes them himself. he's a coder, not a writer and he just knows too much and would assume too much. so, he writes his programs and then finds someone who knows absolutely NOTHING about the program and has them write the manuals. this works a charm. the newbie has to learn what's there and learn it in his/her terms with his/her current knowledge of the program, which is nothing. so, they have to figure it out just like the end user is going to have to do. and as they do so, they simply write down what they find out. if they have questions, they ask him. it's the most brilliant technical writing technique i've ever heard of.Craig, this is your big chance! :) Go to the FM site (http://www.filtermeister.com/) , select Documents, then FilterMeister Wiki. When you're through writing the manual :dizzy: (or if you have any doubts :confused: ) just call us up. I've already corrected one of the entries there.
Rô Kraellin 04-03-2006, 12:33 AM Ro,
thank you.
i'd say more in response, but at the moment it's quite late and i wanted to post this for you all. all i can say is that it works. it's sloppy, amatuer, etc, but it does work! :D
%ffp
OnFilterstart:{
setDialogPos( true, 50, 50, 550, 200 ); // repositions and resizes dialog window
setDialogColor (RGB(225,56,56));
//setDialogPos( false, -1, -1, 320, 240 ); // centers dialog according to host client area
return true;
}
//OnFilterstart:{
// setCtlPos(CTL_OK, 420,280, -1, -1);
// setCtlPos(CTL_CANCEL, 460,280, -1, -1);
// setCtlPos(CTL_PREVIEW, 5, 5,175,150);
// setCtlPos(CTL_ZOOM, 200,285, 50, 10);
// setCtlPos(CTL_PROGRESS, 5,285,185, 10);
// return false;
// }
ctl(0):"0",size=(*,6),pos=(265,8),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(1):"8",size=(*,6),pos=(265,16),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(2):"16",size=(*,6),pos=(265,24),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(3):"24",size=(*,6),pos=(265,32),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(4):"32",size=(*,6),pos=(265,40),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(5):"40",size=(*,6),pos=(265,48),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(6):"48",size=(*,6),pos=(265,56),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(7):"56",size=(*,6),pos=(265,64),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(8):"64",size=(*,6),pos=(265,72),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(9):"72",size=(*,6),pos=(265,80),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(10):"80",size=(*,6),pos=(265,88),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(11):"88",size=(*,6),pos=(265,96),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(12):"96",size=(*,6),pos=(265,104),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(13):"104",size=(*,6),pos=(265,112),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(14):"112",size=(*,6),pos=(265,120),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(15):"120",size=(*,6),pos=(265,128),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(16):"128",size=(*,6),pos=(410,8),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(17):"136",size=(*,6),pos=(410,16),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(18):"144",size=(*,6),pos=(410,24),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(19):"152",size=(*,6),pos=(410,32),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(20):"160",size=(*,6),pos=(410,40),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(21):"168",size=(*,6),pos=(410,48),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(22):"176",size=(*,6),pos=(410,56),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(23):"184",size=(*,6),pos=(410,64),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(24):"192",size=(*,6),pos=(410,72),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(25):"200",size=(*,6),pos=(410,80),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(26):"208",size=(*,6),pos=(410,88),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(27):"216",size=(*,6),pos=(410,96),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(28):"224",size=(*,6),pos=(410,104),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(29):"232",size=(*,6),pos=(410,112),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(30):"240",size=(*,6),pos=(410,120),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(31):"248",size=(*,6),pos=(410,128),range=(-1000,1000),val=0,color=gray,fontcolor=white,track
ctl(72): PUSHBUTTON, "Reset all to 0",size=(47,14),pos=(484,160),val=0
ForEveryTile:{
int x,y,r,g,b,avg,final,number;
float workingfloat,weight1,weight2;
for (y=y_start; y<y_end; y++){
//if(updateProgress(y,y_end)) abort();
for (x=x_start; x<x_end; x++){
r=src(x,y,0);
g=src(x,y,1);
b=src(x,y,2);
avg=(r+g+b)/3;
//avg=r*0.30 + g*0.59 + b*0.11;
workingfloat=(float)avg/8.50;
// +0.5 for rounding
number=floor(workingfloat+0.5);
// again, +0.5 for rounding
weight1=(workingfloat+0.5)-number;
weight2=1.0 - weight1;
// checking along the way
//final=number*51;
//final=weight1*255;
//final=weight2*255;
// final weighted value
final=avg + ctl(number)*weight2 + ctl(number+1)*weight1;
// write the values back
pset(x,y,0,final);
pset(x,y,1,final);
pset(x,y,2,final);
{
if (ctl(72)) setCtlVal(0, 0),setCtlVal(1, 0),setCtlVal(2, 0),
setCtlVal(3, 0),setCtlVal(4, 0),setCtlVal(5, 0),setCtlVal(6, 0),
setCtlVal(7, 0),setCtlVal(8, 0),setCtlVal(9, 0),setCtlVal(10, 0),
setCtlVal(11, 0),setCtlVal(12, 0),setCtlVal(13, 0),setCtlVal(14, 0),
setCtlVal(15, 0),setCtlVal(16, 0),setCtlVal(17, 0),setCtlVal(18, 0),
setCtlVal(19, 0),setCtlVal(20, 0),setCtlVal(21, 0),setCtlVal(22, 0),
setCtlVal(23, 0),setCtlVal(24, 0),setCtlVal(25, 0),setCtlVal(26, 0),
setCtlVal(27, 0),setCtlVal(28, 0),setCtlVal(29, 0),setCtlVal(30, 0),
setCtlVal(31, 0),setCtlVal(72,0);
return false; }
}} // x y
return true;
} // for every pixel
thanks guys!
craig Stroker 04-04-2006, 02:38 PM Filter Meister uses structures. It took me awhile to wrap my head around these. ForEveryTile and ForEveryPixel are structures. I think of structures as sub-routines that are run in a particular order or when certain things happen.
For pushbuttons, you should use the OnCtl(n) structure. When ever you push a button or whatever, this structure will be run. Within the structure, check to see which button or control was messed with. Then do junk based on that.
OnCtl(n):{
if (n==72){ // reset button was pushed
int i;
for(i=0;i<72;i++){setCtlVal(i, 0);} // loop and reset
}// end reset all to 0
return false;
}// end on control Kraellin 04-05-2006, 12:10 AM stroker,
thanks.
we used to call what you're calling 'structures', 'functions'. but yes, they are sort of sub-routines or algorythms(sp?). i used what i used there because that's the example i found in the docs and code stuff. it just said 'if (ctl(72) { '. and then followed it with a 'for' or another 'if' (i forget). i didnt know how to do the 'for', so i just did it up in longhand. but yours looks pretty simple. i did see the 'onctl' mentioned, but it wasnt mentioned with pushbuttons, so i just went with the code example.
now, on to the 'for'. you put: "for(i=0;i<72;i++){setCtlVal(i, 0);} // loop and reset" . i understand that it's a loop. that's fine. what i dont understand is the syntax of it. you declared 'i'. ok. and in the 'for' statement you did 'i=0;' . ok, i get that. and i understand the last part, but i dont get the 'i<72;i++)', particularly with it being in conjunction with the i=0. if the whole is a loop, wouldnt the i be reset to 0 each time around in the loop? i get the i is going to not hit 72 (< = less than) and i get that i++ = increment i by 1 each time aruond. but the way i read that code it looks like the 'for' loops i=0 and i<72 and increment i by 1, all on every loop. and if i = 0 each time, then i is never going to reach 31 (the highest n in my ctl's). but that's just the way i understand it based on older codes and what they did. and i can certainly understand that that may not be the case here.
anyways, i can try it and see. but i need to understand how these things work with each other, the syntax and so on.
also, dont the braces { } more or less set a piece of code apart, sort of like the old if-then. if the 'if' tests true you'd jump to a new line. if it was false, you'd simply bypass the rest of the code in the braces. i assume that's still true here (only without the 'then' now).
and what stops the 'for' from looping further, the <72 ? i seem to recall back in the old 8 bit, BASIC days that a 'for' was followed by something the same way the if was always followed by a 'then', but i forget what it was. 'while'? so, what breaks it now? how does the loop know when it's finished?
craig we used to call what you're calling 'structures', 'functions'. but yes, they are sort of sub-routines or algorythms(sp?). Not really.
The correct term is "handler", which gives a good idea of what it is.
This is not ordinary linear (start here - end there) programming, this is more "object orientated". Which means that each handler gets called in response to something happening.
The easiest handler to understand is OnCtrl(n), this gets invoked whenever you fiddle with a control - other than that it doesn't run.
Unfortunately, unless I missed something, FM does not have any provision for sub-routines or functions.
now, on to the 'for'. you put: "for(i=0;i<72;i++){setCtlVal(i, 0);} // loop and reset" . i understand that it's a loop. that's fine. what i dont understand is the syntax of it....but the way i read that code Aha! But that isn't code. I can see what you're saying though. The three parts in the brackets are not code lines, it's just a convenient (although it seems, slightly confusing) way of grouping all the parameters of the "for" loop:
a) Start from zero;
b) Do while less than 72;
c) Increment by one on each pass
also, dont the braces { } more or less set a piece of code apart, sort of like the old if-then. if the 'if' tests true you'd jump to a new line. if it was false, you'd simply bypass the rest of the code in the braces. i assume that's still true here (only without the 'then' now).Braces serve to group various lines of code as if it were one. Normally with an "if" or "for" command you will want to group some code. Actually I find the exception, where there is only one line, more confusing - stroker's code..
for(i=0;i<72;i++){setCtlVal(i, 0);}can be written without the braces..
for(i=0;i<72;i++) setCtlVal(i, 0);without problem. Although in the middle of a page of code you'll have to look carefully - especially if it isn't properly indented.
and what stops the 'for' from looping further, the <72 ? i seem to recall back in the old 8 bit, BASIC days that a 'for' was followed by something the same way the if was always followed by a 'then', but i forget what it was. 'while'? so, what breaks it now? how does the loop know when it's finished?see a), b), c) above. It's all rolled into the "for" loop parameters.
Hope that cleared it up.
Any questions, just fire away!
Rô Kraellin 04-05-2006, 12:18 PM Ro,
thanks.
ok, grouped parameters. i can live with that. thus, it is the <72 that defines the end of the loop. and the ';' is simply demarking the end of a given parameter, but like you said, it's not linear. ok. so, the handler simply understands all this and handles things accordingly. would it matter the order then of the various parameters? is there a specified syntax to that? if it's not linear, i would think it wouldnt matter, but then again, if the handler is set up to look for certain things first, then it would.
so are 'if's the same way as the 'for's?
craig ...would it matter the order then of the various parameters? is there a specified syntax to that?Order does matter. Initial - Ending condition - Increment. As to syntax, I usually stick to the simple stuff (like (i=0;i<72;i++)) - I don't know how far you can complicate the parameters.
so are 'if's the same way as the 'for's?In general structure, yes. After the "If" there's a condition* inside the brackets, and after that one line of code or various lines enclosed in braces.
After the "If" code is all finished you can optionally add an "Else" section.
*something that returns a true/false value
Rô Stroker 04-05-2006, 04:27 PM There are shortcuts to the basic math functions.
i=i+1
is the same as
i++
This is why you usually see i++ in the for loops.
i=i+j
is the same as
i+=j
for( initial state ; conditional ; incremental )
{
// statements
}
Like Ro said.
In the conditional, using < or <= may make a difference. I haven't completely figured this out. Sometimes a loop will go one beyond and sometimes it will behave just fine. Even in BASIC, I've had to break for/next loops early because of One Beyond Syndrome.
I think FM does support do/while and while/wend loops. I avoid them because it's easy for me to plant a logic bomb when I use them. I can handle logic bombs, but these ones throw me for a... loop. ~snicker~
Indenting - ugh! I was never one for proper indenting because I have the hardest time reading code with indents. Once in a great while I might indent properly if my nested conditionals get uber hairy. I'm trying to be better about it. Honestly.
Crud. I lost my train of thought. Kraellin 04-05-2006, 11:10 PM thanks stroker. still studying, but all that does help.
also, anyone know if FM is still being developed? would love to see a greater zoom and an increase in ctl numbers (docs say it's currently limited to 60).
craig Stroker 04-06-2006, 12:11 AM FM is still being developed. Alex and Harald, I believe.
- zooming in
- user defined functions
- dll linking
- Perlin Noise function
And some other things I can't remember right now.
I think the limit on controls is more than 60. Like 0 to 255. .....anyone know if FM is still being developed? Go to the FM home page http://www.filtermeister.com/ , select "Documents", then "FilterMeister Wiki" then "New in FM 1.0". There you'll find a (long) list of developments. Maybe interesting reading.
Rô Kraellin 04-06-2006, 12:15 PM thanks guys. good to know it's still being worked on.
that 'what's new' page is actually what's in the version i'm using. the setZoom does work. tried it out, but functionally, it doesnt really seem get anything more than what i was getting before before using setZoom. they said '200% larger preview' on the what's new, but i dont really see it, unless it means that what exists now is 200% over what was possible in the earlier versions, which i never had. but it's not a 200% of original image. what i'd love to see is 200% of the original image. then again, i may have implemented it wrong or be looking at it incorrectly.
i tried it like they said, but wasnt quite sure where to put the -888.
setZoom(ctl(40));
ctl(40): "Preview Zoom",Range=(-888,16),pos=(305,330)
this did work. it compiled and i got the new 'zoom preview' with a slider to magnify, but it, at the largest size, only takes it to a 100% view.
but again, i'm probably just implementing it incorrectly or thinking about it incorrectly.
craig Kraellin 05-03-2006, 10:06 PM guys,
a question here about FM. does it have the capability to do a color pick from the preview window and if so, could you steer me in that direction? you know, like the eye dropper tool, pick a color and tell you its values or assign it to something.
craig Craig,
You can use the chooseColor command, see here for details (http://www.filtermeister.com/wiki/index.php?page=chooseColor) .
Good luck,
Rô Kraellin 05-04-2006, 09:59 AM thanks Ro. that does look like what i was after.
craig ParkerF1 05-05-2006, 09:00 AM well DAMN. I've got to day this... As a very new member of RetouchPRO and a technology-minded, vb script reading digital arts freak... you guys completely amaze me in how much you're willing to share on this forum. Quality... love it. My ears are smoking btw.
:bow:
Rob ParkerF1, nice to see you around here. Have you already delved into FilterMeister?
"technology-minded, vb script reading digital arts freak" - seems like you're in the right place.
Folks of FM world. This thread is getting too long to be really useful to anybody trying to get the information out easily.
Over the weekend I'll be chopping this thread into smaller chunks, something like:
FM Basic information;
FM Colour conversion;
FM Sample filters
+ any other suggestions?
If the interest continues maybe we'll get ourselves our own little sub-forum - and tomorrow the world :dizzy: Cameraken 05-05-2006, 06:38 PM Hi Rô.
Are you trying to make FM easy? :spchless:
Maybe an FM Art Chunk? I think this would be popular. And it’s an area we haven’t really touched on yet. Maybe ParkerF1 can contribute.
If this has to be split then I can think of no-one more capable than yourself. I am sure you will do it correctly.
But really this question can only be answered by Stroker. Without Stroker’s fantastic contributions this thread would not have become such a wonderful resource of FM info.
And they thought FM was just for geeks.
Ken. Stroker 05-06-2006, 03:04 AM Whatever byRo or whomever wants to do, I'm cool. If someone sets something up, I'm sure I'll contribute content. Ever since my last stretch with Tech-Slop, I haven't been much of a mood to do big organization type stuff (which is why I wanted a wiki, much looser for my sloppy ways). ParkerF1 05-08-2006, 06:39 AM Nope, u guys just turned me on to it :shocked: :bigthmb:
I haven't had time to dive into it just yet. The 1 yr old at home sucks every ounce of time out of my evenings! I don't think I would even bother if it hadn't been for what you've already done here... I honestly am blown away by the generosity here. this forum is second to none. | |