photo-utils 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/Gemfile +4 -0
  4. data/README.rdoc +1 -0
  5. data/Rakefile +1 -0
  6. data/TODO.txt +34 -0
  7. data/bin/photo-util +39 -0
  8. data/lib/photo_utils.rb +28 -0
  9. data/lib/photo_utils/angle.rb +17 -0
  10. data/lib/photo_utils/aperture.rb +62 -0
  11. data/lib/photo_utils/apex.rb +210 -0
  12. data/lib/photo_utils/brightness.rb +49 -0
  13. data/lib/photo_utils/camera.rb +82 -0
  14. data/lib/photo_utils/compensation.rb +29 -0
  15. data/lib/photo_utils/extensions/array.rb +11 -0
  16. data/lib/photo_utils/extensions/float.rb +18 -0
  17. data/lib/photo_utils/extensions/math.rb +11 -0
  18. data/lib/photo_utils/extensions/numeric.rb +23 -0
  19. data/lib/photo_utils/formats.rb +146 -0
  20. data/lib/photo_utils/frame.rb +36 -0
  21. data/lib/photo_utils/illuminance.rb +48 -0
  22. data/lib/photo_utils/length.rb +92 -0
  23. data/lib/photo_utils/lens.rb +50 -0
  24. data/lib/photo_utils/scene.rb +180 -0
  25. data/lib/photo_utils/scene_view.rb +134 -0
  26. data/lib/photo_utils/sensitivity.rb +44 -0
  27. data/lib/photo_utils/time.rb +53 -0
  28. data/lib/photo_utils/tool.rb +17 -0
  29. data/lib/photo_utils/tools/blur.rb +43 -0
  30. data/lib/photo_utils/tools/brightness.rb +20 -0
  31. data/lib/photo_utils/tools/calc_aperture.rb +45 -0
  32. data/lib/photo_utils/tools/cameras.rb +24 -0
  33. data/lib/photo_utils/tools/chart_dof.rb +146 -0
  34. data/lib/photo_utils/tools/compare.rb +305 -0
  35. data/lib/photo_utils/tools/dof.rb +42 -0
  36. data/lib/photo_utils/tools/dof_table.rb +45 -0
  37. data/lib/photo_utils/tools/film_test.rb +57 -0
  38. data/lib/photo_utils/tools/focal_length.rb +25 -0
  39. data/lib/photo_utils/tools/reciprocity.rb +36 -0
  40. data/lib/photo_utils/tools/test.rb +91 -0
  41. data/lib/photo_utils/value.rb +37 -0
  42. data/lib/photo_utils/version.rb +5 -0
  43. data/photo-utils.gemspec +29 -0
  44. data/test/aperture_test.rb +40 -0
  45. data/test/apex_test.rb +28 -0
  46. data/test/brightness_test.rb +36 -0
  47. data/test/length_test.rb +40 -0
  48. data/test/scene_test.rb +25 -0
  49. data/test/sensitivity_test.rb +36 -0
  50. data/test/time_test.rb +42 -0
  51. metadata +185 -0
@@ -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
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ Gemfile.lock
3
+ pkg/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in photo-utils.gemspec
4
+ gemspec
@@ -0,0 +1 @@
1
+ FIXME
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -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
@@ -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)
@@ -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,17 @@
1
+ require 'delegate'
2
+
3
+ module PhotoUtils
4
+
5
+ class Angle < DelegateClass(Float)
6
+
7
+ def initialize(n)
8
+ super(n.to_f)
9
+ end
10
+
11
+ def to_s
12
+ "#{format}°"
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -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