dealwithify 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rmagick', "2.12.0", :require => 'RMagick'
data/Gemfile.lock ADDED
@@ -0,0 +1,10 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ rmagick (2.12.0)
5
+
6
+ PLATFORMS
7
+ ruby
8
+
9
+ DEPENDENCIES
10
+ rmagick (= 2.12.0)
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/dealwithify ADDED
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'dealwithify'
5
+ require 'net/http'
6
+ require 'open-uri'
7
+ require 'json'
8
+ require 'RMagick'
9
+
10
+ FACE_API_KEY = ENV['FACE_API_KEY']
11
+ FACE_API_SECRET = ENV['FACE_API_SECRET']
12
+ tmp_glasses = Magick::Image.read(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'glasses.png')).first
13
+ tmp_glasses.format = 'gif'
14
+ GLASSES = tmp_glasses
15
+
16
+ ORIG_GLASSES_MID_X, ORIG_GLASSES_MID_Y = [210, 30]
17
+ FLIP_GLASSES_MID_X, FLIP_GLASSES_MID_Y = [115, 23]
18
+ GLASSES_WIDTH_MULTIPLIER = 2.7
19
+
20
+ def angle_between_eyes(left_eye, right_eye)
21
+ Math.atan((right_eye['y'] - left_eye['y'])/(right_eye['x'] - left_eye['x'])) * 180.0 / Math::PI
22
+ end
23
+
24
+ def rotate_point(center, point, angle)
25
+ cx, cy = center
26
+ px, py = point
27
+
28
+ distance = Math.sqrt((cx-px)**2 + (cy-py)**2)
29
+
30
+ [cx + Math.sin(Math::PI/180.0 * angle)*distance, cy + Math.cos(-Math::PI/180.0 * angle)*distance]
31
+ end
32
+
33
+ # Returns an overlaid image (image1 over image2) such that the point at coords coords1 on image1
34
+ # are over the point at coords2 on image2
35
+ def align_images(image1, image2, coords1, coords2)
36
+ x1, y1 = coords1
37
+ x2, y2 = coords2
38
+ x_shift = x2 - x1
39
+ y_shift = y2 - y1
40
+ image2.composite(image1, x_shift, y_shift, Magick::OverCompositeOp)
41
+ end
42
+
43
+ img_src = ARGV[0]
44
+ if img_src
45
+ response = Net::HTTP.get(URI("http://api.face.com/faces/detect.json?api_key=#{FACE_API_KEY}&api_secret=#{FACE_API_SECRET}&urls=#{img_src}"))
46
+ parsed_response = JSON.parse(response)
47
+
48
+ tags = parsed_response['photos'].first['tags']
49
+ rotate = false #!(params[:rotate]=='false' || params[:rotate]=='no')
50
+ flip_flag = false #!(params[:flip]=='false' || params[:flip]=='no')
51
+
52
+ final = Magick::ImageList.new
53
+
54
+ original_image = Magick::Image.read(img_src).first
55
+ 10.downto(1).each do |n|
56
+ cur_frame = original_image.dup
57
+ tags.each do |tag|
58
+ left_eye = tag['eye_left']
59
+ right_eye = tag['eye_right']
60
+ if left_eye && right_eye
61
+ eye_angle = angle_between_eyes(left_eye, right_eye)
62
+ flip = tag['yaw'] > 0 && flip_flag
63
+ cur_frame = DealWithify::DealWithIt.new(left_eye, right_eye, eye_angle, cur_frame, rotate, flip).shifted_glasses(-10 * n)
64
+ end
65
+ end
66
+ final << cur_frame
67
+ end
68
+
69
+ centered_frame = Magick::Image.read(img_src).first
70
+ tags.each do |tag|
71
+ left_eye = tag['eye_left']
72
+ right_eye = tag['eye_right']
73
+ if left_eye && right_eye
74
+ eye_angle = angle_between_eyes(left_eye, right_eye)
75
+ flip = tag['yaw'] > 0 && flip_flag
76
+ centered_frame = DealWithify::DealWithIt.new(left_eye, right_eye, eye_angle, centered_frame, rotate, flip).centered_glasses
77
+ end
78
+ end
79
+
80
+ txt = Magick::Draw.new
81
+ centered_frame = centered_frame.annotate(txt, 0,0,0,0, 'Deal with it'){
82
+ txt.font_family = 'monospace'
83
+ txt.gravity = Magick::SouthGravity
84
+ txt.pointsize = 36
85
+ txt.stroke = '#ffffff'
86
+ txt.stroke_width = 2
87
+ txt.fill = '#000000'
88
+ txt.font_weight = Magick::BoldWeight
89
+ }
90
+
91
+ 5.times { final << centered_frame.dup }
92
+
93
+ #final.to_blob
94
+ img_uri = URI.parse(img_src)
95
+ file = img_uri.path.split('/')[-1]
96
+ filename = file.chomp(File.extname(file))
97
+ final.write("#{filename}.gif")
98
+ else
99
+ puts <<-eos
100
+ Give it a url!
101
+ dealwithify url
102
+
103
+ example:
104
+ dealwithify http://facebook.com/profile.jpg
105
+ eos
106
+ end
data/config.ru ADDED
@@ -0,0 +1,2 @@
1
+ require './server.rb'
2
+ run Sinatra::Application
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'dealwithify/version'
4
+
5
+ Gem::Specification.new do |g|
6
+ g.name = "dealwithify"
7
+ g.version = DealWithify::VERSION
8
+ g.platform = Gem::Platform::RUBY
9
+ g.authors = ["Tomer Elmalem"]
10
+ g.email = ["telmalem@gmail.com"]
11
+ g.homepage = "https://github.com/tomelm/deal-withify"
12
+ g.summary = ""
13
+ g.description = %q{CLI for Dealwithify}
14
+
15
+ g.files = `git ls-files`.split("\n")
16
+ g.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ g.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
+ g.require_paths = ["lib"]
19
+
20
+ g.add_dependency 'rmagick'
21
+ end
data/glasses.png ADDED
Binary file
@@ -0,0 +1,3 @@
1
+ module DealWithify
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,75 @@
1
+ require 'dealwithify/version'
2
+
3
+ module DealWithify
4
+ class DealWithIt
5
+ def initialize(left_eye, right_eye, angle, img, rotate, flip)
6
+ @img = img
7
+ @img.format = 'gif'
8
+ @rotate = rotate
9
+ @flip = flip
10
+ @img_width = @img.columns
11
+ @img_height = @img.rows
12
+ @saved_glasses = nil
13
+
14
+ left_eye_x = left_eye['x'] * @img_width / 100.0
15
+ left_eye_y = left_eye['y'] * @img_height / 100.0
16
+ right_eye_x = right_eye['x'] * @img_width / 100.0
17
+ right_eye_y = right_eye['y'] * @img_height / 100.0
18
+
19
+ @eye_distance = Math.sqrt((left_eye_x - right_eye_x)**2 + (left_eye_y - right_eye_y)**2)
20
+ eye_midpoint_x = left_eye_x + (right_eye_x - left_eye_x)/2.0
21
+ eye_midpoint_y = left_eye_y + (right_eye_y - left_eye_y)/2.0
22
+ @eye_midpoint = [eye_midpoint_x, eye_midpoint_y]
23
+ @angle = angle
24
+ end
25
+
26
+ def shrunk_glasses_dimensions
27
+ new_width = @eye_distance * GLASSES_WIDTH_MULTIPLIER
28
+ scale = new_width / GLASSES.columns.to_f
29
+ new_height = scale * GLASSES.rows.to_f
30
+ [new_width, new_height]
31
+ end
32
+
33
+ def scaled_and_rotated_glasses
34
+ return @saved_glasses if @saved_glasses
35
+ new_glasses = GLASSES.resize(*self.shrunk_glasses_dimensions, Magick::TriangleFilter, 0.5)
36
+ new_glasses.background_color = 'none'
37
+ new_glasses.format = 'png'
38
+
39
+ new_glasses.flop! if @flip
40
+ new_glasses.rotate!(@angle) if @rotate
41
+
42
+ @saved_glasses = new_glasses
43
+ end
44
+
45
+ def glasses_midpoint
46
+ gwidth, gheight = self.shrunk_glasses_dimensions
47
+ scale = gwidth / GLASSES.columns.to_f
48
+ if @flip
49
+ [FLIP_GLASSES_MID_X * scale, FLIP_GLASSES_MID_Y * scale]
50
+ else
51
+ [ORIG_GLASSES_MID_X * scale, ORIG_GLASSES_MID_Y * scale]
52
+ end
53
+ end
54
+
55
+ def scaled_and_rotated_glasses_midpoint
56
+ midx, midy = self.glasses_midpoint
57
+ if @rotate
58
+ # midx += 50 * Math.cos(@angle * Math::PI/180)
59
+ # This pushes the glasses up the nose a bit.
60
+ midy += (50 * Math.sin(@angle * Math::PI/180)).abs
61
+ end
62
+ [midx, midy]
63
+ end
64
+
65
+ def centered_glasses
66
+ align_images(self.scaled_and_rotated_glasses, @img, self.scaled_and_rotated_glasses_midpoint, @eye_midpoint)
67
+ end
68
+
69
+ def shifted_glasses(y_shift)
70
+ glasses_mid_x, glasses_mid_y = self.scaled_and_rotated_glasses_midpoint
71
+ glasses_mid_y -= y_shift
72
+ align_images(self.scaled_and_rotated_glasses, @img, [glasses_mid_x, glasses_mid_y], @eye_midpoint)
73
+ end
74
+ end
75
+ end
data/readme.md ADDED
@@ -0,0 +1,32 @@
1
+ DealWithify CLI
2
+ ===============
3
+ Command line interface for the Dealwithify app by Brian Stanwyck.
4
+
5
+ Prerequisites
6
+ -------------
7
+ * ImageMagick + RMagick
8
+
9
+ * Face.com API key and API secret set to environment variables
10
+
11
+ Usage
12
+ -----
13
+ Install the gem
14
+
15
+ gem install dealwithify
16
+
17
+ Run!
18
+
19
+ dealwithify https://fbcdn-sphotos-a.akamaihd.net/hphotos-ak-ash3/579380_3706063060148_602358919_n.jpg
20
+
21
+ This will create a .gif in your local directory that you will need to upload somewhere!
22
+
23
+ Result
24
+
25
+ http://i.imgur.com/A5lZ4.gif
26
+
27
+ Setting environment variables
28
+ -----------------------------
29
+ Paste these two lines into your .bashrc or .zshrc
30
+
31
+ export FACE_API_KEY = 'your api key'
32
+ export FACE_API_SECRET = 'your api secret'
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dealwithify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tomer Elmalem
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rmagick
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: CLI for Dealwithify
31
+ email:
32
+ - telmalem@gmail.com
33
+ executables:
34
+ - dealwithify
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - .gitignore
39
+ - Gemfile
40
+ - Gemfile.lock
41
+ - Rakefile
42
+ - bin/dealwithify
43
+ - config.ru
44
+ - dealwithify.gemspec
45
+ - glasses.png
46
+ - lib/dealwithify.rb
47
+ - lib/dealwithify/version.rb
48
+ - readme.md
49
+ homepage: https://github.com/tomelm/deal-withify
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project:
69
+ rubygems_version: 1.8.24
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: ''
73
+ test_files: []