dealwithify 0.0.4

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,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: []