jazzicon 0.1.0
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/LICENSE.txt +21 -0
- data/README.md +44 -0
- data/lib/jazzicon/helpers/color_helpers.rb +23 -0
- data/lib/jazzicon/helpers/geometry_helpers.rb +104 -0
- data/lib/jazzicon/helpers/image_helpers.rb +25 -0
- data/lib/jazzicon/icon.rb +88 -0
- data/lib/jazzicon/version.rb +5 -0
- data/lib/jazzicon.rb +8 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1c28a74ab282c10c0caea691c048f7bc5598ee0cc92a867950b8bd20176cd4e2
|
4
|
+
data.tar.gz: befd3d81c9bbed1bfcecac4bc6d911761f053814eb2066d27ce8904b13c36444
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7c5d2eef67d11f3284e34f567ea236510fca7f746f9e4281a645aa7b6121bc9436a78a777401bcdbf08a0d0f140512497423c588184f8d147e44692db3f1e723
|
7
|
+
data.tar.gz: 892a0e2f7a0d3ec3a14208f1df3f283392a0e419a7f0e3c8cbfd0c556fdf3dbfe4e5cbe8b434ab8298309204313bb26e2c3566f310653b8e13028c03d64c011d
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Arux Software, Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Jazzicon
|
2
|
+
|
3
|
+
This is a ruby port of https://github.com/danfinlay/jazzicon
|
4
|
+
|
5
|
+
> Say goodbye to boring blocky identicons that look like they came out of the 70s, and replace them with jazzy, colorful collages that more likely came out of the 80's.
|
6
|
+
|
7
|
+

|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'jazzicon'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle install
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install jazzicon
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'jazzicon'
|
29
|
+
Jazzicon::Icon.generate("random string or integer").save("icon.png")
|
30
|
+
```
|
31
|
+
|
32
|
+
## Development
|
33
|
+
|
34
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
35
|
+
|
36
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
37
|
+
|
38
|
+
## Contributing
|
39
|
+
|
40
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Arux-Software/jazzicon_ruby.
|
41
|
+
|
42
|
+
## License
|
43
|
+
|
44
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jazzicon
|
4
|
+
HUE_WOBBLE = 30
|
5
|
+
# The Jazzicon::ColorHelpers module provides color-related helper methods.
|
6
|
+
module ColorHelpers
|
7
|
+
# Shifts the hue of the given colors by a random amount.
|
8
|
+
#
|
9
|
+
# @param colors [Array<String>] Array of hex color strings.
|
10
|
+
# @param random [Random] Random object for deterministic randomness.
|
11
|
+
# @return [Array<String>] Array of hue-shifted colors.
|
12
|
+
def self.hue_shift(colors, random)
|
13
|
+
amount = (random.rand * 30) - (HUE_WOBBLE / 2.0)
|
14
|
+
|
15
|
+
colors.map do |hex|
|
16
|
+
hsl = ChunkyPNG::Color.to_hsl(ChunkyPNG::Color.from_hex(hex))
|
17
|
+
hsl[0] = (hsl[0] + amount) % 360
|
18
|
+
hsl[3] = 255
|
19
|
+
ChunkyPNG::Color.from_hsl(*hsl)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jazzicon
|
4
|
+
Rectangle = Struct.new(:corners, keyword_init: true)
|
5
|
+
Point = Struct.new(:x, :y, keyword_init: true)
|
6
|
+
Size = Struct.new(:width, :height, keyword_init: true)
|
7
|
+
|
8
|
+
# The Jazzicon::GeometryHelpers module provides methods for geometric calculations and operations.
|
9
|
+
module GeometryHelpers
|
10
|
+
# Adds a randomly positioned and rotated rectangle to the given image.
|
11
|
+
#
|
12
|
+
# @param image [ChunkyPNG::Image] The image to modify.
|
13
|
+
# @param diameter [Integer] The diameter of the image.
|
14
|
+
# @param color [String] The color of the rectangle.
|
15
|
+
# @param index [Integer] The index of the current shape.
|
16
|
+
# @param total [Integer] The total number of shapes.
|
17
|
+
# @param random_numbers [Array<Float>] Array of random numbers for positioning and rotation.
|
18
|
+
def self.random_rectangle(diameter, index, total, random_numbers)
|
19
|
+
velocity, rotation, angle = generate_momentum(diameter, index, total, random_numbers)
|
20
|
+
center = diameter / 2.0
|
21
|
+
|
22
|
+
point = Point.new(
|
23
|
+
x: center + (Math.cos(angle) * velocity),
|
24
|
+
y: center + (Math.sin(angle) * velocity)
|
25
|
+
)
|
26
|
+
size = Size.new(width: diameter, height: diameter)
|
27
|
+
|
28
|
+
# Draw the rectangle
|
29
|
+
rotated_rectangle(point, size, rotation, center)
|
30
|
+
end
|
31
|
+
|
32
|
+
private_class_method def self.generate_momentum(diameter, index, total, random_numbers)
|
33
|
+
first_rot = random_numbers.pop
|
34
|
+
velocity = (diameter / total * random_numbers.pop) + (index * diameter / total)
|
35
|
+
rotation = (first_rot * 360) + (random_numbers.pop * 180)
|
36
|
+
angle = Math::PI * 2 * first_rot
|
37
|
+
|
38
|
+
[velocity, rotation, angle]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Draws a rotated rectangle on the image.
|
42
|
+
#
|
43
|
+
# @param image [ChunkyPNG::Image] The image to modify.
|
44
|
+
# @param x [Float] The x-coordinate of the rectangle's center.
|
45
|
+
# @param y [Float] The y-coordinate of the rectangle's center.
|
46
|
+
# @param width [Float] The width of the rectangle.
|
47
|
+
# @param height [Float] The height of the rectangle.
|
48
|
+
# @param color [String] The color of the rectangle.
|
49
|
+
# @param rotation [Float] The rotation angle in degrees.
|
50
|
+
# @param center [Float] The center point of the image.
|
51
|
+
def self.rotated_rectangle(point, size, rotation, center)
|
52
|
+
# Define the four corners of the rectangle
|
53
|
+
corners = rotate_corners(calculate_corners(point, size), rotation, center)
|
54
|
+
Rectangle.new(corners: corners)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Calculates the four corners of a rectangle given its width and height.
|
58
|
+
#
|
59
|
+
# @param x [Float] The x-coordinate of the rectangle's center.
|
60
|
+
# @param y [Float] The y-coordinate of the rectangle's center.
|
61
|
+
# @param width [Float] The width of the rectangle.
|
62
|
+
# @param height [Float] The height of the rectangle.
|
63
|
+
# @return [Array<Array<Float>>] Array of coordinates representing the rectangle's corners.
|
64
|
+
def self.calculate_corners(point, size)
|
65
|
+
half_width = size.width / 2
|
66
|
+
half_height = size.height / 2
|
67
|
+
|
68
|
+
offsets = [
|
69
|
+
[-half_width, -half_height], # Top-left
|
70
|
+
[half_width, -half_height], # Top-right
|
71
|
+
[half_width, half_height], # Bottom-right
|
72
|
+
[-half_width, half_height] # Bottom-left
|
73
|
+
]
|
74
|
+
|
75
|
+
offsets.map { |dx, dy| Point.new(x: point.x + dx, y: point.y + dy) }
|
76
|
+
end
|
77
|
+
|
78
|
+
# Rotates the given corners of a rectangle around its center.
|
79
|
+
#
|
80
|
+
# @param corners [Array<Array<Float>>] Array of rectangle corner coordinates.
|
81
|
+
# @param rotation [Float] The rotation angle in degrees.
|
82
|
+
# @param center [Float] The center point of the image.
|
83
|
+
# @return [Array<Array<Float>>] Array of rotated corner coordinates.
|
84
|
+
def self.rotate_corners(corners, rotation, center)
|
85
|
+
rad_rotation = rotation * Math::PI / 180
|
86
|
+
|
87
|
+
corners.map do |point|
|
88
|
+
rotate_point(point, rad_rotation, center)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private_class_method def self.rotate_point(point, rad_rotation, center)
|
93
|
+
point.x -= center
|
94
|
+
point.y -= center
|
95
|
+
cos_theta = Math.cos(rad_rotation)
|
96
|
+
sin_theta = Math.sin(rad_rotation)
|
97
|
+
|
98
|
+
[
|
99
|
+
(cos_theta * point.x) - (sin_theta * point.y) + center,
|
100
|
+
(sin_theta * point.x) + (cos_theta * point.y) + center
|
101
|
+
]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "chunky_png"
|
4
|
+
|
5
|
+
module Jazzicon
|
6
|
+
# The Jazzicon::ImageHelpers module provides methods for adjusting the whole image.
|
7
|
+
module ImageHelpers
|
8
|
+
# Crops the image to a perfect circle.
|
9
|
+
#
|
10
|
+
# @param image [ChunkyPNG::Image] The image to crop.
|
11
|
+
# @param diameter [Integer] The diameter of the circle.
|
12
|
+
def self.crop_to_circle(image, diameter)
|
13
|
+
center = diameter / 2.0
|
14
|
+
radius = diameter / 2.0
|
15
|
+
|
16
|
+
image.height.times do |y|
|
17
|
+
image.width.times do |x|
|
18
|
+
# Check if the pixel is outside the circle
|
19
|
+
outside = (((x - center)**2) + ((y - center)**2)) > radius**2
|
20
|
+
image.set_pixel(x, y, ChunkyPNG::Color::TRANSPARENT) if outside
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "chunky_png"
|
4
|
+
require "digest"
|
5
|
+
|
6
|
+
require_relative "helpers/color_helpers"
|
7
|
+
require_relative "helpers/geometry_helpers"
|
8
|
+
require_relative "helpers/image_helpers"
|
9
|
+
|
10
|
+
module Jazzicon
|
11
|
+
COLORS = [
|
12
|
+
"#01888C", "#FC7500", "#34E90B", "#FF4A4A",
|
13
|
+
"#662E9B", "#FC7500", "#0284C7", "#A0D911",
|
14
|
+
"#A855F7", "#FF7875"
|
15
|
+
].freeze
|
16
|
+
Iteration = Struct.new(:index, :color, :random_numbers, keyword_init: true)
|
17
|
+
|
18
|
+
# The Jazzicon::Icon class provides functionality to generate jazzy and colorful identicons.
|
19
|
+
# These identicons are generated based on a given seed and can be customized by specifying the diameter and the number
|
20
|
+
# of shapes that make up the icon.
|
21
|
+
#
|
22
|
+
# The main steps involved in generating an icon include:
|
23
|
+
# - Hashing the seed to ensure deterministic randomness.
|
24
|
+
# - Randomly selecting and hue-shifting colors.
|
25
|
+
# - Generating and combining multiple layers of shapes (rectangles) to create a visually distinctive pattern.
|
26
|
+
# - Cropping the image into a circular form.
|
27
|
+
#
|
28
|
+
# Key Features:
|
29
|
+
# - Deterministic: The same seed always produces the same icon.
|
30
|
+
# - Customizable: Supports customization of diameter and shape count.
|
31
|
+
#
|
32
|
+
# Dependencies:
|
33
|
+
# - `chunky_png`: Used for image creation and manipulation.
|
34
|
+
#
|
35
|
+
# Example Usage:
|
36
|
+
# ```
|
37
|
+
# require "jazzicon/icon"
|
38
|
+
#
|
39
|
+
# seed = "example-seed"
|
40
|
+
# diameter = 500
|
41
|
+
# shape_count = 4
|
42
|
+
#
|
43
|
+
# icon = Jazzicon::Icon.generate(seed, diameter: diameter, shape_count: shape_count)
|
44
|
+
# icon.save("icon.png")
|
45
|
+
# ```
|
46
|
+
class Icon
|
47
|
+
# Generates a unique icon based on the given seed.
|
48
|
+
#
|
49
|
+
# @param seed [String, Integer] The input seed used to generate the icon.
|
50
|
+
# @param diameter [Integer] The diameter of the generated icon.
|
51
|
+
# @param shape_count [Integer] The number of shapes to include in the icon.
|
52
|
+
# @return [ChunkyPNG::Image] The generated icon image.
|
53
|
+
def self.generate(seed, diameter: 500, shape_count: 4)
|
54
|
+
random = random(seed)
|
55
|
+
colors = ColorHelpers.hue_shift(COLORS.shuffle(random: random), random)
|
56
|
+
|
57
|
+
final_image = ChunkyPNG::Image.new(diameter, diameter, colors.delete(colors.sample(random: random)))
|
58
|
+
|
59
|
+
# Generate each shape and adds it
|
60
|
+
iterations(shape_count, colors, random).each do |iteration|
|
61
|
+
rec = GeometryHelpers.random_rectangle(diameter, iteration.index, shape_count, iteration.random_numbers)
|
62
|
+
final_image.polygon(rec.corners, iteration.color, iteration.color)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Crop to a perfect circle
|
66
|
+
ImageHelpers.crop_to_circle(final_image, diameter)
|
67
|
+
|
68
|
+
# Profit!$!
|
69
|
+
final_image
|
70
|
+
end
|
71
|
+
|
72
|
+
private_class_method def self.random(seed)
|
73
|
+
# Hash the seed if it is a string
|
74
|
+
seed = Digest::SHA256.hexdigest(seed).to_i(16) if seed.is_a?(String)
|
75
|
+
Random.new(seed)
|
76
|
+
end
|
77
|
+
|
78
|
+
private_class_method def self.iterations(shape_count, colors, random)
|
79
|
+
(0...shape_count).map do |i|
|
80
|
+
Iteration.new(
|
81
|
+
index: i,
|
82
|
+
color: colors.delete(colors.sample(random: random)),
|
83
|
+
random_numbers: 3.times.map { random.rand }
|
84
|
+
)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/jazzicon.rb
ADDED
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jazzicon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Heuer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-01-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chunky_png
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.4'
|
27
|
+
description: Jazzicon is a Ruby implementation of the javascript Jazzicon identicon
|
28
|
+
generator (https://github.com/danfinlay/jazzicon).
|
29
|
+
email:
|
30
|
+
- sheuer@aruxsoftware.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files:
|
34
|
+
- README.md
|
35
|
+
- LICENSE.txt
|
36
|
+
files:
|
37
|
+
- LICENSE.txt
|
38
|
+
- README.md
|
39
|
+
- lib/jazzicon.rb
|
40
|
+
- lib/jazzicon/helpers/color_helpers.rb
|
41
|
+
- lib/jazzicon/helpers/geometry_helpers.rb
|
42
|
+
- lib/jazzicon/helpers/image_helpers.rb
|
43
|
+
- lib/jazzicon/icon.rb
|
44
|
+
- lib/jazzicon/version.rb
|
45
|
+
homepage: https://github.com/Arux-Software/jazzicon_ruby
|
46
|
+
licenses:
|
47
|
+
- MIT
|
48
|
+
metadata:
|
49
|
+
homepage_uri: https://github.com/Arux-Software/jazzicon_ruby
|
50
|
+
source_code_uri: https://github.com/Arux-Software/jazzicon_ruby
|
51
|
+
rubygems_mfa_required: 'true'
|
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: 2.3.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.2.3
|
68
|
+
signing_key:
|
69
|
+
specification_version: 4
|
70
|
+
summary: A Ruby implementation of the javascript Jazzicon identicon generator.
|
71
|
+
test_files: []
|