Last active
May 1, 2021 11:31
-
-
Save pigeonhill/e40b415b8f751e8369c0edc9d09003c6 to your computer and use it in GitHub Desktop.
fmath version of M3 Bracketing
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
--[[ | |
@title Brackets (M3) | |
@chdk_version 1.5 | |
@subtitle Bracketing Options | |
#mode = 0 "Focus bracket?" {Off X2INF Min2INF} | |
#bracket = 0 "Exposure bracket?" {Off +4Ev +3Ev +2Ev 2(+2Ev) 3(+2Ev) ISO1600 auto} | |
#sky = 0 "Sky Bracket?" {Off Sky+2Ev Sky+3Ev Sky+4Ev Sky+5Ev Sky+6Ev} | |
@subtitle Bracketing Settings | |
#infinity = 3 "Infinity focus (xH)" [2 4] | |
#overlap = 15 "Overlap (um)" [5 30] | |
#hilit = 20 "% histo HiLit" [5 30] | |
#pmag = 1 "Assumed Pupil Mag" [1 6] | |
@subtitle Other Settings | |
#dofs = 0 "DoF display" {Blur DoFs} | |
#traf = 0 "Traffic Lights" {Off On} | |
#sleep_time = 2 "Delay (s)" | |
#bookends = 1 "Bookends?" {Off On} | |
#screen_off = 0 "Screen?" {Off On} | |
#log = 0 "Log?" {Off On Reset} | |
#help = 0 "Console" {Off On} | |
#lens = 0 "Lens name?" {Off On} | |
Notes: | |
* This version only runs on the M3 with the fmath library version of CHDK | |
* Can only use registered EF-M lenses | |
* Script best used with WA lenses ;-) | |
* For retrofocus lenses use an assumed pupil mag at least as large as your guess. For telephoto use 1 | |
* Register your EF-M lens below in the lens_info() function | |
* Not designed for macro focus stacking, ie best for deep focus photography only | |
* To stop flickering, cycle the Canon screen (INFO), eg to not show the Canon histogram | |
* If you reset/delete the log, you need set the log menu to on or off after | |
* When paused, at the assess point, you can refocus and see the impact on bracketing. You can also change focal length, but you need to press the RIGHT key to reset things | |
* If traffic light (TL) feedback is enabled, once an image is captured, the left hand TL shows the near DoF's focus overlap state, relative to the last image captured... | |
...and the right TL sows the far DoF's overlap state relative to the last image captured. Yellow = same focus; green = a positive overlap; red = a negative overlap (a gap). | |
In addition, as you manually focus bracket, the centre info area of the bar changes from showing the focal length and the number of bracket, to the fL and the blur at the overlap | |
* Use pmag to ensure focus overlap insurance. Use 1 for a telephoto lens and a value greater than what you think it is for a retrofocus lens | |
* Also at the assess point, you can exit ALT mode and change aperture. Reentering ALT and pressing the RIGHT key to reset things. | |
* Exposure bracketing and Sky Bracketing are mutually exclusive. To undertake sky bracketing you need to set exposure bracketing to zero. | |
* All console measurements, focus and near DoF, are relative to the sensor. | |
* Note: the script attempts to detect Canon changes, eg PLAY or MENU etc, but isn't perfect ;-) If the bar disappears, just press ALT on and off, or wait for M3 Bracketing to auto refresh | |
Release 1.07 | |
photography.grayheron.net | |
April 2021 | |
--]] | |
capmode = require("capmode") | |
bi = get_buildinfo() | |
if (bi.platform ~= "m3") then | |
print("Only runs on M3") | |
sleep(3000) | |
return | |
end | |
local s,e = pcall(function() local w=fmath.new(0) end) | |
if s == false then | |
print("Can't use script") | |
sleep(3000) | |
return | |
end | |
require "drawings" | |
props=require'propcase' | |
set_console_autoredraw(1) | |
set_console_layout(0,0,45,1) | |
if log == 2 then | |
print_screen(1) | |
print("Log reset") | |
print("Reset log menu") | |
print_screen(0) | |
return | |
end | |
press("shoot_half") | |
repeat sleep(10) until get_shooting() | |
dof = get_dofinfo() | |
F = fmath.new(dof.focal_length,1000) -- focal length in mm (real) | |
s = get_prop(props.TV) | |
av = get_prop(props.AV) | |
n = fmath.new(av96_to_aperture(av),1000) -- aperture number as a real | |
start_s = s | |
s_ev = s | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
steps = 1 | |
steps_back = 0 | |
inf = 81000 -- infinity trap | |
function units(xx) | |
local xr ="" | |
if xx:int() > 5000 then | |
xr=(xx/1000):tostr(1).."m" | |
elseif xx:int() > 1000 then | |
xr=(xx/10):tostr(0).."cm" | |
else | |
xr=(xx):tostr(0).."mm" | |
end | |
return xr | |
end | |
function hH() -- calculate the full & short versions of the hyperfocal | |
n = fmath.new(av96_to_aperture(get_user_av96()),1000) -- convert to a real aperture number | |
h = (1000*F*F)/(n*overlap) -- short hyperfocal (mm) | |
H = h + F -- 'full' hyperfocal (mm), as measured from the lens front principal, ie NOT the sensor as reported by Canon | |
end | |
function update_DoFs(xx) -- update stuff for DoFs etc | |
local q = xx-t | |
u = (((q*(q-4*F)):sqrt() + q)/2):int() -- focus distance in mm from front principal | |
if xx < inf then | |
ndof = F*F/(u-F) | |
ndof = ndof+(h*(F-h*pmag))/(pmag*(u+h-F)) | |
ndof = (ndof+(pmag*(2*F+h+t)-F)/pmag) | |
else | |
ndof = H | |
end | |
if u < H:int() then | |
fdof = F*F/(u-F) | |
fdof = fdof-(h*(F+h*pmag))/(pmag*(u-h-F)) | |
fdof = (fdof+(pmag*(2*F-h+t)-F)/pmag) | |
num = (1+(H/u + 1)/2):int() | |
else | |
fdof = fmath.new(inf+1) | |
num = 1 | |
end | |
end | |
function get_focus_distance_upper() -- returns upper focus distance in mm, but note 'accuracy' is 1cm from Canon. NOTE - NOT USED IN THIS SCRIPT | |
local x = -1 | |
if (bi.platsub == "101a") then | |
x = peek(0x00244916, 2) | |
elseif (bi.platsub == "120f") then | |
x = peek(0x0024495A, 2) | |
else | |
error('Not 101a or 120f') | |
end | |
if x ~= -1 then return x*10 else return x end | |
end | |
function get_focus_distance_lower() -- returns lower focus distance in mm, but note 'accuracy' is 1cm from Canon | |
local x = -1 | |
if (bi.platsub == "101a") then | |
x = peek(0x00244918, 2) | |
elseif (bi.platsub == "120f") then | |
x = peek(0x0024495C, 2) | |
else | |
error('Not 101a or 120f') | |
end | |
if x == -1 then return -1 else return x*10 end | |
end | |
function refocus_to(xx) -- Only moves towards infinity. Returns requested focus distance in mm | |
local current_x = get_focus_distance_lower() -- current focus distance in mm to nearest cm. Based on Canon lower EXIF value | |
local steps_total = 0 | |
local last_step_count = steps_total | |
if xx < current_x then return -1 end -- don't use | |
local last_step_x = current_x | |
while current_x < xx do | |
call_event_proc("EFLensCom.MoveFocus", steps, 1) -- move smallest step you can towards infinity | |
steps_total = steps_total + steps | |
sleep(25) -- for system to catch up | |
current_x = get_focus_distance_lower() -- Get Canon lower EXIF value | |
if (current_x ~= last_step_x) and (current_x < xx) then -- just went through an intermediate step change, ie not yet reached the step that covers xx | |
last_step_x = current_x | |
last_step_count = steps_total -- close enough | |
end | |
end | |
-- now fine tune position backwards if required | |
steps_back = ((current_x - xx) * (steps_total - last_step_count)) / (current_x - last_step_x) | |
if steps_back > 0 then | |
for i = 1, steps_back do call_event_proc("EFLensCom.MoveFocus", -steps, 1) end | |
end | |
sleep(25) -- for system to catch up | |
current_x = get_focus_distance_lower() | |
return xx -- request focus position, eg the 'best' estimate in mm as to where we really are | |
end | |
function lens_name() | |
local get_lens_name_fn = 0xfc2f3fd5 | |
if (bi.platsub == "101a") then get_lens_name_fn = 0xfc2f3fc3 end | |
if call_event_proc('System.Create') == -1 then error('Unknown Error') end | |
local ppname = call_event_proc('AllocateMemory', 8) | |
if ppname == -1 or ppname == 0 then error('Unknown Error') end | |
local plen = ppname + 4 | |
poke(ppname, 0) | |
poke(plen, 0) | |
local status = call_func_ptr(get_lens_name_fn, ppname, plen) | |
local pname = peek(ppname) | |
local len = peek(plen) | |
call_event_proc('FreeMemory', ppname) | |
if ppname == -1 or ppname == 0 then error('Unknown Error') end | |
local i = 0 | |
local t = {} | |
while i < len do | |
local c = peek(pname + i, 1) | |
if c == 0 then break end | |
table.insert(t, string.char(c)) | |
i = i + 1 | |
end | |
local name = table.concat(t) | |
return name | |
end | |
function restore() | |
set_tv96_direct(s) | |
set_av96_direct(av) | |
press("shoot_half") | |
repeat sleep(10) until get_shooting() | |
sleep(100) | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
if current_focus_mode ~= 1 then set_mf(0) end | |
if (current_mode ~= "M") then capmode.set(current_mode) end | |
set_lcd_display(1) | |
exit_alt() | |
print_screen(0) | |
cls() | |
end | |
function set_up() | |
current_focus_mode = get_focus_mode() | |
current_mode = capmode.get_name() | |
if current_focus_mode ~= 1 then set_mf(1) end | |
s = get_tv96() | |
av = get_av96() | |
press("shoot_half") | |
repeat sleep(10) until get_shooting() | |
if sky > 0 and bracket == 0 then -- reset exposure for the sky/infinity bracket | |
set_tv96_direct(s - 96*(sky+1)) | |
sleep(100) | |
end | |
if (current_mode ~= "M") then capmode.set("M") end | |
s = get_tv96() | |
set_tv96_direct(s) | |
set_av96_direct(av) | |
sleep(100) | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
dof = get_dofinfo() | |
F = fmath.new(dof.focal_length,1000) -- focal length in mm (real) | |
lens_test = lens_info() | |
hH() -- update hyperfocal info | |
end | |
function myshoot() | |
local prevcnt = hook_shoot.count() | |
local rawprevcnt = hook_raw.count() | |
press 'shoot_full_only' | |
repeat sleep(10) until prevcnt ~= hook_shoot.count() | |
release 'shoot_full_only' | |
repeat sleep(10) until rawprevcnt ~= hook_raw.count() | |
end | |
function X_bracket() | |
press("shoot_half") | |
repeat sleep(10) until (get_shooting()) | |
set_tv96_direct(s) | |
if bracket == 0 or bracket >= 8 then | |
myshoot() | |
elseif bracket == 1 then | |
myshoot() | |
set_tv96_direct(s - 96 * 4) | |
myshoot() | |
elseif bracket == 2 then | |
myshoot() | |
set_tv96_direct(s - 96 * 3) | |
myshoot() | |
elseif bracket == 3 then | |
myshoot() | |
set_tv96_direct(s - 96 * 2) | |
myshoot() | |
elseif bracket == 4 then | |
myshoot() | |
set_tv96_direct(s - 96 * 2) | |
myshoot() | |
set_tv96_direct(s - 96 * 4) | |
myshoot() | |
elseif bracket == 5 then | |
myshoot() | |
set_tv96_direct(s - 96 * 2) | |
myshoot() | |
set_tv96_direct(s - 96 * 4) | |
myshoot() | |
set_tv96_direct(s - 96 * 6) | |
myshoot() | |
elseif bracket == 6 then | |
local iso = get_iso_mode() | |
set_iso_mode(100) | |
myshoot() | |
set_iso_mode(1600) | |
myshoot() | |
set_iso_mode(iso) | |
elseif bracket == 7 then | |
shot_histo_enable(1) | |
myshoot() | |
sleep(100) | |
lower = 1024 - 1024*hilit/100 | |
test=get_histo_range(lower,1024) | |
step = 0 | |
while test > 0 do | |
step = step + 1 | |
set_tv96_direct(s + 96 * 2 * step) | |
myshoot() | |
sleep(100) | |
test=get_histo_range(lower,1024) | |
end | |
shot_histo_enable(0) | |
end | |
set_tv96_direct(s) | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
end | |
function bookend() | |
set_tv96_direct(960) | |
set_av96_direct(get_max_av96()) | |
local ecnt = get_exp_count() | |
shoot() | |
set_tv96_direct(s) | |
set_av96_direct(av) | |
repeat sleep(10) until (get_exp_count() ~= ecnt) | |
end | |
function hiatus() | |
local M = fmath.new(Mmax,1000) | |
local Fr = fmath.new(Fmax,1000) | |
-- Note the following is an estimate of the mag at f, based on simply scaling the max mag by the focal length ratio | |
-- A better model would be to explicity measure the mag at a focal length, or at least at the zooms and interpolate | |
-- Maybe in the future ;-) | |
m=M*F/Fr | |
t = (F * (1 + m) * (1 + m)) | |
t = MFD - t/m -- this is an estimate of the spilt thin lens thickness (mm) | |
return t | |
end | |
function lens_info() | |
if lens_name() == "EF-M11-22mm f/4-5.6 IS STM" then -- calculate lens thickness from manufacturer's data | |
-- add other lenses as required, ie replace the following for your lens | |
-- For the above lens, 300 is the lens max magnification x 1000, ie from manufacturer's data or your measurement | |
-- 22000 is the lens maximun zoom, or the prime, focal length in microns | |
-- 150 is the lens minimum focus distance (mm), ie from manufacturer's data or your measurement | |
Fmax = 22000 -- Longest focal length (mm) * 1000 | |
Mmax = 300 -- Max magnification * 1000 | |
MFD = 150 -- Minimum Focus Distance in mm | |
t = hiatus() -- distance between front and rear principals | |
return true | |
elseif lens_name() == "EF-M28mm f/3.5 MACRO IS STM" then | |
Fmax = 28000 -- Longest focal length (mm) * 1000 | |
Mmax = 1000 -- Max magnification * 1000 | |
MFD = 97 -- Minimum Focus Distance in mm | |
t = hiatus() -- distance between front and rear principals | |
return true | |
elseif lens_name() == "EF-M55-200mm f/4.5-6.3 IS STM" then | |
Fmax = 200000 -- Longest focal length (mm) * 1000 | |
Mmax = 210 -- Max magnification * 1000 | |
MFD = 960 -- Minimum Focus Distance in mm | |
t = hiatus() -- distance between front and rear principals | |
return true | |
elseif lens_name() == "EF-M18-55mm f/3.5-5.6 IS STM" then | |
Fmax = 55000 -- Longest focal length (mm) * 1000 | |
Mmax = 240 -- Max magnification * 1000 | |
MFD = 150 -- Minimum Focus Distance in mm | |
t = hiatus() -- distance between front and rear principals | |
return true | |
elseif lens_name() == "EF-M15-45mm f/3.5-6.3 IS STM" then | |
Fmax = 45000 -- Longest focal length (mm) * 1000 | |
Mmax = 250 -- Max magnification * 1000 | |
MFD = 250 -- Minimum Focus Distance in mm | |
t = hiatus() -- distance between front and rear principals | |
return true | |
--[[ | |
elseif lens_name() == "10-20mm" then | |
Fmax = 20000 -- Longest focal length (mm) * 1000 | |
Mmax = 130 -- Max magnification * 1000 | |
MFD = 240 -- Minimum Focus Distance in mm | |
t = hiatus() -- distance between front and rear principals | |
return true | |
elseif lens_name() == "your lens" then | |
copy template above | |
]] | |
else -- lens not recognised, so don't use | |
return false | |
end | |
end | |
function update() | |
update_DoFs(x) -- update u and DoFs | |
draw.replace(obj1,"rectf",0,0,lcd,35,"black","black") -- clear the info bar | |
if x > inf then | |
temp = ">=H : INF" | |
elseif u >= H:int() then | |
temp = ">=H : "..units(fmath.new(x,1)) | |
else | |
temp = " <H : "..units(fmath.new(x,1)) | |
end | |
draw.replace(obj2,"string",(30*lcd)/720,0,temp,"white","black") -- draw focus position info | |
inf_blur = ((overlap*(H-F))/(u-F)):int() | |
if not get_alt_mode() and traf == 1 and not image then -- change to Ev feedback | |
temp_s = ((get_user_tv96()-s_ev)*10)/96 | |
local sign = -1 | |
if temp_s < 0 then | |
sign = 1 | |
temp_s = -temp_s | |
end | |
temp = ((sign*temp_s)/10).."."..(temp_s-10*(temp_s/10)).."ev / #"..num | |
else | |
temp = F:int().."mm / #"..num | |
end | |
draw.replace(obj3,"string",(280*lcd)/720, 0,temp,"white","black") | |
if dofs == 0 then | |
temp = units(ndof).." / "..inf_blur.."um" | |
else | |
if u < H:int() then | |
temp = units(ndof).." / "..units(fdof) | |
else | |
temp = units(ndof).." / INF" | |
end | |
end | |
draw.replace(obj4,"string",(490*lcd)/720,0,temp,"white","black") | |
if image and not get_alt_mode() and traf == 1 and last_image_u < inf then -- display traffic lights | |
local clr = "black" | |
if x == last_image_x then | |
clr = "yellow" | |
elseif (ndof >= last_image_ndof) and (ndof <= last_image_fdof) then | |
clr = "green" | |
elseif (ndof > last_image_fdof) or (ndof < last_image_ndof) then | |
clr = "red" | |
end | |
draw.replace(obj5,"rectf",5,5,20,25,clr,clr) -- update left traffic light | |
if x == last_image_x then | |
clr = "yellow" | |
elseif (fdof <= last_image_fdof) and (fdof >= last_image_ndof) then | |
clr = "green" | |
elseif (fdof > last_image_fdof) or (fdof < last_image_ndof) then | |
clr = "red" | |
end | |
draw.replace(obj6,"rectf",(700*lcd)/720,5,(715*lcd)/720,25,clr,clr) -- update right traffic light | |
local ee = (F*(pmag-1))/(pmag) -- pupil extension in mm | |
local blur = ee*(u+last_image_u)-2*u*last_image_u | |
blur = blur + F*(u+last_image_u-2*ee) | |
blur = blur*n | |
blur = ((1000*F*F*(u-last_image_u))/blur):int() -- blur at overlap in microns | |
if blur < 0 then blur = -blur end | |
if x < inf then | |
temp = F:int().."mm / "..blur.."um" | |
else | |
temp = F:int().."mm / ".."???" | |
end | |
draw.replace(obj3,"string",(280*lcd)/720, 0,temp,"white","black") | |
else | |
clr = "black" | |
draw.replace(obj5,"rectf",5,5,20,25,clr,clr) -- update left traffic light | |
draw.replace(obj6,"rectf",(700*lcd)/720,5,(715*lcd)/720,25,clr,clr) -- update right traffic light | |
end | |
draw.overdraw() | |
dirty = false | |
end | |
-- Main Section | |
if lens == 1 then | |
print_screen(-1) | |
print(lens_name()) | |
sleep(3000) | |
restore() | |
return | |
end | |
if bracket > 0 and sky > 0 then | |
print("Exposure bracketing clash!") | |
sleep(3000) | |
restore() | |
return | |
end | |
set_up() | |
if lens_test == false then | |
print("Can only use registered EF-M lenses") | |
sleep(3000) | |
restore() | |
return | |
end | |
if mode == 2 then -- move to focus minimum | |
repeat | |
x = get_focus_distance_lower() | |
call_event_proc("EFLensCom.FocusSearchNear") | |
sleep(50) | |
until x == get_focus_distance_lower() | |
end | |
print_screen(0) -- switch off logging until bracketing | |
last_x = 0 | |
dirty = true | |
lcd = 0 | |
if help == 0 then -- then switch off console display | |
set_console_layout(0,0,1,0) | |
print("") | |
set_console_autoredraw(-1) | |
end | |
-- Set up the bar drawing objects | |
obj1 = draw.add("rectf", 0, 0, 0, 0, "black","black") | |
obj2 = draw.add("string", 0, 0, "","white","black") | |
obj3 = draw.add("string", 0,0,"","white","black") | |
obj4 = draw.add("string",0,0,"","white","black") | |
obj5 = draw.add("rectf", 0, 0, 0, 0, "black","black") | |
obj6 = draw.add("rectf", 0, 0, 0, 0, "black","black") | |
last_alt_state = get_alt_mode() | |
image = false -- no image taken yet | |
last_image_ndof = fmath.new(0) | |
last_image_fdof = fmath.new(0) | |
last_image_x = 0 | |
last_image_u = 0 | |
ecnt = get_exp_count() | |
tsec = get_day_seconds() | |
repeat -- stay here while in asssess/shooting mode | |
x = get_focus_distance_lower() | |
if last_x ~= x then dirty = true end | |
last_x = x | |
wait_click(50) -- check for a button press | |
if is_key("right") and get_alt_mode() then -- re-run set up tasks | |
set_up() | |
dirty = true | |
elseif is_key("shoot_full") and not get_alt_mode() then -- taking an image outside of ALT mode | |
last_image_ndof = ndof | |
last_image_fdof = fdof | |
last_image_x = x | |
last_image_u = u | |
repeat sleep(50) until ecnt ~= (get_exp_count()) | |
ecnt = get_exp_count() | |
image = true | |
dirty = true | |
elseif is_key("shoot_half") and not get_alt_mode() then | |
dirty = true | |
end | |
if get_alt_mode() ~= last_alt_state then -- refresh a few things if ALT state changes | |
dirty = true | |
last_alt_state = get_alt_mode() | |
image = false | |
s_ev = get_user_tv96() -- reset ev feedback | |
end | |
if get_gui_screen_width() ~= lcd then -- screens have changed | |
if get_gui_screen_width() == 720 then -- potentially show the console if requested | |
set_console_autoredraw(1) | |
set_console_layout(0,0,45,1) | |
dirty = true | |
else -- don't show console when using EVF | |
set_console_autoredraw(-1) | |
set_console_layout(0,0,1,1) | |
print("") | |
dirty = true | |
end | |
end | |
lcd = get_gui_screen_width() | |
if lcd == 720 and help == 1 then -- update console to show help reminder | |
print("SET=Run : RIGHT=Reset : FSP = EXIT") | |
end | |
if ((get_day_seconds()-tsec > 2) and x == last_x) then | |
dirty = true | |
tsec = get_day_seconds() | |
end | |
if dirty then update() end -- update the info bar | |
sleep(500) -- no need to check too often | |
until ((is_key("set") or is_key("shoot_full")) and get_alt_mode()) -- then take brackets or exit | |
if help == 1 and lcd == 720 then -- show bracketing progress in main screen | |
set_console_autoredraw(1) | |
set_console_layout(0,0,45,1) | |
end | |
if log == 1 then | |
set_console_autoredraw(-1) | |
print_screen(-1) | |
print("...") | |
print(os.date()) | |
set_console_autoredraw(1) | |
end | |
t1=os.time() -- start the clock | |
draw.clear() | |
print_screen(0) | |
print("Bracketing Started") | |
if log == 1 then print_screen(-1) end -- switch focus bracketing logging on | |
update_DoFs(x) -- update stuff | |
if bookends == 1 then bookend() end | |
t1=sleep_time-(os.time()-t1) | |
if t1 > 0 then sleep(t1*1000) end | |
if screen_off == 1 then set_lcd_display(0) end | |
print("1/"..num.." @ "..units(fmath.new(x))) | |
X_bracket() -- First exposure(s) | |
if mode == 0 then -- exposure bracket only requested so exit script after taking images at current focus | |
if sky > 0 and bracket == 0 then -- sky bracket requested | |
press("shoot_half") | |
repeat sleep(10) until (get_shooting()) | |
set_tv96_direct(s + 96*(sky+1)) | |
myshoot() | |
set_tv96_direct(s) | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
end | |
if bookends == 1 then bookend() end | |
restore() | |
return | |
end | |
i = 1 | |
while (u < (H/3):int()) do -- capture the rest of the focus brackets up to H/3 | |
-- Note that focus bracketing is calculated/updated in u space, but actual refocusing is in x space | |
-- All console feedback is in x space, ie distance estimates measured from the sensor | |
new_u = 2*F*F*(pmag-1) + F*(u-2*pmag*u) + h*pmag*u | |
new_u = (new_u/( F*(2*pmag-1) + pmag*(h-2*u))):int() -- new u in mm, using DOFIS model | |
if new_u <= u then new_u = u + 5 end -- move at least 5mm, just in case. Remember: script is not designed for macro work! | |
u = new_u | |
x = (u + F + (F*F)/(u-F) + t) -- next focus bracket estimate in x space: in mm from f(1+m)+t+u | |
refocus_to(x:int()) | |
i = i + 1 -- keep track of number of images taken | |
print(i.."/"..num.." @ "..units(x)) | |
X_bracket() | |
end | |
if u < inf and x:int() < inf then -- take additional images at/beyond H | |
if u < H:int() then | |
temp = ((F*F)/(H-F) + F + t + H) | |
refocus_to(temp:int()) | |
else | |
temp = ((F*F)/(u-F) + F + t + u) | |
end | |
print("@H = "..units(temp)) | |
X_bracket() | |
temp = ((F*F)/(infinity*H-F) + F + t + infinity*H) | |
if temp:int() > inf then -- adjust as at/beyond lens infinity | |
repeat | |
infinity = infinity - 1 | |
temp = ((F*F)/(infinity*H-F) + F + t + infinity*H) | |
until temp:int() < inf or infinity == 2 | |
end | |
refocus_to(temp:int()) | |
print("@"..infinity.."xH = "..units(temp)) | |
X_bracket() | |
if sky > 0 and bracket == 0 then -- take an extra exposure shot for the sky | |
press("shoot_half") | |
repeat sleep(10) until (get_shooting()) | |
set_tv96_direct(s + 96*(sky+1)) | |
myshoot() | |
set_tv96_direct(s) | |
release("shoot_half") | |
repeat sleep(10) until (not get_shooting()) | |
print("Inf X @ "..units(temp)) | |
end | |
end | |
if bookends == 1 then bookend() end | |
restore() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment