FrameAway

Composition guide


FrameAway is a transparent composition guide that helps you frame your photographs in different sizes, aspect ratios and layouts.

Writing a plug-in

FrameAway allows you to write plugins that can be used to define custom shapes for the frame type. Writing a plug-in requires a bit of knowledge in geometry and the willingness to experiment with a small Lua script.

Creating and installing the plugin

The plugin needs to be written in a text file with the ".fap" extension. When you try opening ".fap" files, FrameAway will prompt you to install the plugin described in the file. If you confirm the installation, FrameAway will create a copy of the plugin in "Library/Application Support/FrameAway/Plugins/". Please note that once the plugin is installed, if you need to change anything in the plugin code you need to alter the file in the "Application Support" directory.

The following screencast demonstrates creating and installing a FrameAway plugin

Drawing concepts, what to write inside the plugin

The plugin is responsible of drawing a path that FrameAway will render each time the shape of the user's selection changes. FrameAway will export a bunch of variables to the plug-in, namely:

  • OriginX as the value of the origin on the horizontal
  • OriginY as the value of the origin on the vertical
  • width as the width of the selection
  • height as the height of the selection

You use these variables to call methods on the object called fp, also exported by FrameAway into the Lua script to add elements to the bezier path. The code below draws half of the diagonal formed between the top left and the bottom right of the current selection:

fp:moveTo__(originX, originY);
fp:lineTo__(originX + width / 2, originY - height / 2);
The rendering of the plugin defined above looks like this:

Another example

Let's try something a bit more complicated - a digonal and the perpendicular line connection one of the dots not adjacent to the origins of the diagonal

This requires computing the coordinates of the point where the perpendicular intersects the digonal. We know that:

  • The sine of an angle is equal to the ratio between the opposite leg and the hypotenuse
  • The cosine of an angle is equal to the ratio between the adjacent leg and the hypotenuse
  • Angles whose lines are perpendicular are equal
Based on these, the X coordinate of the intersection point i equal to height ^ 2 * width / hypotenuse ^ 2 while the Y coordinate is equal to height ^ 3 / hypotenuse ^ 2.

We also know that in a right angled triangle the squared hypotenuse is equal to the sum of the squared legs.

All of this results in the following plugin code:

hyp = (height * height + width * width);
perpX = originX + (height * height * width / hyp);
perpY =  originY - height + (height * height * height / hyp);


fp:moveTo__(perpX, perpY);
fp:lineTo__(originX, originY);
fp:moveTo__(originX, originY - height);
fp:lineTo__(originX + width, originY);

FrameAway renders the following frame type based on this code:

Plugin API

We've also written a more formal approach to describing the FrameAway plugin system

References on Lua

FrameAway expects its plugins to contain parsable Lua code

One of the best Lua references we've found is Programming in Lua, by Roberto Ierusalimschy