motion-capture 1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 098882fee3cdac39ac683f6add7df21009187b01
4
+ data.tar.gz: 95a133286c70f6bab31ce7410056046df6ed2231
5
+ SHA512:
6
+ metadata.gz: 1957c4720f94d8fb3aaf998535a6865fa2b98d37daed7469703920f21167b15b64a029607644345c350d9477584cff1a2524707d76f08997b9e3496411bc06ce
7
+ data.tar.gz: ec63205dae5efc7e59eecbdc569f07b91c99c862dd47952446c5964bdb1ea18e733b19c789d5dbc9a0ac5bd02c72ed2b997cb3bd222f499949964b1feb219e25
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # motion-capture
2
+
3
+ Camera support for custom camera controllers
4
+
5
+ ## Usage
6
+
7
+ motion_capture = Motion::Capture.new
8
+ motion_capture = Motion::Capture.new(device: :front) # specify camera
9
+
10
+ preview = motion_capture.capture_preview_view(frame: view.bounds)
11
+ view.addSubview(preview) # UIView containing AVCaptureVideoPreviewLayer
12
+
13
+ motion_capture.toggle_camera # Switch between front/rear cameras
14
+ motion_capture.toggle_flash # Switch bettwen flash on/off
15
+
16
+ motion_capture.turn_flash_on
17
+ motion_capture.turn_flash_off
18
+
19
+ motion_capture.use_camera(:default)
20
+ motion_capture.use_camera(:front)
21
+ motion_capture.use_camera(:rear)
22
+
23
+ motion_capture.capture do |image|
24
+ # Use UIImage
25
+ end
26
+
27
+ ## Setup
28
+
29
+ Add this line to your application's Gemfile:
30
+
31
+ gem 'motion-capture'
32
+
33
+ And then execute:
34
+
35
+ $ bundle
36
+
37
+ Or install it yourself as:
38
+
39
+ $ gem install motion-capture
40
+
41
+ ## Contributing
42
+
43
+ 1. Fork it
44
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
45
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
46
+ 4. Push to the branch (`git push origin my-new-feature`)
47
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ unless defined?(Motion::Project::Config)
2
+ raise "This file must be required within a RubyMotion project Rakefile."
3
+ end
4
+
5
+ lib_dir_path = File.dirname(File.expand_path(__FILE__))
6
+ Motion::Project::App.setup do |app|
7
+ app.files.unshift(Dir.glob(File.join(lib_dir_path, "project/**/*.rb")))
8
+ end
@@ -0,0 +1,193 @@
1
+ class Motion
2
+ class Capture
3
+ DEFAULT_OPTIONS = { device: :default }
4
+
5
+ attr_accessor :options, :device
6
+
7
+ def initialize(options = {})
8
+ self.options = options.merge(DEFAULT_OPTIONS)
9
+ end
10
+
11
+ def start!
12
+ use_camera(options[:device])
13
+
14
+ add_ouput(still_image_output)
15
+ end
16
+
17
+ def capture(&block)
18
+ still_image_connection = still_image_output.connections.first
19
+
20
+ still_image_output.captureStillImageAsynchronouslyFromConnection(still_image_connection, completionHandler: lambda { |image_data_sample_buffer, error|
21
+ if image_data_sample_buffer
22
+ image_data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(image_data_sample_buffer)
23
+
24
+ image = UIImage.alloc.initWithData(image_data)
25
+
26
+ block.call(image)
27
+ else
28
+ p "Error capturing image: #{error[0].description}"
29
+ end
30
+ })
31
+ end
32
+
33
+ def capture_preview_view(options)
34
+ @_capture_preview_view ||= begin
35
+ start!
36
+
37
+ UIView.alloc.initWithFrame(options.fetch(:frame, CGRectZero)).tap do |view|
38
+ view.backgroundColor = UIColor.whiteColor
39
+
40
+ view.layer.addSublayer(preview_layer_for_view(view))
41
+ end
42
+ end
43
+ end
44
+
45
+ def use_camera(camera)
46
+ device = camera_devices[camera]
47
+
48
+ error = Pointer.new(:object)
49
+
50
+ self.device = device
51
+ input = AVCaptureDeviceInput.deviceInputWithDevice(device, error: error)
52
+
53
+ if input
54
+ set_input(input)
55
+ else
56
+ p error[0].description
57
+ end
58
+ end
59
+
60
+ def toggle_camera
61
+ if using_rear_camera?
62
+ use_camera(:front)
63
+ else
64
+ use_camera(:rear)
65
+ end
66
+ end
67
+
68
+ def toggle_flash
69
+ if device && device.hasFlash
70
+ error = Pointer.new(:object)
71
+ if device.lockForConfiguration(error)
72
+ if flash_on?
73
+ turn_flash_off
74
+ else
75
+ turn_flash_on
76
+ end
77
+
78
+ device.unlockForConfiguration
79
+ else
80
+ p error[0].description
81
+ end
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def set_input(input)
88
+ remove_inputs
89
+
90
+ add_input(input)
91
+ end
92
+
93
+ def set_output(output)
94
+ remove_outputs
95
+
96
+ add_output(output)
97
+ end
98
+
99
+ def remove_inputs
100
+ session.inputs.each do |input|
101
+ remove_input(input)
102
+ end
103
+ end
104
+
105
+ def remove_outputs
106
+ session.outputs.each do |output|
107
+ remove_output(output)
108
+ end
109
+ end
110
+
111
+ def remove_input(input)
112
+ session.removeInput(input)
113
+ end
114
+
115
+ def remove_output(output)
116
+ session.removeOutput(output)
117
+ end
118
+
119
+ def add_input(input)
120
+ session.addInput(input)
121
+ end
122
+
123
+ def add_ouput(output)
124
+ session.addOutput(output)
125
+ end
126
+
127
+ def default_camera
128
+ AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
129
+ end
130
+
131
+ def rear_camera
132
+ capture_devices.select { |device| device.position == camera_position_mapping[:rear] }.first
133
+ end
134
+
135
+ def front_camera
136
+ capture_devices.select { |device| device.position == camera_position_mapping[:front] }.first
137
+ end
138
+
139
+ def using_rear_camera?
140
+ device.position == AVCaptureDevicePositionBack
141
+ end
142
+
143
+ def camera_position_mapping
144
+ { rear: AVCaptureDevicePositionBack, front: AVCaptureDevicePositionFront }
145
+ end
146
+
147
+ def camera_devices
148
+ { default: default_camera, rear: rear_camera, front: front_camera }
149
+ end
150
+
151
+ def capture_devices
152
+ @_capture_devices ||= AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
153
+ end
154
+
155
+ def preview_layer_for_view(view)
156
+ AVCaptureVideoPreviewLayer.layerWithSession(session).tap do |layer|
157
+ layer_bounds = view.layer.bounds
158
+
159
+ layer.bounds = layer_bounds
160
+ layer.position = CGPointMake(CGRectGetMidX(layer_bounds), CGRectGetMidY(layer_bounds))
161
+ layer.videoGravity = AVLayerVideoGravityResizeAspectFill
162
+ end
163
+ end
164
+
165
+ def flash_on?
166
+ device.flashMode == AVCaptureFlashModeOn
167
+ end
168
+
169
+ def turn_flash_on
170
+ device.flashMode = AVCaptureFlashModeOn
171
+ end
172
+
173
+ def turn_flash_off
174
+ device.flashMode = AVCaptureFlashModeOff
175
+ end
176
+
177
+ def session
178
+ @_session ||= AVCaptureSession.alloc.init.tap do |session|
179
+ session.sessionPreset = AVCaptureSessionPresetMedium
180
+
181
+ session.startRunning
182
+ end
183
+ end
184
+
185
+ def still_image_output
186
+ @_still_image_output ||= AVCaptureStillImageOutput.alloc.init.tap do |output|
187
+ settings = { 'AVVideoCodeKey' => AVVideoCodecJPEG }
188
+
189
+ output.setOutputSettings(settings)
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,112 @@
1
+ class GridOverlayView < UIView
2
+ DEFAULTS = { stroke_color: UIColor.grayColor,
3
+ stroke_width: 1.0,
4
+ x_lines: 3,
5
+ y_lines: 3 }
6
+
7
+ attr_accessor :x_interval, :y_interval
8
+ attr_reader :stroke_color, :stroke_width
9
+
10
+ def initWithFrame(frame)
11
+ super.tap do |view|
12
+ view.backgroundColor = UIColor.clearColor
13
+
14
+ self.x_lines = DEFAULTS[:x_lines]
15
+ self.y_lines = DEFAULTS[:y_lines]
16
+ self.stroke_color = DEFAULTS[:stroke_color]
17
+ self.stroke_width = DEFAULTS[:stroke_width]
18
+ end
19
+ end
20
+
21
+ def hidden?
22
+ stroke_color == UIColor.clearColor
23
+ end
24
+
25
+ def toggle
26
+ if hidden?
27
+ show
28
+ else
29
+ hide
30
+ end
31
+ end
32
+
33
+ def show
34
+ self.stroke_color = @original_color
35
+
36
+ setNeedsDisplay
37
+ end
38
+
39
+ def hide
40
+ unless hidden?
41
+ @original_color = stroke_color
42
+
43
+ self.stroke_color = UIColor.clearColor
44
+
45
+ setNeedsDisplay
46
+ end
47
+ end
48
+
49
+ def x_lines=(lines)
50
+ self.x_interval = frame.size.width / lines
51
+
52
+ setNeedsDisplay
53
+ end
54
+
55
+ def y_lines=(lines)
56
+ self.y_interval = frame.size.height / lines
57
+
58
+ setNeedsDisplay
59
+ end
60
+
61
+ def stroke_width=(width)
62
+ @stroke_width = width
63
+
64
+ setNeedsDisplay
65
+ end
66
+
67
+ def stroke_color=(color)
68
+ @stroke_color = color
69
+
70
+ setNeedsDisplay
71
+ end
72
+
73
+ def setup_drawing
74
+ CGContextSetStrokeColorWithColor(context, stroke_color.CGColor)
75
+
76
+ CGContextSetLineWidth(context, stroke_width)
77
+ end
78
+
79
+ def drawRect(rect)
80
+ super
81
+
82
+ setup_drawing
83
+ draw_vertical_lines
84
+ draw_horizontal_lines
85
+
86
+ fill_path
87
+ end
88
+
89
+ def fill_path
90
+ CGContextStrokePath(context)
91
+ end
92
+
93
+ def draw_horizontal_lines
94
+ draw_line([0, y_interval], [size.width, y_interval])
95
+ draw_line([0, y_interval * 2], [size.width, y_interval * 2])
96
+ end
97
+
98
+ def draw_vertical_lines
99
+ draw_line([x_interval, 0], [x_interval, size.height])
100
+ draw_line([x_interval * 2, 0], [x_interval * 2.0, size.height])
101
+ end
102
+
103
+ def draw_line(start_point, end_point)
104
+ CGContextMoveToPoint(context, start_point[0], start_point[1])
105
+
106
+ CGContextAddLineToPoint(context, end_point[0], end_point[1])
107
+ end
108
+
109
+ def context
110
+ @_context ||= UIGraphicsGetCurrentContext()
111
+ end
112
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: motion-capture
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Devon Blandin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: AVFoundation wrapper to support custom camera controllers
28
+ email:
29
+ - dblandin@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.md
35
+ - lib/motion-capture.rb
36
+ - lib/project/motion-capture.rb
37
+ - lib/project/views/overlay_view.rb
38
+ homepage: https://github.com/dblandin/motion-capture
39
+ licenses:
40
+ - MIT
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 2.0.0
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: AVFoundation wrapper to support custom camera controllers
62
+ test_files: []