Joe Maller: FXScript Reference: Variables

Information about how FXScript uses variables while scripting Final Cut Pro.

Variables are little chunks of memory where a script can store information. The information in a variable can be changed or replaced when the script is running.

Defining FXScript Variables

Defining variables in FXScript is a two part process. Each variable must first be declared before it can be assigned a value. A simple variable declaration looks like this:

float VariableName;
VariableName = 5 ;

Each type of data also gets it's own type of variable in FXScript. Multiple variables of the same type can be declared together. Declaring multiple variables might look like this:

float var1, var2, var3;
string dog, cat, lizard;

All six of those still need to have values assigned to them.

FXScript will choke if a script tries to put one type of data into a different type of variable. I didn't have much success moving or converting data between variables, so I try sort out my data types early in the script.

Variables are usually defined in the code section of a script, but the manual states that a variable can be defined before the code section to remain static across frames. Besides inputs, I didn't come across any of those. All code section variables are reset between frames.

FXScript Data Types

The following is a list of FXScript's ten data classifications, followed by example code for how to define a variable of that type. Each example shows the variable being defined as varName:

  • Floating Point

    These are just simple, common numbers. All "floating point" means is the number of digits on the right side of the decimal point is unlimited.

    float varName;

  • Point

    Two-dimensional point coordinates, these usually appear as {x, y}.

    point varName;

    The x and y values of a point variable can be directly accessed or assigned using varName.x and varName.y.

  • Point3d

    I didn't use these, the book described them as "three-dimensional floating point coordinates." I imagine that means something like {x, y, x}.

    point3d varName;

  • Image

    These can be used as additional image buffers, places to store a frame or image during execution of the script. Images need to be declared with their size: [width][height]. Creating image buffers is discussed further down this page.

    Image varName[720][480]

  • Region

    I didn't use these, the book describes them as arbitrarily shaped regions.

    region varName;

  • String

    Strings are text, meant for people to see. String values are described in quotes.

    string varName;

  • Color

    RGB colors, stored as sets of four numbers between 0 and 255 which correspond to: {alpha, R, G, B}

    color varName;

  • YUVcolor

    Similar to the Color data type, but uses the YUV color space. {alpha, Y, U, V}. YUV is the native format for video. Y is Luminance and U and V are color channels.

    YUVcolor varName;

  • Clip

    I didn't use this, the book says it stores an entire clip. I'm not clear how this differs from an image buffer like dest, src1 or src2, I think it might be able to be offset in time relative to the filtered clip.

    clip varName;

  • Value

    These are specifically set aside for the declaring line of a subroutine. These allow scripts to pass data into a subroutine.

Colors

Every color is defined as having four composite values. For RGB colors, the values are alpha, red, green and blue. For YUV, Y (luminance), U (Cb, red to yellow) and V (Cr, blue to yellow). An RGB image can be defined like this:

RGBColor1 = {255, 255, 128, 0}

Once the color is defined, it's composite values can be addressed attaching the color abbreviation to the end of the color's variable name like this:

RGBColor1.r is equal to 255
RGBColor1.g is equal to 128
RGBColor1.b is equal to 0

If the color was YUV, then use YUVcolor.y, YUVcolor.u, and YUVcolor.v. Values can also be set using this notation as well. If a script included the statement RGBColor1.b = 255 after the color was previously defined, then only the blue value would be adjusted. RGBColor1 is now {255, 255, 128, 255}.

This page contains more information about RGB and YUV Color in FXScript and Final Cut Pro.

Image Buffers

FXScript stores video frame data in image buffers.

There are several predefined image buffers in the FXScript language:

  • dest
    This is the predefined output buffer for sending filter or transition results back to Final Cut Pro. Whatever is in the dest image buffer at the end of the FXScript is what will be seen in the viewer.
  • src1
    This is the image the FXScript is applied to. src1 is also the incoming (first) clip in a transition. This is the top thumbnail in the FXBuilder input controls tab.
  • src2
    This is the outgoing (second) clip in a Transition. src2 is the bottom thumbnail in the FXBuilder Input Controls tab. scr2 is only for Transitions and is not available for Filters or Generators.

Scripts do not automatically display anything without being told to, so juggling image buffers is essential to seeing any scripted effects. If a script never assigns any image data to dest, Final Cut Pro freaks out in unpleasant ways. A quick and simple way to avoid that from happening is to include this line somewhere in the script:

dest = src1

That will tell FXScript that the contents of dest now equal the contents of src1.

Scripts are not limited to these two or three image buffers. The code to define an additional image buffer looks like this (must appear in the code section of the script):

image xbuffer[w][h]

The w and h variables refer to the width and height of the image. This syntax is actually a two-dimensional array, which is discussed further down this page. The height and width values can be discovered (preferrable to hard-coding) with the following lines, which needs to come before the image buffer declaration:

float w, h;
dimensionsOf(dest, w, h);

The first line declare the variables w and h as simple numeric (floating point) variables. The second line uses the DinemsionsOf() utility to determine the dimensions of dest and stores the width and height in the w and h variables. These need to appear before the image variable declaration because the values returned will be used to create the image buffer.

The newly declared image variable xbuffer can now be used in place of any of the built in image buffers for storing or moving images within a script.

Compound Operators

Most of mathematical operators are very simple or are covered in the manual, but compound operators only get a passing mention. I had never seen these before and wanted to know what they were since they figured prominently into the mathworks I adapted for Joe's Levels.

Basically, compound operators are shorthand for longer statements. Here is a chart of the most common compound operators (+=, -=, *=, /=) and their equivalent definitions:

x += y x = x + y
x -= y x = x - y
x *= y x = x * y
x /= y x = x / y

Simple Arrays

Arrays allow sets of data to be stored in a single variable. Simple arrays are sort of like a list or a stack of drawers. Any type of data can be stored in an array as long as the data-type declaration is correct.

The notation for a floating point array with 4 entries looks like this:

float compass[4]

The contents of that array could be assigned like this:

box [0] = 1
box [1] = 2
box [2] = 3
box [3] = 4

The complete array could also be defined like this:

box = {1, 2, 3, 4}

Other types of arrays could be points, strings or colors, each defined as follows:

point parray[4]

string strArray[10]

color crayons[64]

Arrays are a bit confusing about how they count. Since computers start counting at zero, the first position in an array is zero instead of one. This makes zero number one, and my head hurt. The term "off-by-one-error" has become tech jargon just to deal with this headache. (You do get used to it eventually, I'm just not sure if I still have ten toes or not.)

Multidimensional Arrays

These are not nearly as complicated as they sound. A multidimensional array is sort of like two or more stacks of drawers side by side. Think of a two dimensional array as a grid of squares and a three dimensional array as a stack of boxes (beyond three dimensions I run out of metaphors).

The image buffers described earlier on this page are examples of multidimensional arrays, height and width being the two dimensions of the array.

The notation for a multidimensional array looks like this:

float neo[3][3]

That code will create a 3x3 grid named neo. If the contents of neo looked like a telephone keypad it could described it as follows:

neo [3] [3]
   1       2       3      [0][0] [0][1] [0][2]
4 5 6 [1][0] [1][1] [1][2]
7 8 9 [2][0] [2][1] [2][2]

Another way of showing that is to use curly braces like on the simple array:

neo = {1, 2, 3, 4, 5, 6, 7, 8, 9}

The defined constraints of the array will tell FXScript where to "wrap" the data into the next row.

The 3x3 matrix

A multidimensional array is usually called a matrix. In researching these pages, I learned that 3x3 or greater matrixes are at the heart of a great deal of digital image processing. 3x3 matrixes can be adjusted for Hue, Saturation and Brightness changes or convolved to find edges, sharpen or blur images. There is more information, though extremely technical, at these links:

Since I had never really dealt with matrixes (or multidimensional arrays for that matter), I wrote a few little plug-ins to help me to visualize what matrixes look like. These really helped me to understand what was happening inside the matrix (insert spoon joke here).

Modifying Arrays

Arrays can get very large. FXScript commonly uses arrays for images or color lookup tables. A normal 720 x 480 image buffer array contains information on 345,600 elements.

Using the compound operators discussed above, a script can change every element in an array with only one simple calculation. The following code will multiply every element of neo by 5:

neo *= 5
before   after
   1       2       3    *=   5     10     15 
4 5 6 20 25 30
7 8 9 35 40 45

If the command had been neo[1][1] *= 5 then only the information in cell [1][1] would have been affected.

 
page last modified: