Shuttter and Focus Stacking Notes[]

May, 2012

timefocus.bas / "SHUTTER & FOCUS STACKING" is a combined depth-of-field (focus) stacking and exposure bracketing script for CHDK.  Written for and tested on the Powershot S3IS, it should be portable to other models by changing the test-values of only two lines which interpret the Mode Switch position.

Before entering <alt> mode you should:

  • Put the Mode switch in either Manual or Av mode, depending on how picky you want to be about choosing your center exposure value.
  • Choose an f-stop (Av). High numbers will give you maximum depth of field in a hurry.  If you want to focus only on a certain foreground range, low numbers will leave the background more blurred, which may help your subject stand out more.
  • Manually focus on the closest point you want to be sharp.
  • Confirm that you're in single-frame mode, not Continuous or Delay.  Note: this script's strength in exposure bracket is its versatility.  Instead of being limited to only 3 exposure steps, you can have up to 9, and the steps can be as far apart as 3 full stops.  But if you don't need that stuff, using your camera's own bracketing system will be faster.  Set up the bracket spacingin the camer's menus (accessed via the FUNC button in the S3).  Where you tell this script how many exposure steps you want, enter 1 to allow the camera's native bracketing to do the job.
  • Turn off Preview.  This script may take a hundred or more shots, and you don't need to wait 2 extra seconds after each one.
  • Mount the camera on a tripod, or at least set it on a solid surface.

Enter <alt> mode and it's menus. Load timefocus.bas as your script.

Choose your script shoot delay based on whether you have a remote for your camera.  If you do, you probably don't need any delay; if not, a couple of seconds will give time for any vibrations to end after you take your finger off the shutter button.

SHUTTER & FOCUS Stacking Parameters[]

Exposure steps: How many different exposure shots do you want at each focus distance?  Most bracketing systems expect either 3 (default) or 5, but you have the option of going up to 9 here, though that might be a sign of insanity.  Even numbers are fine, too.  If you choose 4, for instance, the setting you start with will be exactly halfway between shots 2 and 3 of each set.  If you are using the camera's native exposure bracketing with Continous Mode, set this parameter to 1 and let Canon do that part.  You can also set it to one if you are only interested in the focus stacking part of the script.

Exposure step size: How much brighter should each exposure be from the one before it?  Each step is 1/3rd of a stop, like the camera's native system.  You can go as small as 2/3, or as large as 9/3 (3 full stops).  The HDR software I've experimented with recommends at least 1 full stop, or 3.  The script default is 4.

Focus depth can be defined in any of 5 units, or any combination:

  • Meters
  • Centimeters (cm)
  • Millimeters (mm)
  • Feet
  • Inches

Canon and CHDK work in millimeters, up to 65,535, which is considered infinity.  If you want your depth of field to extend to infinity, enter 65 meters and leave all the other units 0.  The script will recognize when it has shot pictures that extend to infinity and exit gracefully long before it reaches a 65-meter focus distance.

The total focus depth must be a positive number or 0 (which indicates you want only one shot or bracket at the focused distance).  A negative total distance will be converted to 0, but there is no restriction against using negatives for individual units.  If you want your focus depth to be 70 cm, you can set the parameters for 1 meter and -1 foot.  The script will call that (1000 - 305) mm total, or 69.5 cm.

Note that there is no setting for the closest distance; you've already set that when you manually focused the camera.  There is no setting for the farthest distance; CHDK adds your closest focus to the focus depth entered above.

There is no setting for focus step size or number of steps.  CHDK calculates the depth of field after every change of focus and steps by that amount, resulting in a small overlap of focus ranges.  It quits when the script has shot at the calculated far limit or when the DOF reaches to infinity.

Note also that you have the option of shooting at a single focus distance, by setting all the focus depth units to 0 (or having their total add up to 0 or any negative number).  You can also turn off exposure bracketing by setting the number of exposure steps to 1.  If you want to do both of those things at the same time, you can.  It's a pretty elaborate way of shooting a single frame, but you can do it.

At the end of the script the camera is returned to the closest focus distance and center exposure that you began with.  If you're attempting stereo pairs with infinite focus range, for instance, you're ready to nudge the camera a tiny bit to the right, make sure it's aimed right, and push the shutter again for another run.


I believe the only model-specific lines are the ones that interpret the Mode switch position.  get-capture-mode is used to read the state into variable M.  In my S3 IS the required values are 4 for Av mode or 5 for Manual.  Look up your camera's Properties table for its values.  As currently written the lines you may need to change are

38 if not ((M = 4) or (M = 5)) then goto "wrong_mode"


49 if M = 4 then let C = get_tv96 else let C = get_user_tv96


As submitted, the script pauses to display focus and DOF information, and to show bracketing shot counts.  That came in handy for testing, and it may satisfy your curiosity, but once you're confident with it, you can delete or "rem out" those lines, WITH ONE EXCEPTION: around Line 40 you'll see these lines

print "Manual focus on"
print "closest point."
print "Preview off?"
print "Is remote enabled?"
press "shoot_half"
sleep 1800
release "shoot_half"

That sleep 1800 gives you 1.8 seconds to note the reminders in the display, but it also allows the camera to read its light meter while the shutter button is virtually half-pressed.  I'd leave that in.  It's only done once in the beginning of the script, anyway. Near the bottom of the :focus_loop subroutine is the line: gosub "report". Delete or rem out that line to save over 1.5 seconds per focus step. In the :exp_bracket subroutine are commands to display the shot number an pause 1500 milliseconds; I've already rem'd those out. Other shorter sleep commands are to allow time for the camera to change focus or read an internal variable.  Maybe they can be shorter or even eliminated.  I put them in to make sure this thing works and am satisfied for now.

The Script[]

 rem Save as timefocus.bas
 rem uBASIC script by Eric Sandbo (kidtree) for CHDK, May 23, 2012
 rem combines exposure bracketing and focus stacking
 rem written for and tested on  Powershot S3 IS.
 rem Check use of variable M get_capture_mode for camera model compatibility.
 @param e Exposure steps
 @default e 3
 @param s Exposure step size (1/3rd)
 @default s 4
 print "Max. focus distance is 65.535m"
 @param m Focus depth, meters
 @default m 1
 @param c centimeters
 @default c 0
 @param l millimeters
 @default l 0
 @param f focus depth, feet
 @default f 0
 @param i inches
 @default i 0
 if e < 1 then let e = 1
 if e > 9 then let e = 9
 if s < 2 then let s = 2
 if s > 9 then let s = 9
 rem D is total depth in mm
 let D = (1000*m) + (10*c) + l + (305 * f) + (25 * i)
 rem N is manually-focused distance; F is far distance
 if D < 0 then let D = 0
 rem Save closest focus for later restoration.
 N = get_focus
 rem calculate Farthest focus to shoot
 F = N + D
 if F > 65535 then let F = 65535
 rem read mode dial setting.  Must be set to Av (4) or M (5)
 M = get_capture_mode
 sleep 20
 if not ((M = 4) or (M = 5)) then goto "wrong_mode"
 print "Manual focus on"
 print "closest point."
 print "Preview off?"
 print "Is remote enabled?"
 press "shoot_half"
 sleep 1800
 release "shoot_half"
 rem set focus variable to closest distance
 X = N
 rem get Center shutter speed from meter (Av mode) or user setting (Manual)
 if M = 4 then let C = get_tv96 else let C = get_user_tv96
 rem set to Lowest light bracket shot
 let L = (C + ((e-1)*(s*16)))
 if (D = 0) then gosub "one_shot" else gosub "focus_loop"
 goto "restore"
 		set_focus X
 		sleep 100
 		H = get_dof
 		sleep 50
 		if (H = 0) then H = 1
 		gosub "report"
 		gosub "exp_bracket"
 		rem  H is -1 means DOF reaches to infinity, and we've finished.
 		if (H = -1) then goto "restore"
 		X = X + H
 	until X >= F
 	set_focus F
 	H = get_dof
 	sleep 50
 	set_focus (F-(H/3))
 	sleep 100
 	gosub "report"
 	gosub "exp_bracket"
 	print "Focus =", X; "mm"
 	print "DOF =", H
 	print "Far =", F
 	sleep 1500
 	gosub "exp_bracket"
 	for S = 0 to (e-1)
 		let T = (L - (S*(s*32)))
 		set_tv96_direct T
 		sleep 50
 		rem print "Shot", (S+1)
 		rem sleep 1500
 		click "shoot_full"
 			A = get_shooting
 			sleep 30
 		until (A = 1)
 			A = get_shooting
 			sleep 30
 		until (A = 0)
 	next S
 	print "set dial to"
 	print "Av or M"
 	goto "restore"
 	set_tv96 C
 	set_focus N
 	print "Ending now."