Wednesday, April 27, 2016

The ultimate bracketing tool: but only for Canon EOS users

Although I haven’t posted here for a while, because of home and work pressures, I’m pleased to be able to publish the latest (and greatest?) tool for Canon (non-macro) still photographers.

I could only create this tool because of the dedicated work of a few gurus at Magic Lantern, namely A1ex and David. So a very public thanks to them for issuing the latest version of the Magic Lantern Lua scripting module and helping me with some of my debugging.

Ever since the Lua scripting engine was first published, I have had a vision to create a landscape auto focus and exposure bracketing tool. That is a one button ability to cover an infinity depth of field and a (near) infinite dynamic exposure range.

Of course ML provides some great functionality already, eg Raw Expose To The Right (ETTR), Dual ISO, Auto exposure bracketing and Raw Spotmeter. But I wanted more, thus freeing me up to focus on the important things, such as composition.

The script below (which doesn’t run on the EOSM: sorry) requires that the lens reports focus distance to the camera and AF is on. In addition, to ‘prep’ the script, ML (which should be the latest nightly: http://magiclantern.fm/downloads.html) needs to be configured along these lines:

  • ETTR and LUA modules loaded. ETTR setting should be: a long slowest shutter, ie you are on a tripod; highlight ignore very low or zero; SNRs to zero; link to Dual ISO off
  • RAW Spotmeter set to Ev mode
  • Camera in Manual mode
  • Lens in AF mode
Place the script in the ML script folder (I recommend removing all other scripts or putting “_” in front of the script file names, forcing ML not to load them. If you keep other scripts in the directory then assure yourself these do not negatively interacted with each other. I will be publishing my latest Toggler script in the future, which is designed to work with the script below.

To use the script, select it under the ML Shoot menu - it shows up as Auto Focus Bracketing. The menu options go like this:

  • Run Script does what it says after you press SET
  • Delay allows you to choose a script start delay of 0, 2 or 5 seconds
  • Bookends places dark frames at the start and end of the focus and exposure bracket sets for easier identification in, say, Lightroom. Additional dark frames are placed at the start and end of a complete focus/exposure set.
  • Shadow Ev is the integer Raw Spot reading (positive) from the ML spotmeter. The spotmeter should be positioned on the shadow region that you wish to ensure you capture
  • 0Ev Offset allows you to place where the shadow bracket gets positioned relative to the 100% white (0Ev) ETTR point (see below). This value is in tenths of an Ev, ie 35 = 3.5Ev bracket delta per image is either 0, for no exposure bracketing, or 1 or 2 Ev
To establish the 0Ev offset of your camera, all you need to do is focus on a flat, single colour wall, with the ML Raw spotmeter on, and adjust the Canon meter to the 0Ev point. The ML Raw Spotmeter will now give you a reading, in Ev, of the 0Ev offset. You can use this or add or subtract from this as you see fit, ie adjusting the shadow bracket conditions.

My workflow (for a full bracket capture, ie exposure and focus, goes like this:

  • Compose and select an exposure in LV and focus on the closest object that you need to be in focus
  • Place the spotmeter on the shadow area where you wish to see details
  • Set an ML ETTR exposure (or your own exposure to capture the highlights) and note the ML spotmeter reading for your shadow area
  • Go into the ML menu and set the desired values
  • Run the script and let the exposure and focus brackets get automatically captured.
As an example, the following (indoor) test case was captured with the script and the above workflow. This LR screen capture shows the dark frames (the two dark frames at the start and end were not ingested into LR.

The post processing workflow was simply to first use the LR HDR option to create three 32bit images that were adjusted and synced, and then exported to Helicon Focus, once again from within LR. Here is the resultant image.


Bottom line: the latest Magic Lantern Lua module has, once again, made a great camera, in my case the 5D3, an even better camera. As usual I welcome feedback on the attached script and I hope you get value out of it in your photography.

--[[
Landscape auto exposure & focus bracketing script
Release 0.5
This version has no error detection so the user must be aware of certain things:
* Check the correct DoF diffraction options are set in ML, eg diffraction aware is on
* Must use a lens that reports focus distance and DoF can be calculated
* Lens must be in AF mode
* Must be in manual mode
* Switch stabalisation off as you will not be hand holding ;-)
* Must be in LV mode
* Assumes lens is focused at nearest point to start, ie script moves to infinity
* Script takes last bracket with focus point at infinity
--]]

-- Declare a few variables for the script
a1 = 0
b1 = 0
a2 = 0
b2 = 0
fp = 0
inf = 100000
delay = 0
base_tv = 0
delay = 0
factor = 0
num_brackets = 0

function check_bookend()
if keymenu.submenu["Bookends?"].value == "yes"
    then
        base_tv = camera.shutter.ms
        camera.shutter.ms = 1
        camera.shoot(64, false)
        camera.shutter.ms = base_tv
    end
end

function take_image()
    local i = 0
    camera.shoot(64, false)
    if factor ~= 0
    then -- take exposure brackets
    base_tv = camera.shutter.apex
    for i = 1, num_brackets , 1
    do
    camera.shutter.apex = camera.shutter.apex - factor
    camera.shoot(64, false)
    end
    camera.shutter.apex = base_tv
    check_bookend()
    end
end

function albs()
-- check not an EOSM
menu.close()
if camera.model_short == "EOSM"
then
display.notify_box("Sorry doesn't work with the EOSM", 3000)
else
--     Get DoF info, delay as requested & take first bracket
    msleep(delay)
    a2 = lens.dof_near
    b2 = lens.dof_far
    if factor ~= 0
    then -- calculate number of brackets
    num_brackets = (tonumber(keymenu.submenu["Shadow Ev"].value) - tonumber(keymenu.submenu["0Ev offset"].value)/10)/factor
    num_brackets = math.floor(num_brackets)
    if num_brackets <= 1 then num_brackets = 1 end
    end
    check_bookend()
    if num_brackets ~= 0 then check_bookend() end
    take_image()
-- take remaining brackets to infinity end
    repeat
    a1=a2
    b1=b2
        repeat
        lens.focus(-1,1)
        b2 = lens.dof_far
        a2 = lens.dof_near
        fp = lens.focus_distance
        until a2 > b1 or fp >= inf
    lens.focus(1,1)
    take_image()
    until fp >= inf
    check_bookend()
end
end

keymenu = menu.new
{
    parent = "Shoot",
    name = "Auto Focus Bracketing",
    help = "Remember: LV, DoF & AF on + focus at nearest point",
    depends_on = DEPENDS_ON.LIVEVIEW,
    submenu =
    {
        {
            name = "Run Script",
            help = "Does what it says after pressing SET",
            select = function(this) task.create(albs) end,
        },
        {
            name = "Delay",
            help = "Delays script start by stated number of secs",
            choices = {"2","5","0"},
            update = function(this)
            delay = tonumber(keymenu.submenu["Delay"].value)*1000
            end,
        },
        {
            name = "Bookends?",
            help = "Places a dark frame at start and end of focus bracket set",
            choices = {"no","yes"},
        },
        {
            name = "Shadow Ev",
            help = "As measured by shadow Ev from ML Spotmeter",
            help2 = "value in integer positive (Ev) stops",
            min = 1,
           max = 20,
            value = 5,
        },
        {
            name = "0Ev offset",
            help = "Number stops (x10) Canon 0Ev is assumed down from highlight max",
            help2 = "uses tenths of an Ev",
            min = 10,
            max = 60,
            value = 35,
        },
        {
            name = "Ev bracket delta per image",
            help = "0 = no exposure bracketing",
            help2 = "Bracketing limited to 1 or 2",
            choices = {"0","1","2"},
            update = function(this)
            factor = tonumber(keymenu.submenu["Ev bracket delta per image"].value)
            end
        }
    }
}