Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
EOSM script 4 (ND)
--Neutral Density Script (NDS) Release 0.9M
--[[
********************************************************************************************
This script creates a bracket set for post processing, allowing you to simulate an ND filter.
Also you can use the script to create brackets to 'remove people' ;-)
Change the number of brackets or the time delay (s) between brackets using the MENU and PLAY keys (Green text)
Toggle between these changes with the UP key.
Toggle the script on and off, which switches the Focus Bar script as well, using a long single finger screen press.
In addition to the simulated ND set, you can request an ML auto exposure bracket set (ND+ option in the script's menu)
The script 'remembers' the top menu, not additional settings, at camera close, so you will only need to set them once: only change things as required.
Hint, consider using ML Config feature to allocate this script to, say, the 5D3 C3 mode and setting up all the Canon and ML menu to match its needs.
The additional (experimental) settings allow you to ask the script to automatically initiate the auto exosure bracketing at an explicit shadow SNR level. This is
useful if you find the shadow exposure bracket turns out too dark, ie it lifts it to a higher level than the basic ML feature does. You can also request a
dark frame 'bookmark' image be taken at the start and end of the sequence, ie useful in post to differentiate the start of an ND bracket sequence,
especially if you are taking many, back to back.
The script was explicitly written for a EOSM, eg keys, you will need to tweak the code for other cameras.
MENU decreases number of images to be taken and PLAY increases this number. RATE switches the script on and off.
The Canon image review needs to be non-zero, eg 2 sec **IMPORTANT**
Garry George
April 2018
www.photography.grayheron.net
********************************************************************************************
--]]
require("config") -- note only the script's top menu is saved, not the additional setttings'
number_brackets = 1
options0 = {"ON", "OFF"}
options1 = {"0 delay", "2s delay", "5s delay"}
options2 = {"None", "Audio","Led", "Both"}
options3 = {"ND Only", "ND +"}
options4 = {"OFF", "2Ev","4Ev","6Ev"}
options5 = {"NO","YES"}
touch_timer_running = false
touch_time_pressed = 0
run_NDS = false
timer_running = false
time_pressed = 0
beeped = false
good_to_go = false
canon_screen = 0
dirty = false
running = false
base_av = 0
base_tv = 0
bum = false
state = 0
cleared = false
on_off = false
lv_y_offset = 30 -- change these two to position the script's info box on the screen
lv_x_offset = 0
function myround(num,dp) -- I'm sure this could be optimised, but this works :-)
if dp == 0 then
local int = math.floor(num+0.5)
return tostring(int)
else
local int = math.floor(num)
local frac = math.floor((num-int)*(10^dp))
return tostring(int).."."..tostring(frac)
end
end
function check_bookmark() -- captures a dark frame
if NDS_menu.submenu["Additional Settings"].submenu["Bookmark?"].value == "YES"
then
camera.shutter.ms = 1
camera.aperture.apex = 9
camera.shoot()
sleep(1)
camera.shutter.ms = base_tv
camera.aperture.value = base_av
end
end
function find_ETTL() -- Find the 'ETTL' shutter value, ie to lift the shadows higher towards the midtones
local m = menu.get("Auto ETTR","Shadow SNR limit")
local n = menu.get("Auto ETTR","Trigger mode")
menu.set("Auto ETTR","Trigger mode",0) -- set ETTR menu to get an ETTR exposure
local snr = 0
if NDS_menu.submenu["Additional Settings"].submenu["Shadow SNR"].value == " 2Ev" then
snr = 2
elseif NDS_menu.submenu["Additional Settings"].submenu["Shadow SNR"].value == " 4Ev" then
snr = 4
else
snr = 6
end
menu.set("Auto ETTR","Shadow SNR limit", snr)
local check_tv = 0
repeat -- hang around until ETTL value has stabilised
check_tv = camera.shutter.apex
msleep (NDS_menu.submenu["Additional Settings"].submenu["ETTL Set Time?"].value*1000) -- adjust this for your camera. The time delay allows the ML ETTR process to settle down
until check_tv == camera.shutter.apex
menu.set("Auto ETTR","Trigger mode",n) -- reset to user ML ETTR menu setting
menu.set("Auto ETTR","Shadow SNR limit",m)
end
function blank()
if state == 0 then
display.rect(lv_x_offset+5, lv_y_offset+75, 390, 100, COLOR.TRANSPARENT,COLOR.TRANSPARENT)
else
display.rect(lv_x_offset+5, lv_y_offset+75, 390, 100, COLOR.TRANSPARENT_BLACK,COLOR.TRANSPARENT_BLACK)
end
end
function clear() -- simply checks the menu states, to ensure can display the info
if not (menu.visible or camera.gui.play or camera.gui.menu or camera.gui.info or camera.gui.mode==41) then
return true
else
return false
end
end
function info() -- displays the script's info
local time = camera.shutter.value * number_brackets
if time >= 10 then
time = myround(camera.shutter.value * number_brackets, 0)
else
time = myround(camera.shutter.value * number_brackets, 1)
end
display.rect(lv_x_offset+5, lv_y_offset+75, 390, 100, COLOR.TRANSPARENT_BLACK,COLOR.TRANSPARENT_BLACK)
display.print("Simulated time = "..time.." ",lv_x_offset+10,lv_y_offset+110,FONT.LARGE,COLOR.WHITE,COLOR.TRANSPARENT_BLACK)
if bum then
display.print("Number of brackets = "..tostring(number_brackets).." ",lv_x_offset+10,lv_y_offset+80,FONT.LARGE,COLOR.WHITE,COLOR.TRANSPARENT_BLACK)
display.print("Image-2-Image time = "..tostring(NDS_menu.submenu["Image delay"].value).." ",lv_x_offset+10,lv_y_offset+140,FONT.LARGE,COLOR.TRANSPARENT_BLACK,COLOR.TRANSPARENT_BLACK)
else
display.print("Number of brackets = "..tostring(number_brackets).." ",lv_x_offset+10,lv_y_offset+80,FONT.LARGE,COLOR.TRANSPARENT_BLACK,COLOR.TRANSPARENT_BLACK)
display.print("Image-2-Image time = "..tostring(NDS_menu.submenu["Image delay"].value).." ",lv_x_offset+10,lv_y_offset+140,FONT.LARGE,COLOR.WHITE,COLOR.TRANSPARENT_BLACK)
end
end
function refresh_screen()
display.clear()
end
function ND_bracket(arg) -- note this function is called regularly by the shoot_task event handler and does the main work
if not cleared then
if on_off then
menu.set("ND Script", "Turn Script on and off", "ON")
menu.set("Focus Bar", "Display", "OFF") -- switch off the focus bar
else
menu.set("ND Script", "Turn Script on and off", "OFF")
menu.set("Focus Bar", "Display", "ON") -- switch on the focus bar
end
display.draw(refresh_screen)
cleared = true
end
if NDS_menu.submenu["Turn Script on and off"].value == "ON" then good_to_go = true else good_to_go = false end -- track the script's on/off state
if lv.overlays == 2 and good_to_go and running then -- complete the ND simulation bracket sequence
sleep(0) -- change this delay if the bookmark doesn't come at the end of the sequence, might help
beep(2)
menu.set("Shoot", "Advanced Bracket", 0) -- so can ETTR
check_bookmark()
camera.shutter.ms = base_tv
camera.aperture.value = base_av
running = false
return true
end
if (canon_screen == KEY.MENU or canon_screen == KEY.INFO or canon_screen == KEY.PLAY or menu.visible or canon_screen == KEY.RATE) then -- manage Canon and ML menus/buttons
if dirty then
state = 0
display.draw(blank)
dirty = false
end
if canon_screen == KEY.MENU then camera.gui.menu = not camera.gui.menu end
if canon_screen == KEY.PLAY then camera.gui.play = not camera.gui.play end
canon_screen = 0
return true
end
if clear() and good_to_go then
display.draw(info)
end
if good_to_go and timer_running and (not beeped) and (dryos.ms_clock - time_pressed > 3000) and clear() then -- give user feedback if requested
if NDS_menu.submenu["User feedback"].value == "Audio" or NDS_menu.submenu["User feedback"].value == "Both" then beep() end
if NDS_menu.submenu["User feedback"].value == "Led" or NDS_menu.submenu["User feedback"].value == "Both" then led_blink() end
beeped = true -- so don't beep again
end
if good_to_go and run_NDS then -- capture requested ND simulation bracket sequence
base_tv = camera.shutter.ms -- remember starting state
base_av = camera.aperture.value -- changed if a bookmark requested
if NDS_menu.submenu["Delay?"].value == "2s delay" then
sleep(2) -- inject a 2 sec delay
elseif NDS_menu.submenu["Delay?"].value == "5s delay" then
sleep(5) -- inject a 5 sec delay
end -- else no delay
check_bookmark()
for i = 1, number_brackets do
camera.shoot() -- take the ND brackets
if i < number_brackets then sleep(NDS_menu.submenu["Image delay"].value) end -- inject the requested delay between image captures
end
if NDS_menu.submenu["Options?"].value == "ND +" then -- take additional exposure brackets using ML Auto Advanced Bracketing
if NDS_menu.submenu["Additional Settings"].submenu["Shadow SNR"].value ~= "OFF" then
menu.set("Shoot", "Advanced Bracket", 0) -- so can use ML ETTR
find_ETTL()
end
menu.set("Shoot", "Advanced Bracket", 1) -- ensure ML advanced bracketing settings are set correctly
camera.shoot() -- To DO: find a way of detecting the advanced bracketing has completed
end
run_NDS = false
running = true
end
return true
end
function test4key(k)
if menu.get("Focus Bar", "Display") == "OFF" then
if k == KEY.UP then -- toggle between number of brackets and image to image delay
if NDS_menu.submenu["Turn Script on and off"].value == "ON" and clear() then
bum = not bum
return false
else
return true
end
end
if k == KEY.MENU then
if NDS_menu.submenu["Turn Script on and off"].value == "ON" and clear() then
if bum then
number_brackets = number_brackets - 1
if number_brackets <= 0 then number_brackets = 1 end
else
NDS_menu.submenu["Image delay"].value = NDS_menu.submenu["Image delay"].value - 1
if NDS_menu.submenu["Image delay"].value < 0 then NDS_menu.submenu["Image delay"].value = 0 end
end
dirty = false
return false
else
dirty = true
return true
end
end
if k == KEY.PLAY then
if NDS_menu.submenu["Turn Script on and off"].value == "ON" and clear() then
if bum then
number_brackets = number_brackets + 1
if number_brackets <= 0 then number_brackets = 1 end
else
NDS_menu.submenu["Image delay"].value = NDS_menu.submenu["Image delay"].value + 1
end
dirty = false
return false
else
dirty = true
return true
end
end
if k == KEY.HALFSHUTTER and good_to_go and (not timer_running) and (not run_NDS) and clear() then
timer_running = true -- start looking for SET triggered long press
time_pressed = dryos.ms_clock
beeped = false
return false -- steal key
elseif k == KEY.UNPRESS_HALFSHUTTER and good_to_go and timer_running and (not run_NDS) and clear() then
if dryos.ms_clock - time_pressed > 3000 then -- 3 sec plus SET press, so start ND bracketing
run_NDS = true -- OK to run the main script
timer_running = false -- stop looking for a long press
return false -- steal key
else -- less than 3 seconds so handle as a normal SET unpress
timer_running = false
return true
end
end
end
end
event.keypress = test4key
event.shoot_task = ND_bracket
NDS_menu = menu.new
{
parent = "Shoot",
name = "ND Script",
help = "Set exposure for most important feature,",
help2 = "usually the sky or water",
submenu =
{
{
name = "Turn Script on and off",
help = "Plus press RATE to switch script on and off",
help2 = "Off is useful if you find conflicts",
choices = options0,
},
{
name = "Delay?",
help = "Injects the requested delay (0/2/5) before bracketing starts",
help2 = "Switch off Canon delays",
choices = options1,
},
{
name = "Options?",
help = "ND bracketing only or plus an exposure bracket set",
help2 = "Ensure ML ETTR and Advanced Bracketing set up",
choices = options3,
},
{
name = "Image delay",
help = "Injects the request delay between images",
help2 = "Useful for removing people, as long as they move! ;-)",
min = 0,
max = 30,
value = 0,
},
{
name = "User feedback",
help = "To help with 3s trigger",
choices = options2,
},
{
name = "Additional Settings", -- note not saved at camera shut down
help = "Various additional settings for the script",
help2 = "Note these are not saved at camera shut down",
submenu =
{
{
name = "ETTL Set Time?",
help = "A camera specific variable in seconds",
help2 = "Change if ETTL fails to find a solution",
min = 2,
max = 8,
value = 4 -- this works on a 5D3
},
{
name = "Shadow SNR",
help = "Signal-2-Noise ratio in Ev: 4-6 is the sweet spot",
choices = options4,
},
{
name = "Bookmark?",
help = "Places a dark frame at the start of ND bracket set",
choices = options5
},
}
}
}
}
config.create_from_menu(NDS_menu) -- keep a track of the script's menu state at camera close
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment