JavaScript Transforms

A JavaScript transform is a transform that modifies the images according to JavaScript written in a file. You can write the JavaScript yourself, so you can create your own transforms.

First some cautions:
Cautions done, how do we write a JavaScript file for the transform?  I will assume you are familiar with programming, and comfortable in tackling the prograamming side of things.   I will just describe the interface and how to use it.

A JavaScript file is a plain text file containing instructions in JavaScript language.  For our purposes Gorp requires one function to be present (and will ignore most others).  This is the important function:
// create a new image from those given.  
// frameNumber: integer representing current frame number.
// The parameter images is an array of objects of the following form:
// {
// int width; // width of the frame in pixels
// int height; // height of the frame in pixels
// int[] pixels; // array of ints, one per pixel, representing RGB data (0x00RRGGBB)
// }
// There is one image position in the array per declared input, but any image position
// except the first may be null.
// The new image is returned in the pixel data of images[0]
function getFrame(frameNumber, images) {
if (frameNumber < startFrame) {
// do no‌thing
} else if (frameNumber > endFrame) {
images[0].pixels = images[1].pixels;
} else {
numFrames = endFrame - startFrame + 1;
thisFrame = frameNumber - startFrame + 1;
endy = (thisFrame * images[0].height) / numFrames;
endx = (thisFrame * images[0].width) / numFrames;
rowOffset = 0;
for (y = 0; y < endy; y++) {
for (x = 0; x < endx; x++) {
images[0].pixels[rowOffset + x] = images[1].pixels[rowOffset + x];
}
rowOffset = rowOffset + images[0].width;
}
}
}

I have left the comments in this piece of code.  This function takes an array of objects from Java, the array has one element for each input supplied.  This implementation uses two inputs, and so must be hosted by  JavaScriptTwoInputs transform.  What does this script do? Well, it implements a rather simple transition between the two inputs.  If the frame number is less than startFrame then the image from the first input is returned unchanged.  If the frame number is greater than endFrame then the image from the second input is returned.  In between we copy pixels from the second frame to the first.  I am sure that you can do better.

There are a couple of impportant things to note here:
Copy the code above into a text file, lets call it JavaScript1.js.  Now open up Gorp, and add a couple of video sources, then create a JavaScript transform from the popup.  Since our code wants two inputs, we need to create a 'JavascriptTwoInputs' transform.  When prompted by the edit dialogue, select the script file 'JavaScript1.ps'.

Now run your flow diagram, and examine the result.  Simple, really.  But very slow.

How to use parameters

If you want to allow the user to supply values to your JavaScript transform you will need to use the parameter interface.  Doing so will also allow your parameters to persist in the file when a diagram is saved.  There are two parts to this:

Supplying parameters to Gorp

(As a consequence of limitations to the Java/JavaScript interface, this is a little messier than I would like.)
To supply parameters to Gorp you must implement the getParameters function and return a string describing the parameters in the correct format. (The correct format is actually a subset of the Gorp file format).
Here is an example:
startFrame = 20;
endFrame = 70;



// return the parameter names and values in an array
function getParameters() {
params = "{startFrame = "+startFrame+", endFrame = "+endFrame+"}";
return params;
}

Here we returnthe value of our two paarameters as numbers.

Receiving Parameters from Gorp

Receiving parameters from Gorp is easy by comparison.  Just implement the setParameter method like this:
startFrame = 20;
endFrame = 70;

function setParameter(parameterName, parameterValue) {
if ("startFrame" == parameterName) {
startFrame = parameterValue;
} else if ("endFrame" == parameterName) {
endFrame = parameterValue;
}
}
When the file is loaded, or when the values have been successfully edited in a dialogue this method will be called once for each parameter.

There is a problem, however, with letting users supply values: they can supply the wrong ones!  If you look carefully at the method getFrame, you will see that we divide by  endFrame - startFrame  what if the two values are equal?  We will attempt to divide by zero and that will cause the program to fail.  What we need to do is check that the user is supplying reasonable values.

Checking Parameter Values

You can  check parameter values the user is entering into the dialogue before the OK button is pressed, and you can even disaable the OK button.  First we have to change the parameter get and set code a little, so that the start and end frames travel around together as a 'Range':
startFrame = 20;
endFrame = 70;

// return the parameter names and values in an array
function getParameters() {
params = "{frameRange = Range("+startFrame+", "+endFrame+")}";
return params;
}

function setParameter(parameterName, parameterValue) {
if ("frameRange" == parameterName) {
startFrame = parameterValue.start;
endFrame = parameterValue.end;
}
}
Now we implement the checker method:
function checkParameter(parameterName, parameterValue) {
if ("frameRange" == parameterName) {
start = parameterValue.start;
if (parameterValue.start >= parameterValue.end) {
return "invalid frame range";
}
}
return null;
}
If we think the values are suitable, we return null.  If we think there is an error we return a string describing the error.  If we return an error the OK button in the dialogue is disabled.  
I have included the full text of the script file so that you can doownload and try it.