capture_camera 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in capture_camera.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require "bundler/gem_tasks"
2
+
3
+
4
+ namespace :build do
5
+ desc "Build and Run Capture Test Extention"
6
+ task :capture do
7
+ base_path = File.expand_path(".", File.dirname(__FILE__))
8
+ frameworks = %W(Foundation Cocoa QTKit QuartzCore).map {|framework| "-framework #{framework}"}.join(" ")
9
+ include_path = %Q{-I #{base_path}/ext}
10
+ output_file = "#{base_path}/test/CaptureTest"
11
+ main_file = "#{base_path}/test/CaptureTest.m #{base_path}/ext/CapturePhoto.m"
12
+
13
+ system("rm #{output_file}") if File.exists?(output_file)
14
+
15
+ command = %Q{ gcc -arch x86_64 -ObjC -Wall -Wimplicit-function-declaration -lobjc #{frameworks} #{include_path} -o #{output_file} #{main_file} }
16
+
17
+ puts command, "\n"
18
+ system(command)
19
+
20
+ if File.exists?(output_file)
21
+ system("chmod +x #{output_file}")
22
+ puts "Run: #{output_file}"
23
+ puts "-----", "\n"
24
+ system("#{output_file}")
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "capture_camera/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "capture_camera"
7
+ s.version = CaptureCamera::VERSION
8
+ s.authors = ["Fernando Barajas"]
9
+ s.email = ["fernyb@fernyb.net"]
10
+ s.homepage = ""
11
+ s.summary = %q{Take a photo from the macbook camera}
12
+ s.description = %q{Take a photo from the macbook camera}
13
+
14
+ s.rubyforge_project = "capture_camera"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.extensions = ["ext/extconf.rb"]
20
+ s.require_paths = ["lib"]
21
+
22
+ # specify any dependencies here; for example:
23
+ # s.add_development_dependency "rspec"
24
+ # s.add_runtime_dependency "rest-client"
25
+ end
data/ext/Capture.c ADDED
@@ -0,0 +1,54 @@
1
+ #import "Capture.h"
2
+ #import "CapturePhoto.h"
3
+
4
+ NSString * to_nsstring(VALUE string)
5
+ {
6
+ if (string == Qnil) {
7
+ return [NSString string];
8
+ }
9
+ else {
10
+ printf(StringValuePtr(string));
11
+ return [NSString stringWithCString:StringValuePtr(string) encoding:NSASCIIStringEncoding];
12
+ }
13
+ }
14
+
15
+ void Init_Capture() {
16
+ Capture = rb_define_module("Capture");
17
+ rb_define_method(Capture, "take_photo", method_take_photo, 1);
18
+ }
19
+
20
+ CGSize size_from_array(VALUE array) {
21
+ long len = RARRAY_LEN(array);
22
+ int sizeWidth = 0;
23
+ int sizeHeight = 0;
24
+
25
+ if(len == 2) {
26
+ sizeWidth = FIX2INT(rb_ary_entry(array, 0));
27
+ sizeHeight = FIX2INT(rb_ary_entry(array, 1));
28
+ } else {
29
+ rb_raise(rb_eArgError, "size wrong number of arguments (%d for 2)", len);
30
+ }
31
+ return CGSizeMake(sizeWidth, sizeHeight);
32
+ }
33
+
34
+ void method_take_photo(VALUE self, VALUE options)
35
+ {
36
+ Check_Type(options, T_HASH);
37
+ VALUE filename = rb_hash_aref(options, ID2SYM(rb_intern("filename")));
38
+ VALUE size = rb_hash_aref(options, ID2SYM(rb_intern("size")));
39
+
40
+ Check_Type(size, T_ARRAY);
41
+
42
+ NSAutoreleasePool * pool = [NSAutoreleasePool new];
43
+ CapturePhoto * camera = [[CapturePhoto alloc] init];
44
+ if([camera failedToInitialize]) {
45
+ [camera release];
46
+ } else {
47
+ [camera setFilename:to_nsstring(filename)];
48
+ [camera setSize:size_from_array(size)];
49
+
50
+ [camera begin];
51
+ [camera release];
52
+ }
53
+ [pool drain];
54
+ }
data/ext/Capture.h ADDED
@@ -0,0 +1,11 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <QTKit/QTKit.h>
3
+ #import <QuartzCore/QuartzCore.h>
4
+ #import "ruby.h"
5
+
6
+ NSString * to_nsstring(VALUE string);
7
+
8
+ VALUE Capture = Qnil;
9
+ void Init_Capture();
10
+ void method_take_photo();
11
+ CGSize size_from_array(VALUE hash);
@@ -0,0 +1,34 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <Cocoa/Cocoa.h>
3
+ #import <QTKit/QTKit.h>
4
+ #import <QuartzCore/QuartzCore.h>
5
+
6
+
7
+ @interface CapturePhoto : NSObject {
8
+ CVImageBufferRef currentImage;
9
+ BOOL failedToInitialize;
10
+
11
+ QTCaptureDevice * video;
12
+ QTCaptureDecompressedVideoOutput * output;
13
+ QTCaptureInput * input;
14
+ QTCaptureSession * session;
15
+
16
+ NSInteger delay;
17
+ BOOL didTakePhoto;
18
+
19
+ NSString * filename;
20
+ CGSize size;
21
+ }
22
+
23
+ @property(readonly) BOOL failedToInitialize;
24
+ @property(assign) NSInteger delay;
25
+ @property(copy) NSString * filename;
26
+ @property(assign) CGSize size;
27
+
28
+ - (void)initVars;
29
+ - (void)begin;
30
+ - (void)photoTaken:(NSData *)imageData;
31
+ - (NSData *)dataFromImage:(NSImage *)anImage;
32
+ - (CIImage *)applyFiltersForImageBuffer:(CVImageBufferRef)imageBufferRef;
33
+
34
+ @end
@@ -0,0 +1,186 @@
1
+ #import "CapturePhoto.h"
2
+
3
+ @implementation CapturePhoto
4
+ @synthesize failedToInitialize;
5
+ @synthesize delay;
6
+ @synthesize filename, size;
7
+
8
+ - (id)init
9
+ {
10
+ self = [super init];
11
+ [self initVars];
12
+ return self;
13
+ }
14
+
15
+ - (void)initVars
16
+ {
17
+ didTakePhoto = NO;
18
+ delay = 1;
19
+ NSError * error = nil;
20
+
21
+ // Get default input device and open it
22
+ video = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo];
23
+ BOOL success = [video open:&error];
24
+
25
+ if (!success || error != nil) {
26
+ NSLog(@"Error Could Not Open Device");
27
+ failedToInitialize = YES;
28
+ return;
29
+ }
30
+
31
+ input = [[QTCaptureDeviceInput alloc] initWithDevice:video];
32
+ session = [QTCaptureSession new];
33
+ success = [session addInput:input error:&error];
34
+
35
+ if (!success || error != nil) {
36
+ NSLog(@"Error could not add input into session");
37
+ failedToInitialize = YES;
38
+ return;
39
+ }
40
+
41
+ output = [QTCaptureDecompressedVideoOutput new];
42
+ [output setDelegate:self];
43
+
44
+ success = [session addOutput:output error:&error];
45
+ if (!success || error != nil) {
46
+ NSLog(@"Error session failed to add output");
47
+ failedToInitialize = YES;
48
+ return;
49
+ }
50
+
51
+ currentImage = nil;
52
+ }
53
+
54
+ - (void)photoTaken:(NSData *)imageData
55
+ {
56
+ if([self filename]) {
57
+ NSString * saveFilePath = [[NSString stringWithFormat:@"%@", [self filename]] stringByExpandingTildeInPath];
58
+ [imageData writeToFile:saveFilePath atomically:NO];
59
+ }
60
+ }
61
+
62
+ - (void)begin
63
+ {
64
+ [session startRunning];
65
+
66
+ NSDate * now = [[NSDate alloc] init];
67
+ [[NSRunLoop currentRunLoop] runUntilDate:[now dateByAddingTimeInterval:(double)delay]];
68
+ [now release];
69
+
70
+ BOOL didTake = NO;
71
+
72
+ while( didTake == NO ) {
73
+ @synchronized(self) {
74
+ didTake = didTakePhoto;
75
+ }
76
+
77
+ if( didTake == NO ) { // Wait until the photo is taken...
78
+ [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]];
79
+ }
80
+ } // end while
81
+
82
+ // Stop the session
83
+ [session stopRunning];
84
+ }
85
+
86
+ - (void)captureOutput:(QTCaptureOutput *)captureOutput
87
+ didOutputVideoFrame:(CVImageBufferRef)videoFrame
88
+ withSampleBuffer:(QTSampleBuffer *)sampleBuffer
89
+ fromConnection:(QTCaptureConnection *)connection
90
+ {
91
+ // If we already have an image we should use that instead
92
+ if ( currentImage ) return;
93
+
94
+ // Retain the videoFrame so it won't disappear
95
+ // don't forget to release!
96
+ CVBufferRetain(videoFrame);
97
+
98
+ // The Apple docs state that this action must be synchronized
99
+ // as this method will be run on another thread
100
+ @synchronized (self) {
101
+ currentImage = videoFrame;
102
+ }
103
+
104
+ // As stated above, this method will be called on another thread, so
105
+ // we perform the selector that handles the image on the main thread
106
+ [self performSelectorOnMainThread:@selector(saveImage) withObject:nil waitUntilDone:NO];
107
+ }
108
+
109
+ - (NSData *)dataFromImage:(NSImage *)anImage
110
+ {
111
+ NSData * tiffData = [anImage TIFFRepresentation];
112
+ NSBitmapImageFileType imageType = NSJPEGFileType;
113
+ NSDictionary * imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.9] forKey:NSImageCompressionFactor];
114
+
115
+ NSBitmapImageRep * imageRep = [NSBitmapImageRep imageRepWithData:tiffData];
116
+ NSData * photoData = [imageRep representationUsingType:imageType properties:imageProps];
117
+ return photoData;
118
+ }
119
+
120
+ - (CIImage *)applyFiltersForImageBuffer:(CVImageBufferRef)imageBufferRef
121
+ {
122
+ CIImage * inputImage = [CIImage imageWithCVImageBuffer:imageBufferRef];
123
+ CGRect extent = [inputImage extent];
124
+ CGSize inputImageSize = extent.size;
125
+
126
+ CGFloat targetAspectRation = [self size].width / [self size].height;
127
+ CGFloat inputAspectRation = inputImageSize.width / inputImageSize.height;
128
+ CGFloat scaleFactor;
129
+
130
+ if (inputAspectRation > targetAspectRation) {
131
+ scaleFactor = inputImageSize.height / [self size].height;
132
+ } else {
133
+ scaleFactor = inputImageSize.width / [self size].width;
134
+ }
135
+
136
+ CIFilter *scaleFilter = [CIFilter filterWithName:@"CILanczosScaleTransform"];
137
+ [scaleFilter setDefaults];
138
+ [scaleFilter setValue:inputImage forKey:@"inputImage"];
139
+ [scaleFilter setValue:[NSNumber numberWithFloat:scaleFactor] forKey:@"inputScale"];
140
+
141
+ return [scaleFilter valueForKey:@"outputImage"];
142
+ }
143
+
144
+
145
+ - (void)saveImage
146
+ {
147
+ CIImage * ciImage = [self applyFiltersForImageBuffer:currentImage];
148
+ NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:ciImage];
149
+
150
+ NSImage * imageCam = [[NSImage alloc] initWithSize:[imageRep size]];
151
+ [imageCam addRepresentation:imageRep];
152
+
153
+ NSData * imageData = [self dataFromImage:imageCam];
154
+
155
+ if ( [self respondsToSelector:@selector(photoTaken:)] ) {
156
+ [self photoTaken:imageData];
157
+ }
158
+
159
+ // Clean up after us
160
+ [imageCam release];
161
+ CVBufferRelease(currentImage); // release the current from since we retained it above.
162
+ currentImage = nil;
163
+ didTakePhoto = YES; // make sure we know the photo has been taken so we can end the while loop
164
+ }
165
+
166
+
167
+ - (void)dealloc
168
+ {
169
+ [super dealloc];
170
+
171
+ // make sure we are not running
172
+ if ([session isRunning]) {
173
+ [session stopRunning];
174
+ }
175
+ // if video cam is open by the current application (which is us) then we should close it
176
+ if ([video isOpen]) {
177
+ [video close];
178
+ }
179
+
180
+ if(session) [session release];
181
+ if(video) [video release];
182
+
183
+ if(filename) [filename release];
184
+ }
185
+
186
+ @end
data/ext/extconf.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'mkmf'
2
+
3
+ $CFLAGS << " -ObjC "
4
+ $LDFLAGS << " -lobjc -framework Foundation -framework Cocoa -framework QTKit -framework QuartzCore"
5
+
6
+ find_header('CapturePhoto.h', '..')
7
+
8
+ extension_name = "Capture"
9
+
10
+ dir_config(extension_name)
11
+
12
+ create_makefile(extension_name)
@@ -0,0 +1,3 @@
1
+ module CaptureCamera
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "capture_camera/version"
2
+ require "Capture"
3
+
4
+ module CaptureCamera
5
+ include Capture
6
+ end
data/test/CaptureTest ADDED
Binary file
@@ -0,0 +1,5 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <QTKit/QTKit.h>
3
+ #import <QuartzCore/QuartzCore.h>
4
+
5
+ int main();
@@ -0,0 +1,16 @@
1
+ #import "CaptureTest.h"
2
+ #import "CapturePhoto.h"
3
+
4
+ int main() {
5
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
6
+
7
+ CapturePhoto * camera = [[CapturePhoto alloc] init];
8
+ [camera setFilename:@"~/Desktop/screen.jpg"];
9
+ [camera setSize:CGSizeMake(640,480)];
10
+
11
+ [camera begin];
12
+ [camera release];
13
+
14
+ [pool drain];
15
+ return 0;
16
+ }
@@ -0,0 +1,8 @@
1
+ require 'capture_camera'
2
+
3
+ include Capture
4
+
5
+ dir = "~/Desktop"
6
+
7
+ take_photo :filename => "#{dir}/#{commit_sha}.jpg",
8
+ :size => [640,480]
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capture_camera
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Fernando Barajas
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-09 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Take a photo from the macbook camera
15
+ email:
16
+ - fernyb@fernyb.net
17
+ executables: []
18
+ extensions:
19
+ - ext/extconf.rb
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - Rakefile
25
+ - capture_camera.gemspec
26
+ - ext/Capture.c
27
+ - ext/Capture.h
28
+ - ext/CapturePhoto.h
29
+ - ext/CapturePhoto.m
30
+ - ext/extconf.rb
31
+ - lib/capture_camera.rb
32
+ - lib/capture_camera/version.rb
33
+ - test/CaptureTest
34
+ - test/CaptureTest.h
35
+ - test/CaptureTest.m
36
+ - test/capture_test.rb
37
+ homepage: ''
38
+ licenses: []
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project: capture_camera
57
+ rubygems_version: 1.8.12
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Take a photo from the macbook camera
61
+ test_files:
62
+ - test/CaptureTest
63
+ - test/CaptureTest.h
64
+ - test/CaptureTest.m
65
+ - test/capture_test.rb