cheers 0.0.1 → 0.0.3

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