cheers 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .DS_Store
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cheers.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tom-Eric Gerritsen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,59 @@
1
+ Cheers
2
+ ======
3
+
4
+ Cheers randomly generates user avatars from a set of colors and image components.
5
+
6
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_1.png" alt="Example Avatar #1" width="100" height="100"> 
7
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_2.png" alt="Example Avatar #2" width="100" height="100"> 
8
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_3.png" alt="Example Avatar #3" width="100" height="100"> 
9
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_4.png" alt="Example Avatar #4" width="100" height="100"> 
10
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_5.png" alt="Example Avatar #5" width="100" height="100">
11
+
12
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_6.png" alt="Example Avatar #6" width="75" height="75"> 
13
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_7.png" alt="Example Avatar #7" width="75" height="75"> 
14
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_8.png" alt="Example Avatar #8" width="75" height="75"> 
15
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_9.png" alt="Example Avatar #9" width="75" height="75"> 
16
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_10.png" alt="Example Avatar #10" width="75" height="75">
17
+
18
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_11.png" alt="Example Avatar #11" width="50" height="50"> 
19
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_12.png" alt="Example Avatar #12" width="50" height="50"> 
20
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_13.png" alt="Example Avatar #13" width="50" height="50"> 
21
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_14.png" alt="Example Avatar #14" width="50" height="50"> 
22
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_15.png" alt="Example Avatar #15" width="50" height="50">
23
+
24
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_16.png" alt="Example Avatar #16" width="25" height="25"> 
25
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_17.png" alt="Example Avatar #17" width="25" height="25"> 
26
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_18.png" alt="Example Avatar #18" width="25" height="25"> 
27
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_19.png" alt="Example Avatar #19" width="25" height="25"> 
28
+ <img src="https://github.com/eet-nu/cheers/raw/master/doc/example_20.png" alt="Example Avatar #20" width="25" height="25">
29
+
30
+ ## Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ gem 'cheers'
35
+
36
+ And then execute:
37
+
38
+ $ bundle
39
+
40
+ Or install it yourself as:
41
+
42
+ $ gem install cheers
43
+
44
+ ## Usage
45
+
46
+ ````ruby
47
+ require 'cheers'
48
+
49
+ avatar = Cheers::Avatar.new("martins@eet.nu")
50
+ avatar.avatar_file("avatar.png")
51
+ ````
52
+
53
+ ## Contributing
54
+
55
+ 1. Fork it
56
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
57
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
58
+ 4. Push to the branch (`git push origin my-new-feature`)
59
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/cheers/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Mārtiņš Spilners']
6
+ gem.email = ['martins@eet.nu']
7
+ gem.description = %q{Cheers randomly generates user avatars from a set of colors and image components.}
8
+ gem.summary = %q{Generate random user avatars.}
9
+ gem.homepage = 'http://github.com/eet-nu/cheers'
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = 'cheers'
15
+ gem.require_paths = ['lib']
16
+ gem.version = Cheers::VERSION
17
+
18
+ gem.add_dependency 'rmagick'
19
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ $LOAD_PATH << File.expand_path('../', __FILE__)
2
+
3
+ module Cheers
4
+ autoload :VERSION, 'cheers/version'
5
+ autoload :Color, 'cheers/color'
6
+ autoload :Avatar, 'cheers/avatar'
7
+ end
@@ -0,0 +1,161 @@
1
+ require 'RMagick'
2
+ require 'digest/sha1'
3
+ require 'tempfile'
4
+
5
+ module Cheers
6
+ class Avatar
7
+ GEM_ROOT = File.expand_path('../../../', __FILE__)
8
+
9
+ BACKGROUND_COLORS = ['#cccccc', '#dddddd', '#bbbbbb', '#F1A800', '#FEF0CC', '#fd4238', '#fff0f0', '#14899d', '#c3ecee', '#42991a', '#f0fff0']
10
+ # SMILE_COLORS = ['#333', '#666', '#9e005d', '#ef8200', '#d8a129', '#db4640', '#0e788b', '#239340']
11
+ SMILE_COLORS = ['#333333', '#666666', '#9e005d', '#ef8200', '#db4640', '#0e788b', '#239340']
12
+ IMAGES = {
13
+
14
+ smiles: [
15
+ { smile: 'components/mouths/1-smile.png',
16
+ smile_glow: 'components/mouths/1-smile-glow.png',
17
+ bg_mask: 'components/mouths/1-bgmask.png',
18
+ texture: 'components/texture.png' },
19
+ { smile: 'components/mouths/2-smile.png',
20
+ smile_glow: 'components/mouths/2-smile-glow.png',
21
+ bg_mask: 'components/mouths/2-bgmask.png',
22
+ texture: 'components/texture.png' },
23
+ { smile: 'components/mouths/3-smile.png',
24
+ smile_glow: 'components/mouths/3-smile-glow.png',
25
+ bg_mask: 'components/mouths/3-bgmask.png',
26
+ texture: 'components/texture.png' }
27
+ ],
28
+ eyes: [
29
+ { eyes: 'components/eyes/1.png' },
30
+ { eyes: 'components/eyes/2.png' },
31
+ { eyes: 'components/eyes/3.png' },
32
+ { eyes: 'components/eyes/4.png' },
33
+ { eyes: 'components/eyes/5.png' }
34
+ ],
35
+ decorations: [
36
+ { id: 1, decoration: 'components/decorations/1.png' },
37
+ { id: 2, decoration: 'components/decorations/2.png' }
38
+ ]
39
+ }
40
+
41
+ # Creates a new avatar from the seed string
42
+ def initialize(seed)
43
+ @seed = Digest::SHA1.hexdigest(seed).to_i(16)
44
+ end
45
+
46
+ # Writes avatar image at the provided file path
47
+ def avatar_file(file_path)
48
+ compose_avatar
49
+
50
+ @avatar.write(file_path)
51
+
52
+ file_path
53
+ end
54
+
55
+ private
56
+
57
+ def compose_avatar #:nodoc:
58
+ random_generator = Random.new(@seed)
59
+
60
+ # 0. Let's get some random colors
61
+ # We shoudn't change the order we call #rand to keep version changes minimal
62
+ avatar_bg_color = BACKGROUND_COLORS.sample(random: random_generator)
63
+ smile_components = IMAGES[:smiles].sample(random: random_generator)
64
+ smile_bg_color = BACKGROUND_COLORS.sample(random: random_generator)
65
+ # smile_color = SMILE_COLORS.sample(random: random_generator)
66
+ # eyes_color = SMILE_COLORS.sample(random: random_generator)
67
+ eyes_components = IMAGES[:eyes].sample(random: random_generator)
68
+ smile_upper_glow_color = SMILE_COLORS.sample(random: random_generator)
69
+ smile_lower_glow_color = SMILE_COLORS.sample(random: random_generator)
70
+ has_decoration = [true, true, false].sample(random: random_generator)
71
+ decoration_component = IMAGES[:decorations].sample(random: random_generator)
72
+ decoration_color = BACKGROUND_COLORS.sample(random: random_generator)
73
+
74
+ # Lets test if the color behind eyes is very similar to the eye color.
75
+ # Generate a new eye color if that's the case.
76
+ eyes_contrasting_color = if has_decoration and decoration_component[:id] == 1
77
+ decoration_color
78
+ else
79
+ avatar_bg_color
80
+ end
81
+
82
+ # Lets not use the same random generator for generating unknown amount of new colors
83
+ rng = Random.new(random_generator.rand(10000))
84
+ begin
85
+ eyes_color = SMILE_COLORS.sample(random: rng)
86
+ end while Color.new(eyes_color).similar?(eyes_contrasting_color, 0.2)
87
+
88
+ # Lets test if the background colors are very similar to the smile color.
89
+ # Change the smile color if that's the case, right?
90
+ rng = Random.new(random_generator.rand(10000))
91
+ begin
92
+ smile_color = SMILE_COLORS.sample(random: rng)
93
+ the_smile_color = Color.new(smile_color)
94
+ end while the_smile_color.similar?(avatar_bg_color, 0.2) or the_smile_color.similar?(smile_bg_color, 0.2)
95
+
96
+
97
+ # 1. Lets create upper background
98
+ upper_background = Magick::Image.new(512, 512) { self.background_color = avatar_bg_color }
99
+
100
+ # This is smile glow mask
101
+ smile_glow_image = Magick::Image.read(component_path(smile_components[:smile_glow]))[0]
102
+
103
+ # Create smile glow layer and put it on upper background
104
+ smile_upper_glow = Magick::Image.new(512, 512) { self.background_color = smile_upper_glow_color }
105
+ upper_background.add_compose_mask(smile_glow_image)
106
+ upper_background.composite!(smile_upper_glow, 0, 0, Magick::OverCompositeOp)
107
+ upper_background.delete_compose_mask
108
+
109
+
110
+ # 2. Lets create lower background
111
+ lower_background = Magick::Image.new(512, 512) { self.background_color = smile_bg_color }
112
+
113
+ # Create another smile glow layer but put it on lower background
114
+ smile_lower_glow = Magick::Image.new(512, 512) { self.background_color = smile_lower_glow_color }
115
+ lower_background.add_compose_mask(smile_glow_image)
116
+ lower_background.composite!(smile_lower_glow, 0, 0, Magick::OverCompositeOp)
117
+ lower_background.delete_compose_mask
118
+
119
+
120
+ # 3. Lets compose both backgrounds together
121
+
122
+ # This will be the final avatar image.
123
+ # Because we will draw the lower background over the upper background,
124
+ # we can use the upper background as the starting image.
125
+ avatar = upper_background
126
+
127
+ # Lets mask and put the lower background on top of the image
128
+ avatar.add_compose_mask(Magick::Image.read(component_path(smile_components[:bg_mask]))[0])
129
+ avatar.composite!(lower_background, 0, 0, Magick::OverCompositeOp)
130
+ avatar.delete_compose_mask
131
+
132
+ # 4. Add decorations
133
+ if has_decoration
134
+ decoration = Magick::Image.new(512, 512) { self.background_color = decoration_color }
135
+ avatar.add_compose_mask(Magick::Image.read(component_path(decoration_component[:decoration]))[0])
136
+ avatar.composite!(decoration, 0, 0, Magick::OverCompositeOp)
137
+ avatar.delete_compose_mask
138
+ end
139
+
140
+ # 5. Add the texture
141
+ texture = Magick::Image.read(component_path(smile_components[:texture]))[0]
142
+ avatar.composite!(texture, 0, 0, Magick::OverCompositeOp)
143
+
144
+ smile = Magick::Image.new(512, 512) { self.background_color = smile_color }
145
+ avatar.add_compose_mask(Magick::Image.read(component_path(smile_components[:smile]))[0])
146
+ avatar.composite!(smile, 0, 0, Magick::OverCompositeOp)
147
+ avatar.delete_compose_mask
148
+
149
+ eyes = Magick::Image.new(512, 512) { self.background_color = eyes_color }
150
+ avatar.add_compose_mask(Magick::Image.read(component_path(eyes_components[:eyes]))[0])
151
+ avatar.composite!(eyes, 0, 0, Magick::OverCompositeOp)
152
+ avatar.delete_compose_mask
153
+
154
+ @avatar = avatar
155
+ end
156
+
157
+ def component_path(asset) #:nodoc:
158
+ [GEM_ROOT, asset].join('/')
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,57 @@
1
+ module Cheers
2
+
3
+ # Represents a color and allows to compare to others (maybe)
4
+ class Color
5
+ attr_accessor :r, :g, :b
6
+
7
+ # Create new color from a hex value
8
+ def initialize(color = '#000000')
9
+ hex_string = color[1..6]
10
+ self.r = hex_string[0..1].to_i(16)
11
+ self.g = hex_string[2..3].to_i(16)
12
+ self.b = hex_string[4..5].to_i(16)
13
+ end
14
+
15
+ #
16
+ def to_s
17
+ return '#' + r.to_s(16) + g.to_s(16) + b.to_s(16)
18
+ end
19
+
20
+ def to_hsv
21
+ red, green, blue = [r, g, b].collect {|x| x / 255.0}
22
+ max = [red, green, blue].max
23
+ min = [red, green, blue].min
24
+
25
+ if min == max
26
+ hue = 0
27
+ elsif max == red
28
+ hue = 60 * ((green - blue) / (max - min))
29
+ elsif max == green
30
+ hue = 60 * ((blue - red) / (max - min)) + 120
31
+ elsif max == blue
32
+ hue = 60 * ((red - green) / (max - min)) + 240
33
+ end
34
+
35
+ saturation = (max == 0) ? 0 : (max - min) / max
36
+ [hue % 360, saturation, max]
37
+ end
38
+
39
+ def similar?(other_color, threshold)
40
+ other_color = Color.new(other_color) unless other_color.is_a? Color
41
+
42
+ color_hsv = to_hsv
43
+ other_color_hsv = other_color.to_hsv
44
+
45
+ d_hue = (color_hsv[0] - other_color_hsv[0]).abs / 360
46
+ d_saturation = (color_hsv[1] - other_color_hsv[1]).abs
47
+ d_value = (color_hsv[2] - other_color_hsv[2]).abs
48
+
49
+ if d_hue <= threshold and d_saturation <= threshold and d_value <= threshold
50
+ true
51
+ else
52
+ false
53
+ end
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,3 @@
1
+ module Cheers
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cheers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mārtiņš Spilners
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rmagick
16
+ requirement: &70319637709080 !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: *70319637709080
25
+ description: Cheers randomly generates user avatars from a set of colors and image
26
+ components.
27
+ email:
28
+ - martins@eet.nu
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - LICENSE
36
+ - README.md
37
+ - Rakefile
38
+ - cheers.gemspec
39
+ - components/decorations/1.png
40
+ - components/decorations/2.png
41
+ - components/eyes/1.png
42
+ - components/eyes/2.png
43
+ - components/eyes/3.png
44
+ - components/eyes/4.png
45
+ - components/eyes/5.png
46
+ - components/mouths/1-bgmask.png
47
+ - components/mouths/1-smile-glow.png
48
+ - components/mouths/1-smile.png
49
+ - components/mouths/2-bgmask.png
50
+ - components/mouths/2-smile-glow.png
51
+ - components/mouths/2-smile.png
52
+ - components/mouths/3-bgmask.png
53
+ - components/mouths/3-smile-glow.png
54
+ - components/mouths/3-smile.png
55
+ - components/texture.png
56
+ - doc/example_1.png
57
+ - doc/example_10.png
58
+ - doc/example_11.png
59
+ - doc/example_12.png
60
+ - doc/example_13.png
61
+ - doc/example_14.png
62
+ - doc/example_15.png
63
+ - doc/example_16.png
64
+ - doc/example_17.png
65
+ - doc/example_18.png
66
+ - doc/example_19.png
67
+ - doc/example_2.png
68
+ - doc/example_20.png
69
+ - doc/example_3.png
70
+ - doc/example_4.png
71
+ - doc/example_5.png
72
+ - doc/example_6.png
73
+ - doc/example_7.png
74
+ - doc/example_8.png
75
+ - doc/example_9.png
76
+ - lib/cheers.rb
77
+ - lib/cheers/avatar.rb
78
+ - lib/cheers/color.rb
79
+ - lib/cheers/version.rb
80
+ homepage: http://github.com/eet-nu/cheers
81
+ licenses: []
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 1.8.17
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: Generate random user avatars.
104
+ test_files: []