photo-utils 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|