capture_camera 0.0.1

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.
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