face-no-more 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +37 -0
- data/face-no-more.gemspec +26 -0
- data/lib/face-no-more/version.rb +4 -0
- data/lib/face-no-more.rb +168 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 124bf237d91787cc4cfd04d77c117f0aff8069eeae6382707d1669566d4e25a7
|
4
|
+
data.tar.gz: 3c0b4aa07cf08603f80ef380b113a9e8ac6ee7c297dbe6ac84ed87a4df778091
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd9bd3f7bb2f9818c2524f39268516645abc6830a86d83ff6ae94b6a5d9303c8933f941b08b0ed6259e80f6fb91c342ebdeffeed156d227e53379c1d6348d019
|
7
|
+
data.tar.gz: 2bf2b7276b1489d924aaf1fb2d09d79a74bc2b9ee9db87a7548420942099b5f8a2038d1daf4e7b7b4a150bd3942a3f80ed77812e1bb1229ba3f6726d43258663
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
Description
|
2
|
+
===========
|
3
|
+
|
4
|
+
Allow generating avatar pictures from ruby.
|
5
|
+
|
6
|
+
The supported avatar type are: `cat`, `bird`, `abstract`, `mobilizon`,
|
7
|
+
`8bit-female` and `8bit-male`.
|
8
|
+
|
9
|
+
|
10
|
+
Examples
|
11
|
+
========
|
12
|
+
|
13
|
+
~~~ruby
|
14
|
+
require 'face-no-more'
|
15
|
+
|
16
|
+
# Number of possible avatars
|
17
|
+
count = FaceNoMore.possibilities(:mobilizon)
|
18
|
+
|
19
|
+
# Generate avatar picture
|
20
|
+
jpg = FaceNoMore.generate(:cat, "foo@example.com", format: :jpg, size: 256)
|
21
|
+
png = FaceNoMore.generate(:bird, 12345678910)
|
22
|
+
~~~
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Artworks
|
27
|
+
========
|
28
|
+
* `cat`, `bird`, `abstract` and `mobilizon` are from [David Revoy][2]
|
29
|
+
licensed under [CC-By 4.0][4]
|
30
|
+
* `8bit-female` and `8bit-male` are from [matveyco][3]
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
[2]: http://www.peppercarrot.com
|
35
|
+
[3]: https://github.com/matveyco/8biticon
|
36
|
+
[4]: http://creativecommons.org/licenses/by/4.0/
|
37
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require_relative 'lib/face-no-more/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'face-no-more'
|
7
|
+
s.version = FaceNoMore::VERSION
|
8
|
+
s.summary = "Generate avatars"
|
9
|
+
s.description = <<~EOF
|
10
|
+
Generate avatars from artwork assets.
|
11
|
+
Included 5 different types of artwork: cat, bird, abstract, mobilizon, and 8bit.
|
12
|
+
EOF
|
13
|
+
|
14
|
+
s.homepage = 'https://gitlab.com/sdalu/face-no-more'
|
15
|
+
s.license = 'MIT'
|
16
|
+
|
17
|
+
s.authors = [ "Stéphane D'Alu" ]
|
18
|
+
s.email = [ 'stephane.dalu@insa-lyon.fr' ]
|
19
|
+
|
20
|
+
s.files = %w[ README.md face-no-more.gemspec ] +
|
21
|
+
Dir['lib/**/*.rb'] + Dir['data/**']
|
22
|
+
|
23
|
+
s.add_dependency 'rmagick'
|
24
|
+
s.add_development_dependency 'yard', '~>0'
|
25
|
+
s.add_development_dependency 'rake', '~>13'
|
26
|
+
end
|
data/lib/face-no-more.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'securerandom'
|
3
|
+
require 'digest'
|
4
|
+
require 'rmagick'
|
5
|
+
|
6
|
+
|
7
|
+
# Generate avatar
|
8
|
+
#
|
9
|
+
# ~~~ruby
|
10
|
+
# require 'face-no-more'
|
11
|
+
#
|
12
|
+
# FaceNoMore.generate(:cat, "foo@example.com", format: :jpg, size: 256)
|
13
|
+
# FaceNoMore.generate(:bird, 12345678910)
|
14
|
+
# ~~~
|
15
|
+
|
16
|
+
|
17
|
+
module FaceNoMore
|
18
|
+
# @!visibility private
|
19
|
+
IMAGES_DIR = File.join(__dir__, '..', 'data', 'images')
|
20
|
+
|
21
|
+
# @!visibility private
|
22
|
+
# NOTE: - Limited to 16 parts
|
23
|
+
# - Keep sizes sorted from small to big
|
24
|
+
DESCRIPTIONS = {
|
25
|
+
:cat => {
|
26
|
+
:author => 'David Revoy',
|
27
|
+
:license => 'CC-BY',
|
28
|
+
:src => 'https://www.peppercarrot.com/extras/html/2016_cat-generator/',
|
29
|
+
:sizes => [ 256 ],
|
30
|
+
:partname => "%<part>s_%<id>d.png",
|
31
|
+
:parts => { :body => 1..15,
|
32
|
+
:fur => 1..10,
|
33
|
+
:eyes => 1..15,
|
34
|
+
:mouth => 1..10,
|
35
|
+
:accessorie => 1..20 },
|
36
|
+
|
37
|
+
},
|
38
|
+
:bird => {
|
39
|
+
:author => 'David Revoy',
|
40
|
+
:license => 'CC-BY',
|
41
|
+
:src => 'https://www.peppercarrot.com/extras/html/2019_bird-generator/',
|
42
|
+
:sizes => [ 256 ],
|
43
|
+
:partname => "%<part>s_%<id>d.png",
|
44
|
+
:parts => { :tail => 1..9,
|
45
|
+
:hoop => 1..10,
|
46
|
+
:body => 1..9,
|
47
|
+
:wing => 1..9,
|
48
|
+
:eyes => 1..9,
|
49
|
+
:bec => 1..9,
|
50
|
+
:accessorie => 1..20, },
|
51
|
+
},
|
52
|
+
:abstract => {
|
53
|
+
:author => 'David Revoy',
|
54
|
+
:license => 'CC-BY',
|
55
|
+
:src => 'https://www.peppercarrot.com/extras/html/2017_abstract-generator/',
|
56
|
+
:sizes => [ 256 ],
|
57
|
+
:partname => "%<part>s_%<id>d.png",
|
58
|
+
:parts => { :body => 1..15,
|
59
|
+
:fur => 1..10,
|
60
|
+
:eyes => 1..15,
|
61
|
+
:mouth => 1..10, },
|
62
|
+
},
|
63
|
+
:mobilizon => {
|
64
|
+
:author => 'David Revoy',
|
65
|
+
:license => 'CC-BY',
|
66
|
+
:src => 'https://www.peppercarrot.com/extras/html/2020_mobilizon-generator/',
|
67
|
+
:sizes => [ 256, 1024 ],
|
68
|
+
:partname => "%<part>s_%<id>02d.png",
|
69
|
+
:parts => { :body => 1..25,
|
70
|
+
:nose => 1..10,
|
71
|
+
:tail => 1..5,
|
72
|
+
:eyes => 1..10,
|
73
|
+
:mouth => 1..10,
|
74
|
+
:accessories => 1..20,
|
75
|
+
:misc => 1..20,
|
76
|
+
:hat => 1..20, },
|
77
|
+
},
|
78
|
+
:'8bit-female' => {
|
79
|
+
:author => 'matveyco',
|
80
|
+
:src => 'https://github.com/matveyco/8biticon',
|
81
|
+
:path => '8bit/female',
|
82
|
+
:sizes => [ 400 ],
|
83
|
+
:partname => "%<part>s%<id>d.png",
|
84
|
+
:parts => { :face => 1..4,
|
85
|
+
:clothes => 1..59,
|
86
|
+
:mouth => 1..17,
|
87
|
+
:head => 1..33,
|
88
|
+
:eye => 1..53, },
|
89
|
+
},
|
90
|
+
:'8bit-male' => {
|
91
|
+
:author => 'matveyco',
|
92
|
+
:src => 'https://github.com/matveyco/8biticon',
|
93
|
+
:path => '8bit/male',
|
94
|
+
:sizes => [ 400 ],
|
95
|
+
:partname => "%<part>s%<id>d.png",
|
96
|
+
:parts => { :face => 1..4,
|
97
|
+
:clothes => 1..65,
|
98
|
+
:mouth => 1..26,
|
99
|
+
:hair => 1..36,
|
100
|
+
:eye => 1..32, },
|
101
|
+
},
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
# List of supported avatar types
|
106
|
+
TYPES = DESCRIPTIONS.keys.freeze
|
107
|
+
|
108
|
+
|
109
|
+
# Return the number of different avatar possible
|
110
|
+
#
|
111
|
+
# @param type type of avatar
|
112
|
+
#
|
113
|
+
# @return [Integer]
|
114
|
+
#
|
115
|
+
def self.possibilities(type)
|
116
|
+
DESCRIPTIONS.fetch(type) {
|
117
|
+
raise ArgumentError, "unsupported type (#{type})"
|
118
|
+
}[:parts].map {|part, range| range.last - range.first }
|
119
|
+
.reduce(:*)
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
# Generate an avatar
|
124
|
+
#
|
125
|
+
# @param type [Symbol] type of avatar
|
126
|
+
# @param seed [String,Array<Integer>,Integer,nil] seed
|
127
|
+
# @param format [:Symbol] picture format (as defined in ImageMagick)
|
128
|
+
# @param quality [Integer] picture quality (1..100)
|
129
|
+
# @param size [Integer] picture size
|
130
|
+
#
|
131
|
+
# @return [String]
|
132
|
+
#
|
133
|
+
def self.generate(type, seed = nil, format: :png, quality: 90, size: 256)
|
134
|
+
desc = DESCRIPTIONS.fetch(type) {
|
135
|
+
raise ArgumentError, "unsupported type (#{type})" }
|
136
|
+
parts = desc[:parts]
|
137
|
+
sizes = desc[:sizes]
|
138
|
+
path = File.join(IMAGES_DIR, desc[:path] || type.to_s)
|
139
|
+
partsize = sizes.find {|s| size > s } || sizes.last
|
140
|
+
seedbytes = case seed
|
141
|
+
when nil then SecureRandom.random_bytes(16).bytes
|
142
|
+
when String then Digest::MD5.digest(seed).bytes
|
143
|
+
when Array then seed
|
144
|
+
when Integer then parts.map {|_, r|
|
145
|
+
count = r.end - r.begin + 1
|
146
|
+
seed, val = seed.divmod(count)
|
147
|
+
val }
|
148
|
+
end
|
149
|
+
|
150
|
+
if parts.size > seedbytes.size
|
151
|
+
raise ArgumentError, "seed doesn't hold enough elements"
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
files = parts.each_with_index.map {|(part, range), index|
|
156
|
+
mod = (range.end - range.begin) + 1
|
157
|
+
id = range.first + seedbytes[index] % mod
|
158
|
+
File.join(path, partsize.to_s,
|
159
|
+
desc[:partname] % { :part => part, :id => id })
|
160
|
+
}
|
161
|
+
|
162
|
+
Magick::ImageList.new(*files).flatten_images
|
163
|
+
.change_geometry!("#{size}x#{size}") { |cols, rows, me|
|
164
|
+
me.thumbnail!(cols, rows)
|
165
|
+
}.to_blob {|me| me.format = format.to_s
|
166
|
+
me.quality = quality }
|
167
|
+
end
|
168
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: face-no-more
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stéphane D'Alu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rmagick
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: yard
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13'
|
55
|
+
description: |
|
56
|
+
Generate avatars from artwork assets.
|
57
|
+
Included 5 different types of artwork: cat, bird, abstract, mobilizon, and 8bit.
|
58
|
+
email:
|
59
|
+
- stephane.dalu@insa-lyon.fr
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- README.md
|
65
|
+
- face-no-more.gemspec
|
66
|
+
- lib/face-no-more.rb
|
67
|
+
- lib/face-no-more/version.rb
|
68
|
+
homepage: https://gitlab.com/sdalu/face-no-more
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubygems_version: 3.0.8
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: Generate avatars
|
91
|
+
test_files: []
|