face-no-more 0.1.1
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.
- 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: []
|