7
require 'cameralink/cameralink'
11
class Camera < CameraLink::Reader
13
attr_accessor :max_width
14
attr_accessor :max_height
17
attr_accessor :exposure
18
attr_accessor :frame_rate
19
attr_accessor :capture
20
attr_accessor :trigger
23
# Getting parameters from camera
24
#@max_width = Integer(get('Window.W.Max'))
25
#@max_height = Integer(get('Window.H.Max'))
26
@max_width, @max_height = 1280, 1024
28
if ((@max_width <= 0) or (@max_height <= 0)) then
29
raise('Camera communication is failed')
32
@width, @height = @max_width, @max_height
39
set('Window.W', @width)
40
set('Window.H', @height)
42
@trigger = get_integer('Trigger.Source', 0)
43
if (@trigger != 0) && (@trigger != 2) then
44
@trigger = set('Trigger.Source', 0)
50
@frame_rate = get_integer('FrameRate', 10)
53
@exposure = Float(get('ExposureTime'))
62
@display_proc = lambda { |w,h,d| }
63
@status_proc = lambda { |t, at_once| }
65
@set_request = Array.new
69
FileUtils::mkdir_p("saved_camera_images")
74
def set_procs(status_proc, display_proc)
75
@display_proc = display_proc
76
@status_proc = status_proc
81
s = UNIXSocket.open('/tmp/pfserver.socket')
88
def get_integer(val, min)
90
if res =~ /^#(\d+)/ then
93
value = Integer(Float(res));
95
raise('Camera communication is failed') if value < min
100
s = UNIXSocket.open('/tmp/pfserver.socket')
101
s.print(val + ' ' + String(value))
107
# s.get for some reason is crashing if called from GTK callback
109
s = UNIXSocket.open('/tmp/pfserver.socket')
110
s.print(val + ' ' + String(value))
117
@reader_thread = Thread.new {
118
while @running and not @reader_open
122
geometry = Magick::Geometry.new(@width,@height,nil,nil,Magick::AspectGeometry)
125
next_display = Time.now
126
next_status = next_display + 1
129
next_status = @frame_rate
133
#safe_run(@running) { |id, data|
134
#run(@running) { |id, data|
135
send(func, @running) { |id, data|
136
if ((id < 0) or (not data)) then next; end
138
@lost_frames += id - @current_frame - 1
140
#if (id - @current_frame - 1) > 10
141
# puts id, id - @current_frame - 1
148
if (case @trigger; when 0: id > next_status; else time > next_status; end) then
149
if (@frame_rate) then
150
msg = sprintf("FPS/Expected: %i, FPS/Measured: %i, Dropped Frames: %i", @frame_rate, @frames, @lost_frames)
152
msg = sprintf("FPS/Expected: triggered, FPS/Measured: %i, Dropped Frames: %i", @frames, @lost_frames)
156
msg += sprintf(", Captured: %i (%i MB)", @image_frames.length, @image_frames.length * @width * @height / 1024 / 1024)
159
@status_proc.call(msg, false)
161
while @set_request.length > 0
162
@set_request.pop.call
166
next_status = (@trigger > 0)?(time + 1):(id + @frame_rate - 1)
170
if (case @trigger; when 0: ((@display_mode > 0) and (id%@display_mode == 0)); else time > next_display; end) then
171
@display_proc.call(@width, @height, data)
172
next_display = (@display_mode>0)?time + (1.0 / @display_fps):time if (@trigger > 0)
176
if (@capture_storage > 0) then
177
img = Image.from_blob(data) {
184
img.write(sprintf("saved_camera_images/%s/PIC%09i.tif", @session, @capture_frame))
187
@images.push(String.new(data))
190
@image_frames.push(id)
192
if (time > @stop_capture)
193
GC.enable if @capture_storage == 0
196
@capture_session = @session
197
@capture_width = @width
198
@capture_height = @height
206
super(@width, @height)
223
def display_fps=(value)
225
@display_mode = (@frame_rate / value).round if ((@display_mode > 1) and (@frame_rate))
228
def display_mode=(value)
229
@display_mode = case value
230
when 0: @frame_rate?((@frame_rate / @display_fps).round):2
240
def camera_mode=(value)
243
@status_proc.call("Changing camera mode...", true)
245
set('Trigger.Source', @trigger)
250
@frame_rate = get_integer('FrameRate', 10)
251
@display_mode = (@frame_rate / @display_fps).round if @display_mode > 1
257
@set_request.push(lambda {
258
trigger = set('Trigger.Source', value * 2)
259
@trigger = Integer(trigger[1..(trigger.length-1)])
260
if @trigger == 0 then
261
@frame_rate = get_integer('FrameRate', 10)
262
@display_mode = (@frame_rate / @display_fps).round if @display_mode > 1
271
@set_request.push(lambda {
272
@exposure = set('ExposureTime', value)
273
@frame_rate = get_integer('FrameRate', 10) if @trigger == 0
277
def set_resolution(res)
280
@status_proc.call("Changing resolution...", true)
281
@width, @height = res
283
set('Window.W', @width);
284
set('Window.H', @height);
286
if @trigger == 0 then
287
@frame_rate = get_integer('FrameRate', 10)
288
@display_mode = (@frame_rate / @display_fps).round if @display_mode > 1
294
def start_capture(storage, duration, &stop_action)
295
if storage == 0 and @frame_rate then
296
size = @width * @height * @frame_rate * duration
297
if (100 + 1.02 * size) > $freemem then
302
@images = (storage>0)?nil:Array.new()
303
@image_frames = Array.new()
306
#GC.start may cause frame lose, it somehow prevented by calling it after GUI initialization, but still it is possible
313
#@session = time.to_i
314
@session = sprintf("%02i%02i%02i_%02i%02i%02i", time.year, time.month, time.day, time.hour, time.min, time.sec)
315
FileUtils::mkdir_p("saved_camera_images/" + @session) if (storage > 0)
317
@stop_capture = Time.now + duration
318
@stop_action = stop_action
319
@capture_storage = storage
327
@stop_capture = Time.now
331
yield(@capture_width, @capture_height, @images?@images:@capture_session, @image_frames)