photo-utils 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/README.rdoc +1 -0
- data/Rakefile +1 -0
- data/TODO.txt +34 -0
- data/bin/photo-util +39 -0
- data/lib/photo_utils.rb +28 -0
- data/lib/photo_utils/angle.rb +17 -0
- data/lib/photo_utils/aperture.rb +62 -0
- data/lib/photo_utils/apex.rb +210 -0
- data/lib/photo_utils/brightness.rb +49 -0
- data/lib/photo_utils/camera.rb +82 -0
- data/lib/photo_utils/compensation.rb +29 -0
- data/lib/photo_utils/extensions/array.rb +11 -0
- data/lib/photo_utils/extensions/float.rb +18 -0
- data/lib/photo_utils/extensions/math.rb +11 -0
- data/lib/photo_utils/extensions/numeric.rb +23 -0
- data/lib/photo_utils/formats.rb +146 -0
- data/lib/photo_utils/frame.rb +36 -0
- data/lib/photo_utils/illuminance.rb +48 -0
- data/lib/photo_utils/length.rb +92 -0
- data/lib/photo_utils/lens.rb +50 -0
- data/lib/photo_utils/scene.rb +180 -0
- data/lib/photo_utils/scene_view.rb +134 -0
- data/lib/photo_utils/sensitivity.rb +44 -0
- data/lib/photo_utils/time.rb +53 -0
- data/lib/photo_utils/tool.rb +17 -0
- data/lib/photo_utils/tools/blur.rb +43 -0
- data/lib/photo_utils/tools/brightness.rb +20 -0
- data/lib/photo_utils/tools/calc_aperture.rb +45 -0
- data/lib/photo_utils/tools/cameras.rb +24 -0
- data/lib/photo_utils/tools/chart_dof.rb +146 -0
- data/lib/photo_utils/tools/compare.rb +305 -0
- data/lib/photo_utils/tools/dof.rb +42 -0
- data/lib/photo_utils/tools/dof_table.rb +45 -0
- data/lib/photo_utils/tools/film_test.rb +57 -0
- data/lib/photo_utils/tools/focal_length.rb +25 -0
- data/lib/photo_utils/tools/reciprocity.rb +36 -0
- data/lib/photo_utils/tools/test.rb +91 -0
- data/lib/photo_utils/value.rb +37 -0
- data/lib/photo_utils/version.rb +5 -0
- data/photo-utils.gemspec +29 -0
- data/test/aperture_test.rb +40 -0
- data/test/apex_test.rb +28 -0
- data/test/brightness_test.rb +36 -0
- data/test/length_test.rb +40 -0
- data/test/scene_test.rb +25 -0
- data/test/sensitivity_test.rb +36 -0
- data/test/time_test.rb +42 -0
- metadata +185 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 70d478e0579f15d1fdba607ac85c84827ba8cea2
|
4
|
+
data.tar.gz: 53980404437217abd59062595727a0734aeb8fef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 94bc1d34be20f01ff721d12a681a5487d6278f17a50d9edddb0d1a1472f08195d532ce6d9d61b4d00cfd7e8c8579ea117c4a7c3af2c0bb91b653aed0dcad248e
|
7
|
+
data.tar.gz: fc13ab1c3f0876db872371ee1bbf6082889333702faa349a6ed5f75e4c8474dee0cb9b4a3dd5d7b8e0d8135e4d5ef3382c51a4203085e0e91bd6bbccee5e0403
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
FIXME
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/TODO.txt
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
- Create FieldCalculator class:
|
3
|
+
- Set subject distance/height/width/depth
|
4
|
+
- Does DoF calculations
|
5
|
+
|
6
|
+
- Create generic camera models:
|
7
|
+
- 35mm w/50mm lens
|
8
|
+
- 6x6 w/80mm lens
|
9
|
+
- 4x5 w/127mm lens
|
10
|
+
- APS-C w/? lens
|
11
|
+
|
12
|
+
- Create Subject class
|
13
|
+
- Height/width.
|
14
|
+
- Near/far depth of field.
|
15
|
+
|
16
|
+
- Add print size to Scene
|
17
|
+
- Calculate best CoC according to print size
|
18
|
+
|
19
|
+
- Create Medium class?
|
20
|
+
- eg, film, plate, instant, CCD/CMOS
|
21
|
+
- With #sensitivity.
|
22
|
+
|
23
|
+
- Add common brightness values to Brightness class.
|
24
|
+
- eg, open shade, bright sun, etc.
|
25
|
+
|
26
|
+
- Add lighting formulas:
|
27
|
+
http://www.lightsearch.com/resources/lightguides/formulas.html
|
28
|
+
http://www.birket.com/technical-library/143/
|
29
|
+
|
30
|
+
- Add flash calculation
|
31
|
+
|
32
|
+
http://www.scantips.com/lights/flashbasics1c.html
|
33
|
+
http://www.portraitlighting.net/inversesquare_law.htm
|
34
|
+
http://en.wikipedia.org/wiki/Guide_number
|
data/bin/photo-util
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.join(File.realpath(File.dirname($0)), '..', 'lib'))
|
4
|
+
|
5
|
+
require 'photo_utils'
|
6
|
+
require 'photo_utils/tools/reciprocity'
|
7
|
+
require 'photo_utils/tools/focal_length'
|
8
|
+
require 'photo_utils/tools/test'
|
9
|
+
require 'photo_utils/tools/dof_table'
|
10
|
+
require 'photo_utils/tools/dof'
|
11
|
+
require 'photo_utils/tools/compare'
|
12
|
+
require 'photo_utils/tools/blur'
|
13
|
+
require 'photo_utils/tools/film_test'
|
14
|
+
require 'photo_utils/tools/brightness'
|
15
|
+
require 'photo_utils/tools/cameras'
|
16
|
+
require 'photo_utils/tools/calc_aperture'
|
17
|
+
require 'photo_utils/tools/chart_dof'
|
18
|
+
|
19
|
+
options = {}
|
20
|
+
appname = File.basename($0)
|
21
|
+
|
22
|
+
commands = {
|
23
|
+
'reciprocity' => PhotoUtils::Tools::Reciprocity,
|
24
|
+
'focal-length' => PhotoUtils::Tools::FocalLength,
|
25
|
+
'test' => PhotoUtils::Tools::Test,
|
26
|
+
'dof-table' => PhotoUtils::Tools::DOFTable,
|
27
|
+
'dof' => PhotoUtils::Tools::DOF,
|
28
|
+
'compare' => PhotoUtils::Tools::Compare,
|
29
|
+
'blur' => PhotoUtils::Tools::Blur,
|
30
|
+
'film-test' => PhotoUtils::Tools::FilmTest,
|
31
|
+
'brightness' => PhotoUtils::Tools::Brightness,
|
32
|
+
'cameras' => PhotoUtils::Tools::Cameras,
|
33
|
+
'calc-aperture' => PhotoUtils::Tools::CalcAperture,
|
34
|
+
'chart-dof' => PhotoUtils::Tools::ChartDOF,
|
35
|
+
}
|
36
|
+
|
37
|
+
cmd = ARGV.shift or raise "Usage"
|
38
|
+
cmd_class = commands[cmd] or raise "Usage"
|
39
|
+
cmd_class.new.run(ARGV)
|
data/lib/photo_utils.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'hashstruct'
|
3
|
+
require 'builder'
|
4
|
+
require 'path'
|
5
|
+
|
6
|
+
require 'photo_utils/extensions/math'
|
7
|
+
require 'photo_utils/extensions/array'
|
8
|
+
require 'photo_utils/extensions/float'
|
9
|
+
require 'photo_utils/extensions/numeric'
|
10
|
+
|
11
|
+
require 'photo_utils/length'
|
12
|
+
require 'photo_utils/angle'
|
13
|
+
require 'photo_utils/value'
|
14
|
+
|
15
|
+
require 'photo_utils/aperture'
|
16
|
+
require 'photo_utils/brightness'
|
17
|
+
require 'photo_utils/compensation'
|
18
|
+
require 'photo_utils/illuminance'
|
19
|
+
require 'photo_utils/sensitivity'
|
20
|
+
require 'photo_utils/time'
|
21
|
+
|
22
|
+
require 'photo_utils/apex'
|
23
|
+
require 'photo_utils/lens'
|
24
|
+
require 'photo_utils/camera'
|
25
|
+
require 'photo_utils/frame'
|
26
|
+
require 'photo_utils/formats'
|
27
|
+
require 'photo_utils/scene'
|
28
|
+
require 'photo_utils/scene_view'
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module PhotoUtils
|
2
|
+
|
3
|
+
class Aperture < Value
|
4
|
+
|
5
|
+
def self.new_from_fstop(f)
|
6
|
+
new(f)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.new_from_v(v)
|
10
|
+
new(Math.sqrt(2 ** v.to_f))
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_v
|
14
|
+
Math.log2(self ** 2)
|
15
|
+
end
|
16
|
+
|
17
|
+
def format_fstop(stop_steps=3)
|
18
|
+
rounded_f = Aperture.new_from_v((to_v.to_f * stop_steps).to_i / stop_steps.to_f).format(10)
|
19
|
+
frac = rounded_f.to_f - rounded_f.to_i
|
20
|
+
if frac != 0
|
21
|
+
"f/#{rounded_f.to_f}"
|
22
|
+
else
|
23
|
+
"f/#{rounded_f.to_i}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def format_us
|
28
|
+
# Av 8 is equivalent to f/16 and US 16
|
29
|
+
steps = to_v.to_i - 8
|
30
|
+
us = 16
|
31
|
+
if steps < 0
|
32
|
+
steps.abs.times { us /= 2 }
|
33
|
+
else
|
34
|
+
steps.times { us *= 2 }
|
35
|
+
end
|
36
|
+
"US #{us}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def format_value
|
40
|
+
"Av:#{to_v.format(10)}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s(format=:fstop, stop_steps=3)
|
44
|
+
case format
|
45
|
+
when :us
|
46
|
+
format_us
|
47
|
+
when :fstop
|
48
|
+
format_fstop(stop_steps)
|
49
|
+
when :value
|
50
|
+
format_value
|
51
|
+
else
|
52
|
+
raise "Unknown format: #{format.inspect}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def absolute(focal_length)
|
57
|
+
focal_length / self
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
module PhotoUtils
|
2
|
+
|
3
|
+
class Exposure
|
4
|
+
|
5
|
+
=begin
|
6
|
+
|
7
|
+
http://doug.kerr.home.att.net/pumpkin/APEX.pdf
|
8
|
+
http://en.wikipedia.org/wiki/APEX_system
|
9
|
+
http://en.wikipedia.org/wiki/Exposure_value
|
10
|
+
http://en.wikipedia.org/wiki/Light_meter#Exposure_meter_calibration
|
11
|
+
|
12
|
+
basic APEX formula:
|
13
|
+
Ev = Tv + Av = Sv + Bv
|
14
|
+
|
15
|
+
logarithmic to linear equations:
|
16
|
+
2^Av = N^2 (N is f-Number)
|
17
|
+
2^Tv = 1/T (T in seconds)
|
18
|
+
2^Sv = S/π (S is ASA film speed, now ISO)
|
19
|
+
2^Bv = Bl (Bl in foot-lamberts) = B/π (B in candles per square foot)
|
20
|
+
|
21
|
+
base values:
|
22
|
+
Tv = 0 for a time (shutter speed) of one second.
|
23
|
+
Av = 0 for an aperture of f/1.
|
24
|
+
Sv = 0 for a film speed of ISO 3.125 arithmetic (and hence Sv = 5 for ISO 100).
|
25
|
+
Bv = 0 for a scene brightness of 1 foot-lambert.
|
26
|
+
|
27
|
+
calculate time from exposure and aperture
|
28
|
+
Tv = Ev - Av
|
29
|
+
|
30
|
+
calculate time from brightness, sensitivity, and aperture
|
31
|
+
Tv = (Sv + Bv) - Av
|
32
|
+
|
33
|
+
calculate brightness from Ev and sensitivity
|
34
|
+
Bv = Ev - Sv
|
35
|
+
|
36
|
+
calculate Ev from aperture, time, and film speed
|
37
|
+
Ev = (Tv + Av) - Sv
|
38
|
+
|
39
|
+
=end
|
40
|
+
|
41
|
+
attr_accessor :aperture
|
42
|
+
attr_accessor :time
|
43
|
+
attr_accessor :sensitivity
|
44
|
+
attr_accessor :light
|
45
|
+
attr_accessor :compensation
|
46
|
+
|
47
|
+
def initialize(params={})
|
48
|
+
params.each do |key, value|
|
49
|
+
send("#{key}=", value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def aperture=(n)
|
54
|
+
@aperture = n ? Aperture.new(n) : nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def time=(n)
|
58
|
+
@time = n ? Time.new(n) : nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def sensitivity=(n)
|
62
|
+
@sensitivity = n ? Sensitivity.new(n) : nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def light=(n)
|
66
|
+
@light = case n
|
67
|
+
when Brightness, Illuminance
|
68
|
+
n
|
69
|
+
when Numeric
|
70
|
+
Brightness.new(n)
|
71
|
+
when nil
|
72
|
+
nil
|
73
|
+
else
|
74
|
+
raise
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def compensation=(n)
|
79
|
+
@compensation = n ? Compensation.new_from_v(n) : nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def aperture
|
83
|
+
if @aperture
|
84
|
+
@aperture
|
85
|
+
elsif @sensitivity && @light && @time
|
86
|
+
Aperture.new_from_v(sv + lv - tv + cv)
|
87
|
+
else
|
88
|
+
raise "Need sensitivity/light/time to compute aperture"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def time
|
93
|
+
if @time
|
94
|
+
@time
|
95
|
+
elsif @sensitivity && @light && @aperture
|
96
|
+
Time.new_from_v(sv + lv - av + cv)
|
97
|
+
else
|
98
|
+
raise "Need sensitivity/light/aperture to compute time"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def sensitivity
|
103
|
+
if @sensitivity
|
104
|
+
@sensitivity
|
105
|
+
elsif @aperture && @time && @light
|
106
|
+
Sensitivity.new_from_v(av + tv - bv + cv)
|
107
|
+
else
|
108
|
+
raise "Need aperture/time/light to compute sensitivity"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def brightness
|
113
|
+
if @light
|
114
|
+
Brightness.new_from_v(lv)
|
115
|
+
elsif @aperture && @time && @sensitivity
|
116
|
+
Brightness.new_from_v(av + tv - sv + cv)
|
117
|
+
else
|
118
|
+
raise "Need aperture/time/sensitivity to compute brightness"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def illuminance
|
123
|
+
if @light
|
124
|
+
Illuminance.new_from_v(lv)
|
125
|
+
elsif @aperture && @time && @sensitivity
|
126
|
+
Illuminance.new_from_v(av + tv - sv + cv)
|
127
|
+
else
|
128
|
+
raise "Need aperture/time/sensitivity to compute illuminance"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def exposure
|
133
|
+
if @aperture && @time
|
134
|
+
av + tv
|
135
|
+
elsif @sensitivity && @light
|
136
|
+
sv + lv + cv
|
137
|
+
else
|
138
|
+
raise "Need aperture/time or sensitivity/light to compute exposure"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def av
|
143
|
+
aperture.to_v
|
144
|
+
end
|
145
|
+
|
146
|
+
def tv
|
147
|
+
time.to_v
|
148
|
+
end
|
149
|
+
|
150
|
+
def sv
|
151
|
+
sensitivity.to_v
|
152
|
+
end
|
153
|
+
|
154
|
+
def bv
|
155
|
+
brightness.to_v
|
156
|
+
end
|
157
|
+
|
158
|
+
def iv
|
159
|
+
illuminance.to_v
|
160
|
+
end
|
161
|
+
|
162
|
+
def lv
|
163
|
+
light.to_v
|
164
|
+
end
|
165
|
+
|
166
|
+
def cv
|
167
|
+
@compensation ? @compensation.to_f : 0
|
168
|
+
end
|
169
|
+
|
170
|
+
def ev
|
171
|
+
exposure
|
172
|
+
end
|
173
|
+
|
174
|
+
def ev100
|
175
|
+
ev - sv - Sensitivity.new(100).to_v
|
176
|
+
end
|
177
|
+
|
178
|
+
def stepped_exposures(steps=7, increment=0.3)
|
179
|
+
n = increment * (steps / 2)
|
180
|
+
(-n..n).step(increment).map do |adjustment|
|
181
|
+
new_exposure = dup
|
182
|
+
new_exposure.compensation = (@compensation ? @compensation : 0) + adjustment
|
183
|
+
new_exposure
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def to_s
|
188
|
+
"%s = %s + %s = %s + %s" % [
|
189
|
+
"Ev:#{ev.format(10)}",
|
190
|
+
aperture.format_value,
|
191
|
+
time.format_value,
|
192
|
+
sensitivity.format_value,
|
193
|
+
light.format_value,
|
194
|
+
]
|
195
|
+
end
|
196
|
+
|
197
|
+
def print(io=STDOUT)
|
198
|
+
io.puts "EXPOSURE:"
|
199
|
+
io.puts " light: #{light} (#{light.format_value})"
|
200
|
+
io.puts " sensitivity: #{sensitivity} (#{sensitivity.format_value})"
|
201
|
+
io.puts " aperture: #{aperture} (#{aperture.format_value})"
|
202
|
+
io.puts " time: #{time} (#{time.format_value})"
|
203
|
+
io.puts " compensation: #{@compensation ? compensation.format_value : '--'}"
|
204
|
+
io.puts " exposure: #{to_s}"
|
205
|
+
io.puts
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module PhotoUtils
|
2
|
+
|
3
|
+
class Brightness < Value
|
4
|
+
|
5
|
+
# N = 2 ** Rational(-7, 4)
|
6
|
+
N = 0.3
|
7
|
+
K = 11.4
|
8
|
+
NK = N * K
|
9
|
+
|
10
|
+
# amount specified in cd/m2
|
11
|
+
|
12
|
+
def self.new_from_v(v)
|
13
|
+
new((2 ** v.to_f) * NK)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.new_from_cdm2(n)
|
17
|
+
new(n)
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_v
|
21
|
+
Math.log2(self.to_f / NK)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_cdm2
|
25
|
+
to_f
|
26
|
+
end
|
27
|
+
|
28
|
+
def format_cdm2
|
29
|
+
to_cdm2.format(10) + ' cd/m2'
|
30
|
+
end
|
31
|
+
|
32
|
+
def format_value
|
33
|
+
"Bv:#{to_v.format}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s(format=:cdm2)
|
37
|
+
case format
|
38
|
+
when :cdm2
|
39
|
+
format_cdm2
|
40
|
+
when :value
|
41
|
+
format_value
|
42
|
+
else
|
43
|
+
raise "Unknown format: #{format.inspect}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|