cheers 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dc530a68f47497a4cb2a01b9cdcdd457c8a74c082363dc2c02c370659df6c54a
4
+ data.tar.gz: 1153a39c5a6caea0c03267623bdb0bafd48e7a404180dfd58ec994fd89feb003
5
+ SHA512:
6
+ metadata.gz: 21d50c1983d5e504f49ddee016740f82952ed10bdf74223f54c4eb6f6330e479548a3a14a51645b3d6bf9fb12a69a827466ce5dd38308bd6ee0d2c9ac6a9e3bf
7
+ data.tar.gz: 1cad389111a13dbcff6642d9f03176de7e23d300592efa1116e3fd0d382739c2340dae3deed37d0d12f7f06d2b875150ef3c5716486f9651b6b9024f7a9299ad
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1 @@
1
+ 2.5.0
data/.rvmrc ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p125@cheers"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.10.3" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
+ \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
+ else
29
+ # If the environment file has not yet been created, use the RVM CLI to select.
30
+ rvm --create "$environment_id" || {
31
+ echo "Failed to create RVM environment '${environment_id}'."
32
+ return 1
33
+ }
34
+ fi
35
+
36
+ # If you use bundler, this might be useful to you:
37
+ if [[ -s Gemfile ]] && {
38
+ ! builtin command -v bundle >/dev/null ||
39
+ builtin command -v bundle | grep $rvm_path/bin/bundle >/dev/null
40
+ }
41
+ then
42
+ printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
43
+ gem install bundler
44
+ fi
45
+ if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
46
+ then
47
+ bundle install | grep -vE '^Using|Your bundle is complete'
48
+ fi
data/Gemfile CHANGED
@@ -1,4 +1,26 @@
1
- source 'https://rubygems.org'
1
+ source :rubygems
2
2
 
3
- # Specify your gem's dependencies in cheers.gemspec
3
+ # Specify the project's dependencies in the gemspec:
4
4
  gemspec
5
+
6
+ # Specifiy the development dependencies here:
7
+ group :development do
8
+ gem 'rake'
9
+
10
+ # Documentation:
11
+ gem 'yard'
12
+
13
+ # Testing libraries:
14
+ gem 'rspec'
15
+
16
+ # Colorful messages:
17
+ gem 'rainbow'
18
+
19
+ # Support for guard:
20
+ gem 'guard'
21
+ gem 'guard-bundler'
22
+ gem 'guard-rspec'
23
+ gem 'rb-fsevent'
24
+ gem 'rb-readline'
25
+ gem 'fuubar'
26
+ end
@@ -0,0 +1,13 @@
1
+ require 'rb-readline'
2
+
3
+ guard 'bundler' do
4
+ watch('Gemfile')
5
+ watch('cheers.gemspec')
6
+ end
7
+
8
+ guard 'rspec', version: 2, cli: '--format Fuubar --colour' do
9
+ watch(%r{^spec/.+_spec\.rb})
10
+ watch(%r{^lib/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{lib/.+\.rb}) { "spec" }
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.push './lib'
4
+ require 'cheers'
5
+
6
+ filename = ARGV[0]
7
+
8
+ unless filename
9
+ puts "Usage: cheers <filename>"
10
+ exit
11
+ end
12
+
13
+ avatar = Cheers::Avatar.new(rand(1000_000).to_s)
14
+ avatar.avatar_file(filename)
@@ -15,5 +15,5 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ['lib']
16
16
  gem.version = Cheers::VERSION
17
17
 
18
- gem.add_dependency 'rmagick'
18
+ gem.add_dependency 'mini_magick'
19
19
  end
Binary file
@@ -2,6 +2,22 @@ $LOAD_PATH << File.expand_path('../', __FILE__)
2
2
 
3
3
  module Cheers
4
4
  autoload :VERSION, 'cheers/version'
5
- autoload :Color, 'cheers/color'
6
- autoload :Avatar, 'cheers/avatar'
5
+
6
+ autoload :Avatar, 'cheers/avatar'
7
+ autoload :Background, 'cheers/background'
8
+ autoload :Color, 'cheers/color'
9
+ autoload :Component, 'cheers/component'
10
+ autoload :ContrastingColorPicker, 'cheers/contrasting_color_picker'
11
+ autoload :Decoration, 'cheers/decoration'
12
+ autoload :Eyes, 'cheers/eyes'
13
+ autoload :Face, 'cheers/face'
14
+ autoload :ImageComponent, 'cheers/image_component'
15
+ autoload :LowerGlow, 'cheers/lower_glow'
16
+ autoload :Mouth, 'cheers/mouth'
17
+ autoload :Texture, 'cheers/texture'
18
+ autoload :UpperGlow, 'cheers/upper_glow'
19
+
20
+ def self.root
21
+ File.expand_path('../../', __FILE__)
22
+ end
7
23
  end
@@ -1,42 +1,16 @@
1
- require 'RMagick'
1
+ require 'mini_magick'
2
2
  require 'digest/sha1'
3
3
  require 'tempfile'
4
4
 
5
5
  module Cheers
6
6
  class Avatar
7
- GEM_ROOT = File.expand_path('../../../', __FILE__)
7
+
8
+ BACKGROUND_COLORS = %w(#cccccc #dddddd #bbbbbb #f1a800 #fef0cc
9
+ #fd4238 #fff0f0 #14899d #c3ecee #42991a
10
+ #f0fff0)
8
11
 
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
- }
12
+ COMPONENT_COLORS = %w(#333333 #666666 #9e005d #ef8200 #db4640
13
+ #0e788b #239340)
40
14
 
41
15
  # Creates a new avatar from the seed string
42
16
  def initialize(seed)
@@ -45,117 +19,32 @@ module Cheers
45
19
 
46
20
  # Writes avatar image at the provided file path
47
21
  def avatar_file(file_path)
48
- compose_avatar
49
-
50
- @avatar.write(file_path)
22
+ avatar = compose_avatar
51
23
 
24
+ avatar.write(file_path)
25
+
52
26
  file_path
53
27
  end
54
28
 
29
+ # Returns a binary version of the image
30
+ def to_blob(format)
31
+ avatar = compose_avatar
32
+
33
+ avatar.format = format
34
+ avatar.to_blob
35
+ end
36
+
55
37
  private
56
38
 
57
39
  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
40
+ generator = Random.new(@seed)
41
+
42
+ result = nil
43
+ [Background, Face, Decoration, Eyes].each do |klass|
44
+ result = klass.new(result, generator).apply
138
45
  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('/')
46
+
47
+ result
159
48
  end
160
49
  end
161
50
  end
@@ -0,0 +1,19 @@
1
+ module Cheers
2
+ class Background < Component
3
+
4
+ attr_reader :color
5
+
6
+ def initialize(canvas, randomizer)
7
+ super
8
+
9
+ @color = Avatar::BACKGROUND_COLORS.sample(random: randomizer)
10
+ end
11
+
12
+ def apply
13
+ # Work around instance_eval wonkiness by declaring local variables:
14
+ color = self.color
15
+
16
+ colored_image(color)
17
+ end
18
+ end
19
+ end
@@ -11,10 +11,12 @@ module Cheers
11
11
  self.g = hex_string[2..3].to_i(16)
12
12
  self.b = hex_string[4..5].to_i(16)
13
13
  end
14
-
15
- #
14
+
15
+ #
16
16
  def to_s
17
- return '#' + r.to_s(16) + g.to_s(16) + b.to_s(16)
17
+ return '#' + r.to_s(16).rjust(2, '0') +
18
+ g.to_s(16).rjust(2, '0') +
19
+ b.to_s(16).rjust(2, '0')
18
20
  end
19
21
 
20
22
  def to_hsv
@@ -36,7 +38,7 @@ module Cheers
36
38
  [hue % 360, saturation, max]
37
39
  end
38
40
 
39
- def similar?(other_color, threshold)
41
+ def similar?(other_color, threshold = 0.1)
40
42
  other_color = Color.new(other_color) unless other_color.is_a? Color
41
43
 
42
44
  color_hsv = to_hsv
@@ -52,6 +54,11 @@ module Cheers
52
54
  false
53
55
  end
54
56
  end
57
+
58
+ def self.rgb_to_hex(rgb)
59
+ hex = rgb.map {|c| c.to_s(16).rjust(2, '0')}.join
60
+ return "##{hex}"
61
+ end
55
62
  end
56
63
 
57
- end
64
+ end
@@ -0,0 +1,50 @@
1
+ module Cheers
2
+ class Component
3
+
4
+ attr_reader :canvas, :randomizer
5
+
6
+ def initialize(canvas, randomizer)
7
+ @canvas = canvas
8
+ @randomizer = randomizer
9
+ end
10
+
11
+ def image_path(component)
12
+ [Cheers.root, 'components', component].join '/'
13
+ end
14
+
15
+ def base_image
16
+ MiniMagick::Image.open(image_path('blank.png'))
17
+ end
18
+
19
+ def colored_image(color)
20
+ image = MiniMagick::Image.open(image_path('blank.png'))
21
+
22
+ image.combine_options do |c|
23
+ c.resize '512x512'
24
+ c.fuzz "100%"
25
+ c.fill color
26
+ c.floodfill "+0+0", 'white'
27
+ end
28
+ end
29
+
30
+ def composite_with_mask(base, second, mask_image)
31
+ mask = MiniMagick::Image.open(image_path(mask_image))
32
+ mask.combine_options do |m|
33
+ m.alpha 'copy'
34
+ end
35
+
36
+ base.composite(second, 'png', mask)
37
+ end
38
+
39
+ # assumes top left pixel is background since none of the parts overlap there
40
+ def extract_background_color(image)
41
+ rgb = image.get_pixels[0][0]
42
+ Color.rgb_to_hex(rgb)
43
+ end
44
+
45
+ def apply
46
+ color = self.color
47
+ composite_with_mask(canvas, colored_image(color), image)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,25 @@
1
+ module Cheers
2
+ class ContrastingColorPicker
3
+
4
+ MAX_RETRIES = 10
5
+
6
+ attr_reader :palette, :colors
7
+
8
+ def initialize(palette, *colors)
9
+ @palette = palette.map { |c| Color.new(c) }
10
+ @colors = colors.map { |c| Color.new(c) }
11
+ end
12
+
13
+ def pick(randomizer = Random.new)
14
+ pick = palette.sample(random: randomizer)
15
+
16
+ try = 0
17
+ while colors.any? { |c| c.similar?(pick) } && try <= MAX_RETRIES
18
+ try += 1
19
+ pick = palette.sample(random: randomizer)
20
+ end
21
+
22
+ pick.to_s
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Cheers
2
+ class Decoration < ImageComponent
3
+
4
+ IMAGES = %w( decorations/1.png
5
+ decorations/2.png )
6
+
7
+ attr_reader :color, :image
8
+
9
+ def initialize(canvas, color_randomizer, image_randomizer = nil)
10
+ super
11
+
12
+ @color = ContrastingColorPicker.new(Avatar::BACKGROUND_COLORS, extract_background_color(canvas)).pick(color_randomizer)
13
+ @image = IMAGES.sample random: self.image_randomizer
14
+ end
15
+
16
+ def apply?
17
+ [true, true, false].sample(random: image_randomizer)
18
+ end
19
+
20
+ def apply
21
+ return canvas unless apply?
22
+ super
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module Cheers
2
+ class Eyes < ImageComponent
3
+
4
+ IMAGES = %w( eyes/1.png
5
+ eyes/2.png
6
+ eyes/3.png
7
+ eyes/4.png
8
+ eyes/5.png )
9
+
10
+ attr_reader :color, :image
11
+
12
+ def initialize(canvas, color_randomizer, image_randomizer = nil)
13
+ super
14
+
15
+ @color = ContrastingColorPicker.new(Avatar::COMPONENT_COLORS, extract_background_color(canvas)).pick(color_randomizer)
16
+ @image = IMAGES.sample random: self.image_randomizer
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module Cheers
2
+ class Face < ImageComponent
3
+
4
+ def apply
5
+ wip = canvas
6
+ [UpperGlow, LowerGlow, Texture, Mouth].each do |klass|
7
+ wip = klass.new(wip, color_randomizer, image_randomizer.dup).apply
8
+ end
9
+
10
+ wip
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Cheers
2
+ class ImageComponent < Component
3
+
4
+ attr_reader :canvas, :color_randomizer, :image_randomizer
5
+
6
+ def initialize(canvas, color_randomizer, image_randomizer = nil)
7
+ @canvas = canvas
8
+ @color_randomizer = color_randomizer
9
+ @image_randomizer = image_randomizer || color_randomizer
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ module Cheers
2
+ class LowerGlow < ImageComponent
3
+
4
+ GLOW_IMAGES = %w( mouths/1-smile-glow.png
5
+ mouths/2-smile-glow.png
6
+ mouths/3-smile-glow.png )
7
+
8
+ MASK_IMAGES = %w( mouths/1-bgmask.png
9
+ mouths/2-bgmask.png
10
+ mouths/3-bgmask.png )
11
+
12
+ attr_reader :background_color, :glow_color, :glow_image, :mask_image
13
+
14
+ def initialize(canvas, color_randomizer, element_randomizer = nil)
15
+ super
16
+
17
+ canvas_background = extract_background_color(canvas)
18
+
19
+ @background_color = ContrastingColorPicker.new(Avatar::BACKGROUND_COLORS, canvas_background).pick(color_randomizer)
20
+ @glow_color = ContrastingColorPicker.new(Avatar::COMPONENT_COLORS, canvas_background, background_color).pick(color_randomizer)
21
+ @glow_image = GLOW_IMAGES.sample random: element_randomizer.dup
22
+ @mask_image = MASK_IMAGES.sample random: element_randomizer.dup
23
+ end
24
+
25
+ def apply
26
+ glow_color = self.glow_color
27
+ background_color = self.background_color
28
+
29
+ background = composite_with_mask(colored_image(background_color), colored_image(glow_color), glow_image)
30
+
31
+ composite_with_mask(canvas, background, mask_image)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ module Cheers
2
+ class Mouth < ImageComponent
3
+
4
+ IMAGES = %w( mouths/1-smile.png
5
+ mouths/2-smile.png
6
+ mouths/3-smile.png )
7
+
8
+ attr_reader :color, :image
9
+
10
+ def initialize(canvas, color_randomizer, element_randomizer = nil)
11
+ super
12
+
13
+ @color = ContrastingColorPicker.new(Avatar::COMPONENT_COLORS, extract_background_color(canvas)).pick(color_randomizer)
14
+ @image = IMAGES.sample random: element_randomizer
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Cheers
2
+ class Texture < ImageComponent
3
+
4
+ IMAGES = %w( texture.png )
5
+
6
+ attr_reader :color, :image
7
+
8
+ def initialize(canvas, color_randomizer, element_randomizer = nil)
9
+ super
10
+
11
+ @image = IMAGES.sample random: element_randomizer
12
+ end
13
+
14
+ def apply
15
+ texture = MiniMagick::Image.open(image_path(image))
16
+ canvas.composite(texture) do |c|
17
+ c.compose "Over" # OverCompositeOp
18
+ c.geometry "+0+0"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ module Cheers
2
+ class UpperGlow < ImageComponent
3
+
4
+ IMAGES = %w( mouths/1-smile-glow.png
5
+ mouths/2-smile-glow.png
6
+ mouths/3-smile-glow.png )
7
+
8
+ attr_reader :color, :image
9
+
10
+ def initialize(canvas, color_randomizer, element_randomizer = nil)
11
+ super
12
+
13
+ @color = ContrastingColorPicker.new(Avatar::COMPONENT_COLORS, extract_background_color(canvas)).pick(color_randomizer)
14
+ @image = IMAGES.sample random: element_randomizer
15
+ end
16
+
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module Cheers
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cheers::Color do
4
+ describe '#initialize' do
5
+ it 'converts 32 bit hexadecimal color values to RGB' do
6
+ color = Cheers::Color.new('#7d7d7d')
7
+ [color.r, color.g, color.b].should == [125, 125, 125]
8
+ end
9
+ end
10
+
11
+ describe '#r' do
12
+ it 'returns the intensity of the red component of the color' do
13
+ black = Cheers::Color.new '#000000'
14
+ black.r.should == 0
15
+
16
+
17
+ white = Cheers::Color.new '#ffffff'
18
+ white.r.should == 255
19
+
20
+ red = Cheers::Color.new '#7d0000'
21
+ red.r.should == 125
22
+ end
23
+ end
24
+
25
+ describe '#g' do
26
+ it 'returns the intensity of the green component of the color' do
27
+ black = Cheers::Color.new '#000000'
28
+ black.g.should == 0
29
+
30
+
31
+ white = Cheers::Color.new '#ffffff'
32
+ white.g.should == 255
33
+
34
+ green = Cheers::Color.new '#007d00'
35
+ green.g.should == 125
36
+ end
37
+ end
38
+
39
+ describe '#b' do
40
+ it 'returns the intensity of the blue component of the color' do
41
+ black = Cheers::Color.new '#000000'
42
+ black.b.should == 0
43
+
44
+
45
+ white = Cheers::Color.new '#ffffff'
46
+ white.b.should == 255
47
+
48
+ blue = Cheers::Color.new '#00007d'
49
+ blue.b.should == 125
50
+ end
51
+ end
52
+
53
+ describe '#to_hsv' do
54
+ it 'returns the HSV values for the color' do
55
+ orange = Cheers::Color.new '#d97621'
56
+ h, s, v = orange.to_hsv
57
+
58
+ h.should be_within(0.001).of 27.717
59
+ s.should be_within(0.001).of 0.848
60
+ v.should be_within(0.001).of 0.851
61
+ end
62
+ end
63
+
64
+ describe '#to_s' do
65
+ it 'returns a hexadecimal representation of the color' do
66
+ color = Cheers::Color.new('#00007d')
67
+ color.to_s.should == '#00007d'
68
+ end
69
+ end
70
+
71
+ describe '#similar?' do
72
+ it 'returns true if the colors are similar' do
73
+ bright_white = Cheers::Color.new '#ffffff'
74
+ broken_white = Cheers::Color.new '#eeeeee'
75
+
76
+ bright_white.similar?(broken_white).should be_true
77
+ broken_white.similar?(bright_white).should be_true
78
+ end
79
+
80
+ it 'returns false if the colors are not similar' do
81
+ white = Cheers::Color.new '#ffffff'
82
+ black = Cheers::Color.new '#000000'
83
+
84
+ white.similar?(black).should be_false
85
+ black.similar?(white).should be_false
86
+ end
87
+
88
+ it 'returns true if the color is too similar for the given treshold' do
89
+ orange_1 = Cheers::Color.new '#f1a800'
90
+ orange_2 = Cheers::Color.new '#ef8200'
91
+
92
+ orange_1.similar?(orange_2, 0.02).should be_false
93
+ orange_1.similar?(orange_2, 0.03).should be_true
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require File.expand_path('../../lib/cheers', __FILE__)
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
9
+
10
+ RSpec.configure do |config|
11
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.run_all_when_everything_filtered = true
13
+ config.filter_run :focus
14
+ config.mock_with :rspec
15
+ end
metadata CHANGED
@@ -1,41 +1,50 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cheers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 0.0.3
6
5
  platform: ruby
7
6
  authors:
8
7
  - Mārtiņš Spilners
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-05-24 00:00:00.000000000 Z
11
+ date: 2019-11-28 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- name: rmagick
16
- requirement: &70319637709080 !ruby/object:Gem::Requirement
17
- none: false
14
+ name: mini_magick
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
- version_requirements: *70319637709080
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
25
27
  description: Cheers randomly generates user avatars from a set of colors and image
26
28
  components.
27
29
  email:
28
30
  - martins@eet.nu
29
- executables: []
31
+ executables:
32
+ - cheers
30
33
  extensions: []
31
34
  extra_rdoc_files: []
32
35
  files:
33
- - .gitignore
36
+ - ".gitignore"
37
+ - ".rspec"
38
+ - ".ruby-version"
39
+ - ".rvmrc"
34
40
  - Gemfile
41
+ - Guardfile
35
42
  - LICENSE
36
43
  - README.md
37
44
  - Rakefile
45
+ - bin/cheers
38
46
  - cheers.gemspec
47
+ - components/blank.png
39
48
  - components/decorations/1.png
40
49
  - components/decorations/2.png
41
50
  - components/eyes/1.png
@@ -75,30 +84,43 @@ files:
75
84
  - doc/example_9.png
76
85
  - lib/cheers.rb
77
86
  - lib/cheers/avatar.rb
87
+ - lib/cheers/background.rb
78
88
  - lib/cheers/color.rb
89
+ - lib/cheers/component.rb
90
+ - lib/cheers/contrasting_color_picker.rb
91
+ - lib/cheers/decoration.rb
92
+ - lib/cheers/eyes.rb
93
+ - lib/cheers/face.rb
94
+ - lib/cheers/image_component.rb
95
+ - lib/cheers/lower_glow.rb
96
+ - lib/cheers/mouth.rb
97
+ - lib/cheers/texture.rb
98
+ - lib/cheers/upper_glow.rb
79
99
  - lib/cheers/version.rb
100
+ - spec/cheers/color_spec.rb
101
+ - spec/spec_helper.rb
80
102
  homepage: http://github.com/eet-nu/cheers
81
103
  licenses: []
104
+ metadata: {}
82
105
  post_install_message:
83
106
  rdoc_options: []
84
107
  require_paths:
85
108
  - lib
86
109
  required_ruby_version: !ruby/object:Gem::Requirement
87
- none: false
88
110
  requirements:
89
- - - ! '>='
111
+ - - ">="
90
112
  - !ruby/object:Gem::Version
91
113
  version: '0'
92
114
  required_rubygems_version: !ruby/object:Gem::Requirement
93
- none: false
94
115
  requirements:
95
- - - ! '>='
116
+ - - ">="
96
117
  - !ruby/object:Gem::Version
97
118
  version: '0'
98
119
  requirements: []
99
- rubyforge_project:
100
- rubygems_version: 1.8.17
120
+ rubygems_version: 3.0.6
101
121
  signing_key:
102
- specification_version: 3
122
+ specification_version: 4
103
123
  summary: Generate random user avatars.
104
- test_files: []
124
+ test_files:
125
+ - spec/cheers/color_spec.rb
126
+ - spec/spec_helper.rb