Home | Download | Documents | Tips & Tutorials | Code Library | Help / User Group | Order

Getting Started with FilterMeister

Step 3 - Creating A Filter



Now it's time to create your first custom-made filter.  Create or open a test image in RGB mode, invoke FM, and enter Edit Mode as described in Step 2.
With an empty source edit window, go ahead and press the  button. What!?  All the check boxes, radio buttons, and scroll bars have disappeared! Congratulations: You have just created a Null (or Identity) filter that returns the input image unchanged and has no user controls.

 

Now proceed to create a more useful filter.  In this lesson, we will create a simple "RGB Intensity Modulator" filter that allows the user to control the relative intensities of the red, green, and blue channels in an image.
 
**TIP** If you are too impatient to type in the following examples by hand, just use cut-and-paste to transfer the code from this lesson into the source edit window.

First, type the following in the source edit window:
 
%ffp

This informs the compiler that it will be compiling a program written in the Filter Factory Plus (FF+) language.
 
**TIP** FM can compile filter programs written in several different source languages, including the original Adobe Filter Factory (FF) language, the Filter Factory Wizard (FFW) language, the extended Filter Factory Plus (FF+) language, and the full FilterMeister language (FML). In general, FM can automatically determine which language to compile, but sometimes it can be fooled.  It is good practice to tell FM explicitly which language to use by prefacing your code with "%RGB" (for Filter Factory code), "%FFW" (for Filter Factory Wizard code), "%FFP" (for Filter Factory Plus code), or "%FML" (for FilterMeister Language code).

Our new filter will use three scroll bar controls to allow the user to adjust the intensity of each color channel individually.  Create these controls by entering the following code and pressing  :
%ffp 

ctl(0):"Red intensity" 
ctl(1):"Green intensity" 
ctl(2):"Blue intensity"

**TIP** Periodically save your work by pressing  and saving your current source code as a *.ffp file.  You can later retrieve the source code by pressing  and selecting the saved *.ffp file.

The filter dialog box should now have three slider bars with the appropriate labels.  Test the action of these by moving the slider control with your mouse.  Note that the value of each slider bar is displayed to the right.  The minimum value you can set is 0; the maximum value is 255.  Since we want the intensity to represent a percentage of the original value of each channel, the range of each slider bar should really be 0 to 100, not 0 to 255.  Change the ranges by adding a "range" subkey to each control:
 
%ffp 

ctl(0):"Red intensity",range=(0,100)
ctl(1):"Green intensity",range=(0,100)
ctl(2):"Blue intensity",range=(0,100)

Press  and verify that each control now ranges from 0 to 100.

Okay, the slider bars now work, but the filter still doesn't do anything!  We need to tell the compiler what operations to perform on each channel.  Add the following formulas to define the result of the R (red), G (green), and B (blue) channels, respectively.
 
%ffp 

ctl(0):"Red intensity",range=(0,100) 
ctl(1):"Green intensity",range=(0,100) 
ctl(2):"Blue intensity",range=(0,100) 

R:r*ctl(0)/100 
G:g*ctl(1)/100 
B:b*ctl(2)/100

For example, the formula R:r*ctl(0)/100 means: Take the value of the red pixel (r) in the input image, multiply it by the value of control 0, and divide the result by 100 (to convert the value of the control to a percentage).  Assign the result to the corresponding red pixel in the output image (R).

Press  and then experiment with the three controls to see the result.  The first thing you'll probably notice is that the preview image goes black immediately after you press  .  This is because the control values are initially set to 0%.  If you would rather not have your image go black, then set the control values initially to 100%.  This is easily accomplished by adding a "val" subkey to each control definition:
%ffp 

ctl(0):"Red intensity",range=(0,100),val=100
ctl(1):"Green intensity",range=(0,100),val=100
ctl(2):"Blue intensity",range=(0,100),val=100

R:r*ctl(0)/100 
G:g*ctl(1)/100 
B:b*ctl(2)/100 

Press  and all three controls should now be initialized to 100.

 

Now for the next refinement.  So far, the user can set each channel to a percentage of the original value between 0% and 100%.  This allows the user to darken any given channel, but not to brighten it.  We can give the user more control by allowing the user to amplify each channel beyond 100%.  So let's change the range of each control to 0 through 200:

But remember that the intensity value of each channel pixel must lie in the range 0 to 255.  What happens if we try to amplify the value of some pixel beyond 255?  Will the pixel value "wrap" around to the low end of the range, thus actually *darkening* the pixel rather than brightening it?  Yes, it will, which is probably not the desired behavior.  A more acceptable solution is to "clamp" the value of a pixel to 255 if we try to increase it beyond 255.  We could accomplish this, for example, by using the formula:

This formula says: If the computed value is greater than 255, set the result to 255; otherwise, use the computed value itself.

However, this elaborate code is unnecessary!  FilterMeister automatically clamps output channel values to 255 (if the result would exceed 255) or to 0 (if the result would be negative).  So the only code we need is:
 
%ffp 

ctl(0):"Red intensity",range=(0,200),val=100 
ctl(1):"Green intensity",range=(0,200),val=100 
ctl(2):"Blue intensity",range=(0,200),val=100 

R:r*ctl(0)/100 
G:g*ctl(1)/100 
B:b*ctl(2)/100 

Compile this code and verify that you can brighten each color channel without producing "dark" artifacts due to wraparound.

Now,  for another refinement.  Note that the formula for each channel is identical except for the name of the input pixel (r, g, or b) and the index of the corresponding control (0, 1, or 2). 

Recall that the special variable 'c' means the same as 'r', 'g', or 'b', depending on which channel is being processed.  Also remember that the variable 'z' is set to 0, 1, or 2 when the red, green, or blue channel, respectively, is being processed.  So we can recode the channel formulas with identical expressions as follows:

 

Finally, note that the FF+ language allows you to specify a list of channels to the left of the colon (:), which means that the formula on the right is to be used for each channel in the list in turn (and in the designated order).  So we can simplify our code further to:

%ffp 

ctl(0):"Red intensity",range=(0,200),val=100 
ctl(1):"Green intensity",range=(0,200),val=100 
ctl(2):"Blue intensity",range=(0,200),val=100 

R,G,B:c*ctl(z)/100 

This may not seem like a big deal here, but it can save a lot of typing (or cutting-and-pasting) when used with more complex code.
 
 


Go to Step 4 - Customizing the Filter Dialog
 

 

Home | Download | Documents | Tips & Tutorials | Code Library | Help / User Group | Order