Joe Maller: FXScript Reference: Building Joe's Minimum MaximumThe FXScript concepts behind my minimum maximum filter for Final Cut Pro
Joe's Minimum Maximum recreates a grayscale Erode/Dissolve effect, similar to Photoshop's Minimum and Maximum filters. Normally this would be accomplished with a logical matrix operation, but FXScript doesn't seem to include one. The workaround is to nudge and composite the image using the logical composite modes Lighten and Darken. These two modes are logical, which is why they tend to look synthetic and unnatural:
Lighten: If Pixel A is lighter than Pixel B, then keep Pixel A, else keep pixel B.
Darken: If Pixel A is darker than Pixel B, then keep Pixel A, else keep pixel B.
To preview the effect, duplicate a layer in Photoshop, nudge it up and apply as Lighten or Darken. Repeat with the remaining three directions, finishing one direction before the perpendicular.
This is the most processor-intensive filter I've written. The recursive looping means four composite operations will be executed for each iteration. With high numbers Final Cut Pro gets really bogged down.
This filter also gave me the chance to implement something I've been asking for in Photoshop for years, Minimum and Maximum as one filter with a positive and negative slider.
The Missing Logical Matrix
When I started looking into matrix operations while building Joe's RGB Desaturate and Joe's Radial Desaturate, I learned there was another kind matrix process which used logic to generate the resulting pixel.
Matrix operations consider the eight pixels around the target pixel to generate their effects. Minimum and Maximum are Photoshop's names for processes called Erode and Dilate. Since I don't have a computer science degree, the names Minimum and Maximum were most familiar to me, and probably to most other Final Cut Pro users.
Erode/Minimum and Dilate/Maximum work by choosing either the lightest or darkest value of the target pixel and the eight pixels around it and then replacing the entire matrix with that color.
Clarity instead of Loops
This script could have used a nested loop, but instead places four directional offsets in sequence. It's longer, but easy to take apart. The script starts out by moving the source image into xbuffer2:
Next the main loop starts. This loop repeats to whatever is set in the slider Shifter. Using
Below is the first iteration of the four directional offsets. The xoff and yoff variables will be used for the direction of the offset. These are something of a leftover from the first two-loop version of the script. The first line multiplies each variable by zero, setting them both to zero. Next the script assigns a direction by adding 1 to xoff.
The 1 after the target and destination image buffers is a switch to turn edge repeating on or off. I didn't notice a difference but decided it was safer to generate pixels at the edges then to risk the possibility that Final Cut Pro might freak out on empty space.
The next step is to composite the nudged image. The script evaluates
This directional iteration ends by restoring xbuffer with the new contents of dest:
The next three loops are identical with only the direction of the offset changing. My standard set of compositing controls finish the filter, allowing the complete effect to be composited back onto the original image.
While it would be more efficient and elegant for this filter to use a nested loop, a few extra lines of code are not what is slowing this down. If Apple would include a logical matrix operator in the FXScript syntax the same effect could be recreated in probably 1/100th the time this filter requires. From everything I've read, logical Matrix operations are simple and not processor-intensive, but for now, this is good enough. If you think it's slow on a G4, I wrote and tested it on a 350mhz G3 and a 233mhz G3 PowerBook, ugh.
The FXScript Reference
FXScripting Joe's Filters
Joe's FXScript Explorers
Other FCP Stuff
Film & Video
Final Cut Pro
Site Notes Archive (weblog)
About Joe Maller
Past Home Pages Etc.