tiledenticon 0.0.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/lib/face.rb +64 -0
- data/lib/tiledenticon.rb +50 -0
- data/lib/tiler.rb +184 -0
- metadata +46 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c856d1f52ab0369d34a8abd4a42a85d7272b7053
|
4
|
+
data.tar.gz: f3e5d7a662f909d76bc0d1e11db31dfddba547f9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 65a6ee4426399a52b244a059d70a58e6cbf01dea68b4721cbbb77475d74b6f92d4de68c302bb96f585c00ed027bb1d0cb4bfed1ec96cdd016bfbfb11a140ec10
|
7
|
+
data.tar.gz: 14b4b0cdaf46d353d8055eecfb9e111c5b6553ff4eefe6b1b836c388b24a468a6b215815f46cd6f9f33d8c48d0ff540fc37c199baf13acfae9297036c3bb584b
|
data/lib/face.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
class Face
|
2
|
+
def initialize x, axis1, axis2
|
3
|
+
@pos = x
|
4
|
+
@a_min = min(axis1, axis2)
|
5
|
+
@a_max = max(axis1, axis2)
|
6
|
+
end
|
7
|
+
|
8
|
+
def tick translation_matrix
|
9
|
+
ret = nil
|
10
|
+
@pos = translation_matrix * @pos
|
11
|
+
case @a_min
|
12
|
+
when 0
|
13
|
+
case @a_max
|
14
|
+
when 1
|
15
|
+
@a_min = 1
|
16
|
+
@a_max = 2
|
17
|
+
when 2
|
18
|
+
@a_min = 1
|
19
|
+
@a_max = 3
|
20
|
+
when 3
|
21
|
+
@a_min = 0
|
22
|
+
@a_max = 1
|
23
|
+
|
24
|
+
ret = Face.new(@pos.clone, 1, 3)
|
25
|
+
shunt_pos
|
26
|
+
end
|
27
|
+
when 1
|
28
|
+
case @a_max
|
29
|
+
when 2
|
30
|
+
@a_min = 2
|
31
|
+
@a_max = 3
|
32
|
+
when 3
|
33
|
+
@a_min = 0
|
34
|
+
@a_max = 2
|
35
|
+
|
36
|
+
ret = Face.new(@pos.clone, 2, 3)
|
37
|
+
shunt_pos
|
38
|
+
end
|
39
|
+
when 2
|
40
|
+
@a_min = 0
|
41
|
+
@a_max = 3
|
42
|
+
|
43
|
+
shunt_pos
|
44
|
+
end
|
45
|
+
return ret
|
46
|
+
end
|
47
|
+
|
48
|
+
private def shunt_pos
|
49
|
+
a = @pos.to_a
|
50
|
+
@pos = Vector[a[0] - $dirmultx, a[1], a[2], a[3] + $dirmultx]
|
51
|
+
end
|
52
|
+
|
53
|
+
def pos
|
54
|
+
@pos
|
55
|
+
end
|
56
|
+
|
57
|
+
def min_axis
|
58
|
+
@a_min
|
59
|
+
end
|
60
|
+
|
61
|
+
def max_axis
|
62
|
+
@a_max
|
63
|
+
end
|
64
|
+
end
|
data/lib/tiledenticon.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'tiler.rb'
|
2
|
+
|
3
|
+
class Tiledenticon
|
4
|
+
def initialize out_folder
|
5
|
+
@out_folder = out_folder
|
6
|
+
end
|
7
|
+
def create input
|
8
|
+
md5 = Digest::MD5.new
|
9
|
+
md5 << input
|
10
|
+
hash = md5.hexdigest
|
11
|
+
|
12
|
+
fromMD5 "#{@out_folder}/#{input}.png", hash
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def fromMD5 filename, hash
|
17
|
+
r = Hashrander.new(hash)
|
18
|
+
hue = r.get_rand 3, 360
|
19
|
+
s1 = 0.5 + (r.get_rand 2, 0.5)
|
20
|
+
s2 = 0.5 + (r.get_rand 2, 0.5 * s1)
|
21
|
+
|
22
|
+
p_x = 0.5 + (r.get_rand 2, 1.15)
|
23
|
+
p_y = 0.5 + (r.get_rand 2, 1.15)
|
24
|
+
|
25
|
+
TilerBuilder.new(filename).set_hue(hue).set_sat_major(s1).set_sat_minor(s2).set_projection_lambda(p_x, p_y).build
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Hashrander
|
30
|
+
def initialize hash
|
31
|
+
@hash_i = 0
|
32
|
+
@hash = hash
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_rand sample_size, max
|
36
|
+
i1 = @hash_i % @hash.length
|
37
|
+
|
38
|
+
hash_str = @hash[i1, sample_size]
|
39
|
+
|
40
|
+
# Check if wrap over length
|
41
|
+
rem = i1 + sample_size - @hash.length
|
42
|
+
if rem > 0
|
43
|
+
hash_str << @hash[0, rem]
|
44
|
+
end
|
45
|
+
|
46
|
+
@hash_i += sample_size
|
47
|
+
|
48
|
+
max * hash_str.hex/(16**sample_size)
|
49
|
+
end
|
50
|
+
end
|
data/lib/tiler.rb
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
# From here
|
2
|
+
# http://www.mathematicians.org.uk/eoh/files/Harriss_ANGASRP.pdf
|
3
|
+
|
4
|
+
require 'face'
|
5
|
+
|
6
|
+
require 'chunky_png'
|
7
|
+
require 'matrix'
|
8
|
+
require 'digest'
|
9
|
+
|
10
|
+
def min(*values)
|
11
|
+
values.min
|
12
|
+
end
|
13
|
+
|
14
|
+
def max(*values)
|
15
|
+
values.max
|
16
|
+
end
|
17
|
+
|
18
|
+
def min_max_to_i min, max
|
19
|
+
return max - 1 if min == 0
|
20
|
+
return 1 + max if min == 1
|
21
|
+
return 5
|
22
|
+
end
|
23
|
+
$dirmultx = 1
|
24
|
+
$dirmulty = 1
|
25
|
+
|
26
|
+
|
27
|
+
class TilerBuilder
|
28
|
+
|
29
|
+
def initialize filename
|
30
|
+
@hue = 345
|
31
|
+
@image_width = 256
|
32
|
+
@image_height = 256
|
33
|
+
@ox = @image_width/2
|
34
|
+
@oy = @image_height/2
|
35
|
+
@scale = -24
|
36
|
+
@ticks = 22
|
37
|
+
@filename = filename
|
38
|
+
@sat_major = 1
|
39
|
+
@sat_minor = 0.8
|
40
|
+
@projection_lambda = Complex(1.01891, 0.602565)
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_scale scale
|
45
|
+
@scale = scale
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_hue hue
|
50
|
+
@hue = hue
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_sat_major s
|
55
|
+
@sat_major = s
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_sat_minor s
|
60
|
+
@sat_minor = s
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
def set_image_size width, height
|
65
|
+
@image_width = width
|
66
|
+
@image_height = height
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def set_ticks ticks
|
71
|
+
@ticks = ticks
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
def set_projection_lambda x, y
|
76
|
+
@projection_lambda = Complex(x, y)
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
def build
|
81
|
+
t = Tiler.new(@image_width, @image_height, @scale, @hue, @sat_major,
|
82
|
+
@sat_minor, @projection_lambda)
|
83
|
+
t.tile(@ticks, @filename)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
class Tiler
|
89
|
+
|
90
|
+
@@translation_matrix =
|
91
|
+
Matrix[[0, 0, 0, -1],
|
92
|
+
[1, 0, 0, 0],
|
93
|
+
[0, 1, 0, 0],
|
94
|
+
[0, 0, 1, 1]]
|
95
|
+
|
96
|
+
def initialize image_width, image_height, scale, hue, sat_major, sat_minor, projection_lambda
|
97
|
+
@h1 = hue
|
98
|
+
@h2 = (hue + 360/2) % 360
|
99
|
+
|
100
|
+
@colors = [
|
101
|
+
ChunkyPNG::Color.from_hsv(0, 0, 1),
|
102
|
+
ChunkyPNG::Color.from_hsv(0, 0.0, 1),
|
103
|
+
ChunkyPNG::Color.from_hsv(@h1, sat_major, 1),
|
104
|
+
ChunkyPNG::Color.from_hsv(@h2, sat_major, 1),
|
105
|
+
ChunkyPNG::Color.from_hsv(@h1, sat_minor, 0.6),
|
106
|
+
ChunkyPNG::Color.from_hsv(@h2, sat_minor, 0.6)
|
107
|
+
]
|
108
|
+
|
109
|
+
|
110
|
+
@image_width = image_width
|
111
|
+
@image_height = image_height
|
112
|
+
@ox = @image_width/2
|
113
|
+
@oy = @image_height/2
|
114
|
+
@scale = scale
|
115
|
+
|
116
|
+
@canonical_x = []
|
117
|
+
@canonical_y = []
|
118
|
+
for i in 0..3 do
|
119
|
+
c = projection_lambda ** i
|
120
|
+
@canonical_x << c.real
|
121
|
+
@canonical_y << c.imaginary
|
122
|
+
end
|
123
|
+
@all_faces = [Face.new(Vector[0, 0, 0, 0], 2, 3)]
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
def to_image_space p
|
129
|
+
{x: (@ox + @global_xo -@scale * (p[0] * @canonical_x[0] + p[1] * @canonical_x[1] +
|
130
|
+
p[2] * @canonical_x[2] + p[3] * @canonical_x[3])),
|
131
|
+
y: (@oy + @global_yo + @scale * (p[0] * @canonical_y[0] + p[1] * @canonical_y[1] +
|
132
|
+
p[2] * @canonical_y[2] + p[3] * @canonical_y[3]))};
|
133
|
+
end
|
134
|
+
|
135
|
+
def tile ticks, filename
|
136
|
+
for i in 1 .. ticks
|
137
|
+
new_list = []
|
138
|
+
@all_faces.each do |face|
|
139
|
+
new_list << face
|
140
|
+
ret = face.tick @@translation_matrix
|
141
|
+
new_list << ret unless ret.nil?
|
142
|
+
end
|
143
|
+
@all_faces = new_list
|
144
|
+
|
145
|
+
@global_xo = 0
|
146
|
+
@global_yo = 0
|
147
|
+
p = to_image_space(@all_faces[0].pos.to_a)
|
148
|
+
@global_xo = @ox - p[:x]
|
149
|
+
@global_yo = @oy - p[:y]
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
# Draw
|
154
|
+
image = ChunkyPNG::Image.new(@image_width, @image_height, ChunkyPNG::Color::TRANSPARENT)
|
155
|
+
|
156
|
+
puts "Tiledenticon: Drawing image"
|
157
|
+
@all_faces.each_with_index do |face, i|
|
158
|
+
print "Tiledenticon: Face #{i}\r"
|
159
|
+
|
160
|
+
p1 = to_image_space (face.pos.to_a)
|
161
|
+
|
162
|
+
p2_m = face.pos.to_a
|
163
|
+
p2_m[face.min_axis] += 1
|
164
|
+
p2 = to_image_space(p2_m)
|
165
|
+
|
166
|
+
p3_m = face.pos.to_a
|
167
|
+
p3_m[face.max_axis] += 1
|
168
|
+
p3 = to_image_space(p3_m)
|
169
|
+
|
170
|
+
p4_m = face.pos.to_a
|
171
|
+
p4_m[face.min_axis] += 1
|
172
|
+
p4_m[face.max_axis] += 1
|
173
|
+
p4 = to_image_space(p4_m)
|
174
|
+
|
175
|
+
|
176
|
+
points = ChunkyPNG::Vector.new([p1, p2, p4, p3])
|
177
|
+
color = @colors[min_max_to_i face.min_axis, face.max_axis]
|
178
|
+
image.polygon(points, ChunkyPNG::Color::TRANSPARENT, color)
|
179
|
+
end
|
180
|
+
puts "\nTiledenticon: Saving image to #{filename}"
|
181
|
+
image.save(filename, :interlace => false)
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tiledenticon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Slocombe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: More interesting identicons
|
14
|
+
email: ds4314@ic.ac.uk
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/face.rb
|
20
|
+
- lib/tiledenticon.rb
|
21
|
+
- lib/tiler.rb
|
22
|
+
homepage: https://github.com/danslocombe/tiledenticon
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 2.5.1
|
43
|
+
signing_key:
|
44
|
+
specification_version: 4
|
45
|
+
summary: Tiledenticon
|
46
|
+
test_files: []
|