letter_avatar_simple 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +11 -0
- data/README.md +327 -0
- data/Roboto-Medium +0 -0
- data/lib/letter_avatar_simple.rb +90 -0
- data/lib/letter_avatar_simple/configuration.rb +36 -0
- data/lib/letter_avatar_simple/identity.rb +17 -0
- data/lib/letter_avatar_simple/palette.rb +15 -0
- data/lib/letter_avatar_simple/palettes/google.rb +41 -0
- data/lib/letter_avatar_simple/palettes/i_want_hue.rb +235 -0
- data/lib/letter_avatar_simple/version.rb +4 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eac1036d24e2ef091716b9c981800abf0e3e1175dd2ef724b49946f2f182e730
|
4
|
+
data.tar.gz: e24eb2f56ab42e46cce77a076555248bc6bbfae55f8ec9b853473bcdc9b8fa21
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 98f2beed0d5932e6b6fef70b9c4b6aa01d211655a9550942a28c15020c08a5a11e954dc66b8411b1903c87cbd815c33a736a683c316e2834525a1e4b5fd9a341
|
7
|
+
data.tar.gz: 31fc21b791a0ef895dca8236af35176b3b9062ce21e5dd58c8a12fb80be7167dc3ea34d6e1c125c3bcb9118132f079aac142de3021192c8d1c6948c01d14e000
|
data/CHANGELOG.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,327 @@
|
|
1
|
+
# LetterAvatarSimple
|
2
|
+
|
3
|
+
Generate letter image avatars based on user initials.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
LetterAvatarSimple.generate("foobar")
|
9
|
+
# => #<StringIO:0x000055b3804948a8>
|
10
|
+
```
|
11
|
+
|
12
|
+
<img src="./examples/readme/F.png" alt='Image of letter "F"' width="64" height="64" />
|
13
|
+
|
14
|
+
------------
|
15
|
+
|
16
|
+
We can do multiple letters:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
LetterAvatarSimple.generate("Dallas Smith")
|
20
|
+
# => #<StringIO:0x000055b380e6a058>
|
21
|
+
```
|
22
|
+
|
23
|
+
<img src="./examples/readme/DS.png" alt='Image of letters "DS"' width="64" height="64" />
|
24
|
+
|
25
|
+
------------
|
26
|
+
|
27
|
+
We can save to a file:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
LetterAvatarSimple.generate_file("Dallas Smith")
|
31
|
+
# => #<File:/tmp/x20190527-19344-79m629.png>
|
32
|
+
|
33
|
+
LetterAvatarSimple.generate_file("Dallas Smith", filename: "/tmp/dallas.png")
|
34
|
+
# => #<File:/tmp/dallas.png>
|
35
|
+
```
|
36
|
+
|
37
|
+
------------
|
38
|
+
|
39
|
+
We can specify the initials using `LetterAvatarSimple::Identity`:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
i = LetterAvatarSimple::Identity.new("ZZ", "Dallas Smith")
|
43
|
+
LetterAvatarSimple.generate(i)
|
44
|
+
```
|
45
|
+
|
46
|
+
<img src="./examples/readme/ZZ-1.png" alt='Image of letters "ZZ" in green' width="64" height="64" />
|
47
|
+
|
48
|
+
------------
|
49
|
+
|
50
|
+
Image color is chosen from a palette based on username, so the same initials
|
51
|
+
will (most likely) not share the same color:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
i = LetterAvatarSimple::Identity.new("ZZ", "foobar")
|
55
|
+
LetterAvatarSimple.generate(i)
|
56
|
+
```
|
57
|
+
|
58
|
+
<img src="./examples/readme/ZZ-2.png" alt='Image of letters "ZZ" in pink' width="64" height="64" />
|
59
|
+
|
60
|
+
------------
|
61
|
+
|
62
|
+
The default palette is based on Google Inbox. You can change palettes:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
LetterAvatarSimple.generate("foobar", palette: :i_want_hue)
|
66
|
+
```
|
67
|
+
|
68
|
+
<img src="./examples/readme/F-i_want_hue.png" alt='Image of letter "F"' width="64" height="64" />
|
69
|
+
|
70
|
+
------------
|
71
|
+
|
72
|
+
Or skip the palette feature and provide the desired color directly, in RGB tuple format:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
LetterAvatarSimple.generate("foobar", color: [255,0,0])
|
76
|
+
```
|
77
|
+
|
78
|
+
<img src="./examples/readme/F-red.png" alt='Image of letter "F"' width="64" height="64" />
|
79
|
+
|
80
|
+
------------
|
81
|
+
|
82
|
+
Other options that can be provided to customize image generation:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
LetterAvatarSimple.generate(
|
86
|
+
"foobar",
|
87
|
+
size: 256, # => default 1024
|
88
|
+
palette: :i_want_hue, # => default :google
|
89
|
+
# warning: this bypasses the palette's color selection
|
90
|
+
color: [255, 0, 0] # => default nil
|
91
|
+
pointsize: 150, # => default 600
|
92
|
+
font: "/tmp/path/to/font/file", # => default is path to included Roboto font
|
93
|
+
weight: 500, # => default 300
|
94
|
+
fill_color: "rgba(255, 255, 255, 1)", # => default "rgba(255, 255, 255, 0.65)"
|
95
|
+
annotate_position: "-0+10", # => default "-0+5"
|
96
|
+
filename: "/tmp/foo.png", # => default is randomly generated tempfile path
|
97
|
+
)
|
98
|
+
```
|
99
|
+
|
100
|
+
## About
|
101
|
+
|
102
|
+
Forked from [letter_avatar][], which was in turn extracted from [Discourse][].
|
103
|
+
|
104
|
+
Compared to [letter_avatar][], this gem:
|
105
|
+
* Outputs `StringIO` binary data by default (but can write to files too!)
|
106
|
+
instead of always writing files to the `public` directory. This way you can
|
107
|
+
use image upload gems like [shrine][] much easier
|
108
|
+
* Supports keyword arguments for generating each image (don't need to edit
|
109
|
+
global config or constants)
|
110
|
+
* Simplifies custom palette loading and supports multiple custom palettes
|
111
|
+
* Uses [minimagick][] instead of homegrown ImageMagick shell execution
|
112
|
+
* Does **not** come with model, view, or controller helpers (you should
|
113
|
+
be using [shrine][])
|
114
|
+
* Does **not** do caching (you should be using [shrine][])
|
115
|
+
|
116
|
+
## Installation
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
gem "letter_avatar_simple"
|
120
|
+
```
|
121
|
+
|
122
|
+
## System requirements
|
123
|
+
|
124
|
+
ImageMagick or GraphicsMagick - see
|
125
|
+
[MiniMagick requirements](https://github.com/minimagick/minimagick#requirements)
|
126
|
+
|
127
|
+
## Color palettes
|
128
|
+
|
129
|
+
Two color palettes are provided by default: `:google` and `:i_want_hue`
|
130
|
+
|
131
|
+
Both palettes use an MD5 digest of the username to select the color, so it's
|
132
|
+
likely that two different usernames that share the same initial(s) will render
|
133
|
+
with different colors.
|
134
|
+
|
135
|
+
If you need the same initials to always render with the same color, simply
|
136
|
+
provide a custom palette using a customized `letter_color` method. See below
|
137
|
+
for an example.
|
138
|
+
|
139
|
+
### `:google` - Google Inbox palette
|
140
|
+
|
141
|
+
<!--
|
142
|
+
alphabet = ("A".."Z").cycle
|
143
|
+
|
144
|
+
pairs = LetterAvatarSimple::Palettes::Google::PALETTE.zip(alphabet)
|
145
|
+
|
146
|
+
pairs.each do |color,letter|
|
147
|
+
filename = "./examples/readme/google-palette/#{letter}.png"
|
148
|
+
LetterAvatarSimple.generate_file(
|
149
|
+
letter,
|
150
|
+
color: color,
|
151
|
+
filename: filename,
|
152
|
+
size: 64,
|
153
|
+
pointsize: 37.5,
|
154
|
+
annotate_position: "-0+0"
|
155
|
+
)
|
156
|
+
end
|
157
|
+
-->
|
158
|
+
|
159
|
+
<div>
|
160
|
+
<img src="./examples/readme/google-palette/A.png" alt='Image of letter "A"' width="64" height="64" />
|
161
|
+
<img src="./examples/readme/google-palette/B.png" alt='Image of letter "B"' width="64" height="64" />
|
162
|
+
<img src="./examples/readme/google-palette/C.png" alt='Image of letter "C"' width="64" height="64" />
|
163
|
+
<img src="./examples/readme/google-palette/D.png" alt='Image of letter "D"' width="64" height="64" />
|
164
|
+
<img src="./examples/readme/google-palette/E.png" alt='Image of letter "E"' width="64" height="64" />
|
165
|
+
<img src="./examples/readme/google-palette/F.png" alt='Image of letter "F"' width="64" height="64" />
|
166
|
+
<img src="./examples/readme/google-palette/G.png" alt='Image of letter "G"' width="64" height="64" />
|
167
|
+
<img src="./examples/readme/google-palette/H.png" alt='Image of letter "H"' width="64" height="64" />
|
168
|
+
<img src="./examples/readme/google-palette/I.png" alt='Image of letter "I"' width="64" height="64" />
|
169
|
+
<img src="./examples/readme/google-palette/J.png" alt='Image of letter "J"' width="64" height="64" />
|
170
|
+
<img src="./examples/readme/google-palette/K.png" alt='Image of letter "K"' width="64" height="64" />
|
171
|
+
<img src="./examples/readme/google-palette/L.png" alt='Image of letter "L"' width="64" height="64" />
|
172
|
+
<img src="./examples/readme/google-palette/M.png" alt='Image of letter "M"' width="64" height="64" />
|
173
|
+
<img src="./examples/readme/google-palette/N.png" alt='Image of letter "N"' width="64" height="64" />
|
174
|
+
<img src="./examples/readme/google-palette/O.png" alt='Image of letter "O"' width="64" height="64" />
|
175
|
+
<img src="./examples/readme/google-palette/P.png" alt='Image of letter "P"' width="64" height="64" />
|
176
|
+
<img src="./examples/readme/google-palette/Q.png" alt='Image of letter "Q"' width="64" height="64" />
|
177
|
+
<img src="./examples/readme/google-palette/R.png" alt='Image of letter "R"' width="64" height="64" />
|
178
|
+
<img src="./examples/readme/google-palette/S.png" alt='Image of letter "S"' width="64" height="64" />
|
179
|
+
<img src="./examples/readme/google-palette/T.png" alt='Image of letter "T"' width="64" height="64" />
|
180
|
+
<img src="./examples/readme/google-palette/U.png" alt='Image of letter "U"' width="64" height="64" />
|
181
|
+
<img src="./examples/readme/google-palette/V.png" alt='Image of letter "V"' width="64" height="64" />
|
182
|
+
<img src="./examples/readme/google-palette/W.png" alt='Image of letter "W"' width="64" height="64" />
|
183
|
+
<img src="./examples/readme/google-palette/X.png" alt='Image of letter "X"' width="64" height="64" />
|
184
|
+
<img src="./examples/readme/google-palette/Y.png" alt='Image of letter "Y"' width="64" height="64" />
|
185
|
+
<img src="./examples/readme/google-palette/Z.png" alt='Image of letter "Z"' width="64" height="64" />
|
186
|
+
</div>
|
187
|
+
|
188
|
+
### `:i_want_hue` - [iWantHue][] palette
|
189
|
+
|
190
|
+
<!--
|
191
|
+
alphabet = ("A".."Z").cycle
|
192
|
+
|
193
|
+
pairs = LetterAvatarSimple::Palettes::IWantHue::PALETTE.zip(alphabet)
|
194
|
+
|
195
|
+
f = File.open("/tmp/i_want_hue.txt", "w")
|
196
|
+
pairs.each_with_index do |(color,letter),i|
|
197
|
+
filename = "./examples/readme/i_want_hue-palette/#{i}-#{letter}.png"
|
198
|
+
LetterAvatarSimple.generate_file(
|
199
|
+
letter,
|
200
|
+
color: color,
|
201
|
+
filename: filename,
|
202
|
+
size: 64,
|
203
|
+
pointsize: 37.5,
|
204
|
+
annotate_position: "-0+0"
|
205
|
+
)
|
206
|
+
f.puts <<~HTML
|
207
|
+
<img src="#{filename}" alt='Image of letter "#{letter}"' width="64" height="64" />
|
208
|
+
HTML
|
209
|
+
end
|
210
|
+
f.close
|
211
|
+
-->
|
212
|
+
|
213
|
+
<div>
|
214
|
+
<img src="./examples/readme/i_want_hue-palette/0-A.png" alt='Image of letter "A"' width="64" height="64" />
|
215
|
+
<img src="./examples/readme/i_want_hue-palette/1-B.png" alt='Image of letter "B"' width="64" height="64" />
|
216
|
+
<img src="./examples/readme/i_want_hue-palette/2-C.png" alt='Image of letter "C"' width="64" height="64" />
|
217
|
+
<img src="./examples/readme/i_want_hue-palette/3-D.png" alt='Image of letter "D"' width="64" height="64" />
|
218
|
+
<img src="./examples/readme/i_want_hue-palette/4-E.png" alt='Image of letter "E"' width="64" height="64" />
|
219
|
+
<img src="./examples/readme/i_want_hue-palette/5-F.png" alt='Image of letter "F"' width="64" height="64" />
|
220
|
+
<img src="./examples/readme/i_want_hue-palette/6-G.png" alt='Image of letter "G"' width="64" height="64" />
|
221
|
+
<img src="./examples/readme/i_want_hue-palette/7-H.png" alt='Image of letter "H"' width="64" height="64" />
|
222
|
+
<img src="./examples/readme/i_want_hue-palette/8-I.png" alt='Image of letter "I"' width="64" height="64" />
|
223
|
+
<img src="./examples/readme/i_want_hue-palette/9-J.png" alt='Image of letter "J"' width="64" height="64" />
|
224
|
+
<img src="./examples/readme/i_want_hue-palette/10-K.png" alt='Image of letter "K"' width="64" height="64" />
|
225
|
+
<img src="./examples/readme/i_want_hue-palette/11-L.png" alt='Image of letter "L"' width="64" height="64" />
|
226
|
+
<img src="./examples/readme/i_want_hue-palette/12-M.png" alt='Image of letter "M"' width="64" height="64" />
|
227
|
+
<img src="./examples/readme/i_want_hue-palette/13-N.png" alt='Image of letter "N"' width="64" height="64" />
|
228
|
+
<img src="./examples/readme/i_want_hue-palette/14-O.png" alt='Image of letter "O"' width="64" height="64" />
|
229
|
+
<img src="./examples/readme/i_want_hue-palette/15-P.png" alt='Image of letter "P"' width="64" height="64" />
|
230
|
+
<img src="./examples/readme/i_want_hue-palette/16-Q.png" alt='Image of letter "Q"' width="64" height="64" />
|
231
|
+
<img src="./examples/readme/i_want_hue-palette/17-R.png" alt='Image of letter "R"' width="64" height="64" />
|
232
|
+
<img src="./examples/readme/i_want_hue-palette/18-S.png" alt='Image of letter "S"' width="64" height="64" />
|
233
|
+
<img src="./examples/readme/i_want_hue-palette/19-T.png" alt='Image of letter "T"' width="64" height="64" />
|
234
|
+
<img src="./examples/readme/i_want_hue-palette/20-U.png" alt='Image of letter "U"' width="64" height="64" />
|
235
|
+
<img src="./examples/readme/i_want_hue-palette/21-V.png" alt='Image of letter "V"' width="64" height="64" />
|
236
|
+
<img src="./examples/readme/i_want_hue-palette/22-W.png" alt='Image of letter "W"' width="64" height="64" />
|
237
|
+
<img src="./examples/readme/i_want_hue-palette/23-X.png" alt='Image of letter "X"' width="64" height="64" />
|
238
|
+
<img src="./examples/readme/i_want_hue-palette/24-Y.png" alt='Image of letter "Y"' width="64" height="64" />
|
239
|
+
<img src="./examples/readme/i_want_hue-palette/25-Z.png" alt='Image of letter "Z"' width="64" height="64" />
|
240
|
+
<img src="./examples/readme/i_want_hue-palette/26-A.png" alt='Image of letter "A"' width="64" height="64" />
|
241
|
+
<img src="./examples/readme/i_want_hue-palette/27-B.png" alt='Image of letter "B"' width="64" height="64" />
|
242
|
+
<img src="./examples/readme/i_want_hue-palette/28-C.png" alt='Image of letter "C"' width="64" height="64" />
|
243
|
+
<img src="./examples/readme/i_want_hue-palette/29-D.png" alt='Image of letter "D"' width="64" height="64" />
|
244
|
+
<img src="./examples/readme/i_want_hue-palette/30-E.png" alt='Image of letter "E"' width="64" height="64" />
|
245
|
+
<img src="./examples/readme/i_want_hue-palette/31-F.png" alt='Image of letter "F"' width="64" height="64" />
|
246
|
+
<img src="./examples/readme/i_want_hue-palette/32-G.png" alt='Image of letter "G"' width="64" height="64" />
|
247
|
+
<img src="./examples/readme/i_want_hue-palette/33-H.png" alt='Image of letter "H"' width="64" height="64" />
|
248
|
+
<img src="./examples/readme/i_want_hue-palette/34-I.png" alt='Image of letter "I"' width="64" height="64" />
|
249
|
+
<img src="./examples/readme/i_want_hue-palette/35-J.png" alt='Image of letter "J"' width="64" height="64" />
|
250
|
+
<img src="./examples/readme/i_want_hue-palette/36-K.png" alt='Image of letter "K"' width="64" height="64" />
|
251
|
+
<img src="./examples/readme/i_want_hue-palette/37-L.png" alt='Image of letter "L"' width="64" height="64" />
|
252
|
+
<img src="./examples/readme/i_want_hue-palette/38-M.png" alt='Image of letter "M"' width="64" height="64" />
|
253
|
+
<img src="./examples/readme/i_want_hue-palette/39-N.png" alt='Image of letter "N"' width="64" height="64" />
|
254
|
+
<img src="./examples/readme/i_want_hue-palette/40-O.png" alt='Image of letter "O"' width="64" height="64" />
|
255
|
+
<img src="./examples/readme/i_want_hue-palette/41-P.png" alt='Image of letter "P"' width="64" height="64" />
|
256
|
+
<img src="./examples/readme/i_want_hue-palette/42-Q.png" alt='Image of letter "Q"' width="64" height="64" />
|
257
|
+
<img src="./examples/readme/i_want_hue-palette/43-R.png" alt='Image of letter "R"' width="64" height="64" />
|
258
|
+
<img src="./examples/readme/i_want_hue-palette/44-S.png" alt='Image of letter "S"' width="64" height="64" />
|
259
|
+
<img src="./examples/readme/i_want_hue-palette/45-T.png" alt='Image of letter "T"' width="64" height="64" />
|
260
|
+
<img src="./examples/readme/i_want_hue-palette/46-U.png" alt='Image of letter "U"' width="64" height="64" />
|
261
|
+
<img src="./examples/readme/i_want_hue-palette/47-V.png" alt='Image of letter "V"' width="64" height="64" />
|
262
|
+
<img src="./examples/readme/i_want_hue-palette/48-W.png" alt='Image of letter "W"' width="64" height="64" />
|
263
|
+
<img src="./examples/readme/i_want_hue-palette/49-X.png" alt='Image of letter "X"' width="64" height="64" />
|
264
|
+
<img src="./examples/readme/i_want_hue-palette/50-Y.png" alt='Image of letter "Y"' width="64" height="64" />
|
265
|
+
<img src="./examples/readme/i_want_hue-palette/51-Z.png" alt='Image of letter "Z"' width="64" height="64" />
|
266
|
+
<img src="./examples/readme/i_want_hue-palette/52-A.png" alt='Image of letter "A"' width="64" height="64" />
|
267
|
+
<img src="./examples/readme/i_want_hue-palette/53-B.png" alt='Image of letter "B"' width="64" height="64" />
|
268
|
+
<img src="./examples/readme/i_want_hue-palette/54-C.png" alt='Image of letter "C"' width="64" height="64" />
|
269
|
+
<img src="./examples/readme/i_want_hue-palette/55-D.png" alt='Image of letter "D"' width="64" height="64" />
|
270
|
+
<img src="./examples/readme/i_want_hue-palette/56-E.png" alt='Image of letter "E"' width="64" height="64" />
|
271
|
+
<img src="./examples/readme/i_want_hue-palette/57-F.png" alt='Image of letter "F"' width="64" height="64" />
|
272
|
+
<img src="./examples/readme/i_want_hue-palette/58-G.png" alt='Image of letter "G"' width="64" height="64" />
|
273
|
+
... <a href="./examples/readme/i_want_hue-palette">and 157 more!</a>
|
274
|
+
</div>
|
275
|
+
|
276
|
+
### Custom palettes
|
277
|
+
|
278
|
+
You can add your own custom palette:
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
LetterAvatarSimple.palettes[:my_palette] = LetterAvatarSimple::Palette.new([
|
282
|
+
[120, 132, 205],
|
283
|
+
[91, 149, 249],
|
284
|
+
[72, 194, 249],
|
285
|
+
[69, 208, 226],
|
286
|
+
])
|
287
|
+
# The default method of selecting the color is by MD5 digest of the username. You
|
288
|
+
# can change this behavior by providing a letter_color method.
|
289
|
+
LetterAvatarSimple.palettes[:my_palette].tap do |p|
|
290
|
+
def p.letter_color(identity)
|
291
|
+
if identity.id == "admin"
|
292
|
+
[255, 0, 0] # red
|
293
|
+
elsif identity.id == "bozo"
|
294
|
+
@palette.sample # random
|
295
|
+
else
|
296
|
+
# same initials = same color
|
297
|
+
digest = Digest::MD5.hexdigest(identity.letters.to_s)
|
298
|
+
@palette[digest[0...15].to_i(16) % @palette.length]
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
LetterAvatarSimple.generate_file("foobar", palette: :my_palette)
|
304
|
+
```
|
305
|
+
|
306
|
+
## Configuration
|
307
|
+
|
308
|
+
The same options that can be passed to `generate` can be set as global defaults:
|
309
|
+
|
310
|
+
```ruby
|
311
|
+
LetterAvatarSimple.config do |config|
|
312
|
+
config.size = 256
|
313
|
+
config.palette = :i_want_hue
|
314
|
+
config.color = [255, 0, 0]
|
315
|
+
config.pointsize = 150
|
316
|
+
config.font = "/tmp/path/to/font/file"
|
317
|
+
config.weight = 500
|
318
|
+
config.fill_color = "rgba(255, 255, 255, 1)"
|
319
|
+
config.annotate_position = "-0+10"
|
320
|
+
end
|
321
|
+
```
|
322
|
+
|
323
|
+
[letter_avatar]: https://github.com/ksz2k/letter_avatar
|
324
|
+
[minimagick]: https://github.com/minimagick/minimagick
|
325
|
+
[shrine]: https://github.com/shrinerb/shrine
|
326
|
+
[Discourse]: https://www.discourse.org/
|
327
|
+
[iWantHue]: http://tools.medialab.sciences-po.fr/iwanthue/index.php
|
data/Roboto-Medium
ADDED
Binary file
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "letter_avatar_simple/configuration"
|
3
|
+
require "letter_avatar_simple/identity"
|
4
|
+
require "letter_avatar_simple/palette"
|
5
|
+
require "letter_avatar_simple/version"
|
6
|
+
require "fileutils"
|
7
|
+
require "mini_magick"
|
8
|
+
require "tmpdir"
|
9
|
+
|
10
|
+
class LetterAvatarSimple
|
11
|
+
extend Configuration
|
12
|
+
|
13
|
+
def self.config(&blk)
|
14
|
+
yield(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.palettes
|
18
|
+
@palettes
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.palettes=(h)
|
22
|
+
@palettes = h
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.generate(identity, output: :string, **kwargs)
|
26
|
+
if identity.is_a?(String)
|
27
|
+
identity = Identity.from_username(identity)
|
28
|
+
end
|
29
|
+
|
30
|
+
opts = {
|
31
|
+
palette: kwargs[:palette] || LetterAvatarSimple.palette,
|
32
|
+
color: kwargs[:color] || LetterAvatarSimple.color,
|
33
|
+
size: kwargs[:size] || LetterAvatarSimple.size,
|
34
|
+
pointsize: kwargs[:pointsize] || LetterAvatarSimple.pointsize,
|
35
|
+
font: kwargs[:font] || LetterAvatarSimple.font,
|
36
|
+
weight: kwargs[:weight] || LetterAvatarSimple.weight,
|
37
|
+
fill_color: kwargs[:fill_color] || LetterAvatarSimple.fill_color,
|
38
|
+
annotate_position: kwargs[:annotate_position] || LetterAvatarSimple.annotate_position,
|
39
|
+
}
|
40
|
+
|
41
|
+
filename = kwargs[:filename] || generate_temp_filename
|
42
|
+
color = opts[:color] || LetterAvatarSimple.palettes.fetch(opts.fetch(:palette)).letter_color(identity)
|
43
|
+
MiniMagick::Tool::Convert.new do |x|
|
44
|
+
x.size "#{opts.fetch(:size)}x#{opts.fetch(:size)}"
|
45
|
+
x << "xc:#{to_rgb(color)}"
|
46
|
+
x.pointsize opts.fetch(:pointsize)
|
47
|
+
x.font opts.fetch(:font)
|
48
|
+
x.weight opts.fetch(:weight)
|
49
|
+
x.fill opts.fetch(:fill_color)
|
50
|
+
x.gravity "Center"
|
51
|
+
x.annotate(opts.fetch(:annotate_position), identity.letters)
|
52
|
+
x << filename
|
53
|
+
end
|
54
|
+
|
55
|
+
if output == :file
|
56
|
+
File.open(filename, "rb")
|
57
|
+
else
|
58
|
+
StringIO.new(File.binread(filename), "rb").tap do
|
59
|
+
FileUtils.rm_f(filename)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.generate_file(*args, **kwargs)
|
65
|
+
kwargs[:output] = :file
|
66
|
+
self.generate(*args, **kwargs)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.to_rgb(color)
|
70
|
+
r, g, b = color
|
71
|
+
"rgb(#{r},#{g},#{b})"
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.generate_temp_filename(ext=".png")
|
75
|
+
filename = begin
|
76
|
+
Dir::Tmpname.make_tmpname(["x", ext], nil)
|
77
|
+
rescue NoMethodError
|
78
|
+
require "securerandom"
|
79
|
+
"#{SecureRandom.urlsafe_base64}#{ext}"
|
80
|
+
end
|
81
|
+
File.join(Dir.tmpdir, filename)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
require "letter_avatar_simple/palettes/google"
|
86
|
+
require "letter_avatar_simple/palettes/i_want_hue"
|
87
|
+
LetterAvatarSimple.palettes = {
|
88
|
+
google: LetterAvatarSimple::Palettes::Google.new,
|
89
|
+
i_want_hue: LetterAvatarSimple::Palettes::IWantHue.new,
|
90
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class LetterAvatarSimple
|
3
|
+
module Configuration
|
4
|
+
attr_accessor :color
|
5
|
+
attr_writer :size, :fill_color, :font, :palette, :weight,
|
6
|
+
:annotate_position, :pointsize
|
7
|
+
|
8
|
+
def size
|
9
|
+
@size || 1024
|
10
|
+
end
|
11
|
+
|
12
|
+
def fill_color
|
13
|
+
@fill_color || "rgba(255, 255, 255, 0.65)"
|
14
|
+
end
|
15
|
+
|
16
|
+
def font
|
17
|
+
@font || File.join(File.expand_path("../../", File.dirname(__FILE__)), "Roboto-Medium")
|
18
|
+
end
|
19
|
+
|
20
|
+
def palette
|
21
|
+
@palette || :google
|
22
|
+
end
|
23
|
+
|
24
|
+
def weight
|
25
|
+
@weight ||= 300
|
26
|
+
end
|
27
|
+
|
28
|
+
def annotate_position
|
29
|
+
@annotate_position ||= "-0+5"
|
30
|
+
end
|
31
|
+
|
32
|
+
def pointsize
|
33
|
+
@pointsize ||= 600
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class LetterAvatarSimple
|
3
|
+
class Identity
|
4
|
+
attr_accessor :letters, :id
|
5
|
+
|
6
|
+
def initialize(letters, id)
|
7
|
+
@letters = letters
|
8
|
+
@id = id
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.from_username(username)
|
12
|
+
# "john smith" => "JS"
|
13
|
+
letters = username.split(/\s+/).map{|word| word[0].upcase}.join('')
|
14
|
+
new(letters, username)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "digest"
|
3
|
+
|
4
|
+
class LetterAvatarSimple
|
5
|
+
class Palette
|
6
|
+
def initialize(palette)
|
7
|
+
@palette = palette
|
8
|
+
end
|
9
|
+
|
10
|
+
def letter_color(identity)
|
11
|
+
digest = Digest::MD5.hexdigest(identity.id.to_s)
|
12
|
+
@palette[digest[0...15].to_i(16) % @palette.length]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class LetterAvatarSimple
|
3
|
+
class Palettes
|
4
|
+
class Google < LetterAvatarSimple::Palette
|
5
|
+
# Colors from Google Inbox
|
6
|
+
# https://inbox.google.com
|
7
|
+
PALETTE = [
|
8
|
+
[226, 95, 81], # A
|
9
|
+
[242, 96, 145], # B
|
10
|
+
[187, 101, 202], # C
|
11
|
+
[149, 114, 207], # D
|
12
|
+
[120, 132, 205], # E
|
13
|
+
[91, 149, 249], # F
|
14
|
+
[72, 194, 249], # G
|
15
|
+
[69, 208, 226], # H
|
16
|
+
[72, 182, 172], # I
|
17
|
+
[82, 188, 137], # J
|
18
|
+
[155, 206, 95], # K
|
19
|
+
[212, 227, 74], # L
|
20
|
+
[254, 218, 16], # M
|
21
|
+
[247, 192, 0], # N
|
22
|
+
[255, 168, 0], # O
|
23
|
+
[255, 138, 96], # P
|
24
|
+
[194, 194, 194], # Q
|
25
|
+
[143, 164, 175], # R
|
26
|
+
[162, 136, 126], # S
|
27
|
+
[163, 163, 163], # T
|
28
|
+
[175, 181, 226], # U
|
29
|
+
[179, 155, 221], # V
|
30
|
+
[194, 194, 194], # W
|
31
|
+
[124, 222, 235], # X
|
32
|
+
[188, 170, 164], # Y
|
33
|
+
[173, 214, 125] # Z
|
34
|
+
].freeze
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@palette = PALETTE
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class LetterAvatarSimple
|
3
|
+
class Palettes
|
4
|
+
class IWantHue < LetterAvatarSimple::Palette
|
5
|
+
# palette of optimally disctinct colors
|
6
|
+
# cf. http://tools.medialab.sciences-po.fr/iwanthue/index.php
|
7
|
+
# parameters used:
|
8
|
+
# - H: 0 - 360
|
9
|
+
# - C: 0 - 2
|
10
|
+
# - L: 0.75 - 1.5
|
11
|
+
PALETTE = [
|
12
|
+
[198, 125, 40],
|
13
|
+
[61, 155, 243],
|
14
|
+
[74, 243, 75],
|
15
|
+
[238, 89, 166],
|
16
|
+
[52, 240, 224],
|
17
|
+
[177, 156, 155],
|
18
|
+
[240, 120, 145],
|
19
|
+
[111, 154, 78],
|
20
|
+
[237, 179, 245],
|
21
|
+
[237, 101, 95],
|
22
|
+
[89, 239, 155],
|
23
|
+
[43, 254, 70],
|
24
|
+
[163, 212, 245],
|
25
|
+
[65, 152, 142],
|
26
|
+
[165, 135, 246],
|
27
|
+
[181, 166, 38],
|
28
|
+
[187, 229, 206],
|
29
|
+
[77, 164, 25],
|
30
|
+
[179, 246, 101],
|
31
|
+
[234, 93, 37],
|
32
|
+
[225, 155, 115],
|
33
|
+
[142, 140, 188],
|
34
|
+
[223, 120, 140],
|
35
|
+
[249, 174, 27],
|
36
|
+
[244, 117, 225],
|
37
|
+
[137, 141, 102],
|
38
|
+
[75, 191, 146],
|
39
|
+
[188, 239, 142],
|
40
|
+
[164, 199, 145],
|
41
|
+
[173, 120, 149],
|
42
|
+
[59, 195, 89],
|
43
|
+
[222, 198, 220],
|
44
|
+
[68, 145, 187],
|
45
|
+
[236, 204, 179],
|
46
|
+
[159, 195, 72],
|
47
|
+
[188, 121, 189],
|
48
|
+
[166, 160, 85],
|
49
|
+
[181, 233, 37],
|
50
|
+
[236, 177, 85],
|
51
|
+
[121, 147, 160],
|
52
|
+
[234, 218, 110],
|
53
|
+
[241, 157, 191],
|
54
|
+
[62, 200, 234],
|
55
|
+
[133, 243, 34],
|
56
|
+
[88, 149, 110],
|
57
|
+
[59, 228, 248],
|
58
|
+
[183, 119, 118],
|
59
|
+
[251, 195, 45],
|
60
|
+
[113, 196, 122],
|
61
|
+
[197, 115, 70],
|
62
|
+
[80, 175, 187],
|
63
|
+
[103, 231, 238],
|
64
|
+
[240, 72, 133],
|
65
|
+
[228, 149, 241],
|
66
|
+
[180, 188, 159],
|
67
|
+
[172, 132, 85],
|
68
|
+
[180, 135, 251],
|
69
|
+
[236, 194, 58],
|
70
|
+
[217, 176, 109],
|
71
|
+
[88, 244, 199],
|
72
|
+
[186, 157, 239],
|
73
|
+
[113, 230, 96],
|
74
|
+
[206, 115, 165],
|
75
|
+
[244, 178, 163],
|
76
|
+
[230, 139, 26],
|
77
|
+
[241, 125, 89],
|
78
|
+
[83, 160, 66],
|
79
|
+
[107, 190, 166],
|
80
|
+
[197, 161, 210],
|
81
|
+
[198, 203, 245],
|
82
|
+
[238, 117, 19],
|
83
|
+
[228, 119, 116],
|
84
|
+
[131, 156, 41],
|
85
|
+
[145, 178, 168],
|
86
|
+
[139, 170, 220],
|
87
|
+
[233, 95, 125],
|
88
|
+
[87, 178, 230],
|
89
|
+
[157, 200, 119],
|
90
|
+
[237, 140, 76],
|
91
|
+
[229, 185, 186],
|
92
|
+
[144, 206, 212],
|
93
|
+
[236, 209, 158],
|
94
|
+
[185, 189, 79],
|
95
|
+
[34, 208, 66],
|
96
|
+
[84, 238, 129],
|
97
|
+
[133, 140, 134],
|
98
|
+
[67, 157, 94],
|
99
|
+
[168, 179, 25],
|
100
|
+
[140, 145, 240],
|
101
|
+
[151, 241, 125],
|
102
|
+
[67, 162, 107],
|
103
|
+
[200, 156, 21],
|
104
|
+
[169, 173, 189],
|
105
|
+
[226, 116, 189],
|
106
|
+
[133, 231, 191],
|
107
|
+
[194, 161, 63],
|
108
|
+
[241, 77, 99],
|
109
|
+
[241, 217, 53],
|
110
|
+
[123, 204, 105],
|
111
|
+
[210, 201, 119],
|
112
|
+
[229, 108, 155],
|
113
|
+
[240, 91, 72],
|
114
|
+
[187, 115, 210],
|
115
|
+
[240, 163, 100],
|
116
|
+
[178, 217, 57],
|
117
|
+
[179, 135, 116],
|
118
|
+
[204, 211, 24],
|
119
|
+
[186, 135, 57],
|
120
|
+
[223, 176, 135],
|
121
|
+
[204, 148, 151],
|
122
|
+
[116, 223, 50],
|
123
|
+
[95, 195, 46],
|
124
|
+
[123, 160, 236],
|
125
|
+
[181, 172, 131],
|
126
|
+
[142, 220, 202],
|
127
|
+
[240, 140, 112],
|
128
|
+
[172, 145, 164],
|
129
|
+
[228, 124, 45],
|
130
|
+
[135, 151, 243],
|
131
|
+
[42, 205, 125],
|
132
|
+
[192, 233, 116],
|
133
|
+
[119, 170, 114],
|
134
|
+
[158, 138, 26],
|
135
|
+
[73, 190, 183],
|
136
|
+
[185, 229, 243],
|
137
|
+
[227, 107, 55],
|
138
|
+
[196, 205, 202],
|
139
|
+
[132, 143, 60],
|
140
|
+
[233, 192, 237],
|
141
|
+
[62, 150, 220],
|
142
|
+
[205, 201, 141],
|
143
|
+
[106, 140, 190],
|
144
|
+
[161, 131, 205],
|
145
|
+
[135, 134, 158],
|
146
|
+
[198, 139, 81],
|
147
|
+
[115, 171, 32],
|
148
|
+
[101, 181, 67],
|
149
|
+
[149, 137, 119],
|
150
|
+
[37, 142, 183],
|
151
|
+
[183, 130, 175],
|
152
|
+
[168, 125, 133],
|
153
|
+
[124, 142, 87],
|
154
|
+
[236, 156, 171],
|
155
|
+
[232, 194, 91],
|
156
|
+
[219, 200, 69],
|
157
|
+
[144, 219, 34],
|
158
|
+
[219, 95, 187],
|
159
|
+
[145, 154, 217],
|
160
|
+
[165, 185, 100],
|
161
|
+
[127, 238, 163],
|
162
|
+
[224, 178, 198],
|
163
|
+
[119, 153, 120],
|
164
|
+
[124, 212, 92],
|
165
|
+
[172, 161, 105],
|
166
|
+
[231, 155, 135],
|
167
|
+
[157, 132, 101],
|
168
|
+
[122, 185, 146],
|
169
|
+
[53, 166, 51],
|
170
|
+
[70, 163, 90],
|
171
|
+
[150, 190, 213],
|
172
|
+
[210, 107, 60],
|
173
|
+
[166, 152, 185],
|
174
|
+
[159, 194, 159],
|
175
|
+
[39, 141, 222],
|
176
|
+
[202, 176, 161],
|
177
|
+
[95, 140, 229],
|
178
|
+
[168, 142, 87],
|
179
|
+
[93, 170, 203],
|
180
|
+
[159, 142, 54],
|
181
|
+
[14, 168, 39],
|
182
|
+
[94, 150, 149],
|
183
|
+
[187, 206, 136],
|
184
|
+
[157, 224, 166],
|
185
|
+
[235, 158, 208],
|
186
|
+
[109, 232, 216],
|
187
|
+
[141, 201, 87],
|
188
|
+
[208, 124, 118],
|
189
|
+
[142, 125, 214],
|
190
|
+
[19, 237, 174],
|
191
|
+
[72, 219, 41],
|
192
|
+
[234, 102, 111],
|
193
|
+
[168, 142, 79],
|
194
|
+
[188, 135, 35],
|
195
|
+
[95, 155, 143],
|
196
|
+
[148, 173, 116],
|
197
|
+
[223, 112, 95],
|
198
|
+
[228, 128, 236],
|
199
|
+
[206, 114, 54],
|
200
|
+
[195, 119, 88],
|
201
|
+
[235, 140, 94],
|
202
|
+
[235, 202, 125],
|
203
|
+
[233, 155, 153],
|
204
|
+
[214, 214, 238],
|
205
|
+
[246, 200, 35],
|
206
|
+
[151, 125, 171],
|
207
|
+
[132, 145, 172],
|
208
|
+
[131, 142, 118],
|
209
|
+
[199, 126, 150],
|
210
|
+
[61, 162, 123],
|
211
|
+
[58, 176, 151],
|
212
|
+
[215, 141, 69],
|
213
|
+
[225, 154, 220],
|
214
|
+
[220, 77, 167],
|
215
|
+
[233, 161, 64],
|
216
|
+
[130, 221, 137],
|
217
|
+
[81, 191, 129],
|
218
|
+
[169, 162, 140],
|
219
|
+
[174, 177, 222],
|
220
|
+
[236, 174, 47],
|
221
|
+
[233, 188, 180],
|
222
|
+
[69, 222, 172],
|
223
|
+
[71, 232, 93],
|
224
|
+
[118, 211, 238],
|
225
|
+
[157, 224, 83],
|
226
|
+
[218, 105, 73],
|
227
|
+
[126, 169, 36]
|
228
|
+
].freeze
|
229
|
+
|
230
|
+
def initialize
|
231
|
+
@palette = PALETTE
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: letter_avatar_simple
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Discourse Developers
|
8
|
+
- Krzysiek Szczuka
|
9
|
+
- Mateusz Mróz
|
10
|
+
- Jason Lee
|
11
|
+
- Abe Voelker
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
date: 2019-05-28 00:00:00.000000000 Z
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: mini_magick
|
19
|
+
requirement: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - "~>"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '4.0'
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '4.0'
|
31
|
+
description:
|
32
|
+
email:
|
33
|
+
- abe@abevoelker.com
|
34
|
+
executables: []
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- CHANGELOG.md
|
39
|
+
- README.md
|
40
|
+
- Roboto-Medium
|
41
|
+
- lib/letter_avatar_simple.rb
|
42
|
+
- lib/letter_avatar_simple/configuration.rb
|
43
|
+
- lib/letter_avatar_simple/identity.rb
|
44
|
+
- lib/letter_avatar_simple/palette.rb
|
45
|
+
- lib/letter_avatar_simple/palettes/google.rb
|
46
|
+
- lib/letter_avatar_simple/palettes/i_want_hue.rb
|
47
|
+
- lib/letter_avatar_simple/version.rb
|
48
|
+
homepage: https://github.com/abevoelker/letter_avatar_simple
|
49
|
+
licenses:
|
50
|
+
- GPL-2.0
|
51
|
+
metadata: {}
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubygems_version: 3.0.3
|
68
|
+
signing_key:
|
69
|
+
specification_version: 4
|
70
|
+
summary: Generate letter image avatars based on user initials
|
71
|
+
test_files: []
|