Created
May 12, 2018 13:50
-
-
Save pigeonhill/b025e8ada4eeb07f1d3d6534f675630e to your computer and use it in GitHub Desktop.
EOSM script 4 (ND)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--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