Joe Maller: FXScript Reference: Building Joe's LevelsHow a levels filter works, also how to build one for Final Cut Pro using FXScript and FXBuilder. |
||||||||||||||||||||||||||||||
Visit the New FXScript Reference and Joe's Filters sites. These pages will be phased out soon and may already be out of date. This page describes the FXScript concepts behind Joe's Levels. If you're looking for the page about how to use the filter, click here. OverviewJoe's Levels was the filter that got it all started. I could not make sense of the Levels filter in Final Cut Pro, even though Levels is my favorite adjustment in Photoshop. I did spend some time trying to figure out what the filter was doing, and realized that it wasn't very efficient, needing to be applied several times to create an effect that should be possible in one adjustment. At first, I thought I might be able to simply change the inputs and somehow end up with a working Levels filter. I had modified the default setting on a few other Final Cut Pro filters, but I'd never dealt with the actual code section before and hoped I wouldn't have to. Of course, changing inputs didn't work. I blindly changed a few numbers here and there but only succeeded in breaking the filter completely. After a few hours things only got worse. Out of frustration I shelved the idea somewhere in the back of my mind and forgot about it. A few months later, and I swear this happened, I was falling asleep when the solution came to me. I don't remember exactly what it was, but in three hours I had a complete working Levels filter. Better yet, I even understood why it worked. The doorway to FXScript had been kicked open. Credit where dueSeveral portions of this filter originated with the Levels filter included with Final Cut Pro. Eventually I rewrote it completely and created my own Levels operation from scratch for Building Joe's Threshold, but many of the variable names and routines from the original filter have survived into this one. It's easier to credit sources than to try and hide them. CLUT is not a dirty wordThe acronym CLUT stands for Color Look Up Table. Most of my past experiences with CLUTs have referred to the palette used by a GIF file or Director movie. Naming the main adjustment array clut[256] is a leftover from the original Final Cut Pro adjustment filter, many of the included FXScript use variable names based on variations of the LUT acronym. This and all 8-bit Levels adjustments work by assuming an image has 256 values of gray. The LevelMap function at the end of Joe's Levels will use the values in clut[256] to modify the values in the final image. Arrays are discussed on the FXScript Variables page. All FXScript arrays are filled with zeros by default until some other value is stored. Another look up table array is LinearRamp. This is a pre-defined 256 value array which passes unchanged images through the levelmap function. Dissecting LinearRamp shows that it is composed of 256 incremental decimal values between zero and one, as discussed on the FXScripts Constants page and illustrated by the Joe's LinearRamp Tester exploration filter. (The Final Cut Pro manual wrongly states that it contains values between 0 and 255.) Remember that computers start counting at zero, so the first element of the array is labeled 0 and the last element is labelled 255. Understanding the values in LinearRamp helped me to understand how the LevelMap function worked. A Levels adjustment works by creating a Clut that is not a perfect Ramp from zero to one. Below are two simplified sets of numbers representing LinearRamp and a Levels-adjusted ramp showing the result of changing the Input Black setting (in this case to 3). The total value scale is then stretched through the remaining spaces. LinearRamp:
Adjusted clut[10]:
The adjusted decimal values are determined by mulitplying the current position in the scaled range of values by the total possible number of values. Since the first three places are ramped to zero, there are seven values remaining. The first value is 1/7 * 10 = 1.42, this works the same as it did in LinearRamp: 1/10 * 10 = 1. That is the whole concept of a levels adjustment. Almost everything in this filter is used to build the adjustment clut, once those 256 levels are defined, the rest is easy. LoopingThis filter uses several For/Next loops to generate incremental variables. Below is an example loop:
The above loop will repeat 5 times, and each loop would increase the x variable by one. After one loop, Input White and BlackFirst the script sets all the values above the input White setting to 1. A for/next loop steps through all the values from Input White up to 255 and sets the corresponding array index to 1.
At this step, essentially the image has been thresholded to the Input White value. All other elements of the The next step is to determine how many spaces in the array will be used to represent the curve from black to white. This is accomplished using the following if/else statement
It's not possible for GammaThis is the part that initially confused me the most. Without gamma, image values are ramped straight from white to black. Gamma bends that line towards black or white, making it possible to adjust the middle values in an image without affecting the extremes. Here are three diagrams showing how gamma will affect the values in the adjustment clut:
If you wanted to generate graphs like that, the formula is: x = y(gamma) The graph can also be visualized with Photoshop's Curves adjustment, which plainly shows input values and output values. The next step is probably the most important because this is where the adjustment clut will be filled with the adjusted range of values.
The The for/next loop counts from That fractional value is then used as the base number of the Output White and BlackOutput White and black define the darkest and lightest possible values in the image. Output settings use compound operators to affect every index in the adjustment clut in one operation. (Compound Operators are discussed at the bottom of the FXScript Variables page.) First, the script multiplies every item in the adjustment clut by the difference between outputWhite and outputBlack:
This is the first time an operation has increased values in the adjustment clut above one. The maximum possible number is 255, so now the adjustment clut is populated with values between 0 and 255. Before this section ends, the values will be brought back down between zero and one. Next the script adds the value of
This step increases the bottommost value to equal Finally the script divides the entire adjustment clut by 255 (the maximum possible value. This turns everything in the adjustment clut into a fractional value of 255, all of which are less than one. Math can be really cool.
RGB or YUVOne side effect of RGB levels is that colors can appear more saturated. This is a natural side effect of compressing channel information. Applying levels only to the Y of YUV makes it easy to affect only the luminance of the original image while preserving the separate color information. More information about YUV is available on the RGB and YUV Color page. This section of the filter uses the same kind of paranoid PixelFormat checks as appear in Building Joe's Color Glow. I'm going to skip the color conversion statements here and focus on the actual The end of this filter wrapped in a big if/else statement. The first section applies the adjustment clut as RGB, the second applies it to the Y of YUV.
There is a series of color conversion statements here which move the source image into a new image buffer called
The If the user has selected Y only (luminance), the following LevelMap() command is run, after another set of pixelFormat checks and conversions.
The filter ends with one more format conversion, to make sure ConclusionThe complete FXScript source code for Joe's Levels is included with the paid version of Joe's Filters. |
The FXScript ReferenceFXScripting Joe's FiltersJoe's Filters for Final Cut Pro Building Joe's Minimum Maximum Joe's FXScript ExplorersJoe's Debug and Explore Filters Joe's 3x3 Convolve Matrix Tester Joe's 3x3 Matrix Values Tester Other FCP Stuff
Film & VideoRecording the sound of PhotographyProjectsFinal Cut ProDesignWRITINGSite Notes Archive (weblog) Web ResourcesAbout Joe MallerPast Home Pages Etc.Search joemaller.comContact Me
|
|||||||||||||||||||||||||||||