Scripting Exposure Compensation for Timelapse

As I discussed previously it’s sometimes necessary to change the exposure during a timelapse capture ( for example for a sunset or sunrise). However for timelapse the advice is generally to leave the camera in full manual mode because modifying the exposure during the capture can lead to two problems:

  • Changing the exposure can cause a very noticeable flicker in the final movie which de-flickering tools may not be able to remove
  • Adjusting the controls on the camera during a timelapse can cause the camera to move slightly which will also be very noticeable in the final movie

The process described below can overcome both of these problems over a limited range of exposures. Wider exposure changes need different approaches and these are discussed at the end.

Note that in the discussions below “Exposure Value” means the potential total amount of light entering the camera for each shot. A larger exposure value means potentially more light and this can be achieved by one or more of:

  • Decreasing the aperture ( e.g. f8 instead of f11 )
  • Decreasing the shutter speed ( e.g. 1/60s instead of 1/120s )
  • Increasing the ISO ( e.g. 400 ISO instead of 100 ISO )

The opposite is done to reduce the exposure value. The Wikipedia article on Exposure value discusses this in great detail but the introduction gives the information that most people need..

The Problem

The exposure problem is shown in the following diagram:

The red line shows the actual exposure needed for a sunset timelapse. At the start the required exposure is lower because the sun is higher in the sky and so is brighter. As the sunset progresses then the sun gets lower and less bright so more exposure is needed. ( I’ve assumed that the change in exposure is linear ). The green line is the exposure of the camera which, being fixed, is a compromise. It’s over exposed at the start, nearly correct in the middle and then under exposed at the end.

The Solution

If we shoot in RAW format then there is scope for adjusting the exposure of each shot after the timelapse sequence is taken.

The two blue lines show the exposure compensation that is available from the RAW format – usually about +/- 3EV. This shows that it’s possible to modify the “fixed” exposure from the camera to meet that of the sunset. However there are limitations to this technique. For example trying to shoot a 24hr timelapse of a city scene going from full daylight to full darkness is probably going to require more exposure change than this technique can handle.

I found that the easiest way of determining the amount of compensation needed was to open the first and last frames in an editor ( I use Darktable or UFRaw ) and modify the exposure of each frame until they look OK. Ideally for a sunset the first image will need a negative compensation ( made darker ) and the final image positive compensation ( made lighter ). I then make a note of these changes for the script below.

Tools and Scripts

Having decided on the exposure change needed for the first and last frames then manually calculating and modifying the exposure for the remaining frames of the video is somewhat impractical and tedious so some form of script is needed. In addition, after the exposure compensation has been applied to a RAW image, it needs to be converted to a jpg or a png file. Finally a “nice to have” option would be the ability to crop and/or resize the images.

The only tool that I know of that can do all this from the command line is UFRaw, or specifically the command line version – ufraw-batch. The man page for ufraw-batch will show the very large number of options available but we need to end up with something along the following lines for each file:

ufraw-batch DSC_4442.NEF --exposure -1.5 --restore clip 
--out-type png --crop-left 209 --crop-right 4072 --crop-top 603 
--crop-bottom 2776 --size 1279 --out-path=output_files --overwrite

This looks complicated but is quite logical:

  • The black text runs ufraw-batch on the file DSC_4442.NEF
  • The red text specifies the exposure change needed ( 1.5 stops darker in this case ) the “–restore” option control how highlights are restored when applying negative EV. ‘clip’ restores nothing and is therefore safe from any artifacts. Refer to the man page for more details.
  • The green text specifies the output file type, the output location ( in a sub-directory called output_files in this case ) and to automatically overwrite any existing files.
  • The blue text is optional and specifies any cropping and resizing

( Note: The “size” option should specify the number of pixels on the larger side of the final image. In this case I wanted a width of 1280 but to achieve this I had to set –size to 1279. I haven’t checked the UFRaw code to see if this is a bug or a feature )

The script to make these edits runs in a two stage process. Note that the script and an example configuration file can be found in my GitHub repository – – under the directory “timelapse_exposure_script”

  1. Run the first script ( ) and its associated configuration file on the directory containing the RAW images. This generates a ufraw-batch command for each file which can be stored in a second script file …
  2. The actual edits are done by running the second script file. Note that this make take some time to run.

I chose the two step approach because the edit commands can take a long time to run and sometimes it’s useful to do a sanity check first.

The script is largely self explanatory but some points to note:

  • The configuration files are effectively script files themselves which are run using the “source” command in the script. This is a simple way of allowing the user to override the default values.
  • Cropping can be disabled by setting the left and right crop values to be the same, disabled by default
  • Resizing can be disabled by setting the size value to be 0, disabled by default
  • Script files can normally only handle integer values. However floating point values are needed to calculate the exposure values. I’ve used the bc language as a simple calculator to achieve this. Four decimal places are used to maintain the accuracy although I think that that UFRaw only uses two places.
  • The script currently assumes a linear change in exposure values. However it could be modified to handle more complex changes if necessary.
  • The script sends its output to the command line. To create the second script this output needs to be redirected to a file, e.g. “ myconfig.cfg > editscript

I used this script to process the files for the sunset timelapse. The change in exposure was quite small = -1.5EV for the first image and +1EV for the final image. The change in the final image is virtually unnoticeable after the image has been cropped and rescaled but it does make a subtle improvement to the overall movie

First Frame

Final Frame

Alternative Methods

Other techniques like Bulb Ramping are available to cope with wider exposure changes but these usually need additional equipment and put restrictions on what shutter speeds, and therefore what image intervals, you can use.

The Alpine Labs website has some explanations and example timelapses taken with their equipment ( but note that I haven’t tried any of their products). Other, usually more expensive, controllers can use a combination of shutter speed, aperture and ISO to ramp the exposure but may depend on what remote control features are available on your camera.

If you have a Canon camera then the Magic Lantern alternative firmware can implement bulb ramping in camera. I have a Nikon so I haven’t tried it.


This entry was posted in Timelapse. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.