@codegasms/fluxicons
v2.0.0
Published
Generate Identicons
Downloads
6
Maintainers
Readme
Fluxicon (Identicon For FLUX)
Usage
import fluxicons from '@codegasms/fluxicons';
const message = 'Hello World';
const size = 512;
// Method 1
const fluxiconData: Buffer = fluxicons.fluxicon(message, size, 'data');
const fluxiconBuffer: Buffer = fluxicons.fluxicon(fluxiconData);
fs.writeFileSync('fluxicons_hello_world.png', fluxiconBuffer);
// Method 2
const fluxiconBuffer: Buffer = fluxicons.fluxicon(message, size, 'image');
fs.writeFileSync('fluxicons_hello_world.png', fluxiconBuffer);
What Is A Fluxicon?
Fluxicons
, our Identicons, are simple “pixel” sprites that are generated using a hash (using @codegasms/sha256
) of (anything).
The algorithm walks through the hash and generates a tom loads of properties such as:
- The shape defining the Fluxicon grid
- Color of the Fluxicon
- Type of the shapes
- Rotation of the shapes
- Inversion of the shapes
These shapes are then stitched together to create a buffer
which defines the Fluxicon. Due to a variety in the properties, each generated Fluxicon is ensured to be unique
.
Generating A Fluxicon
Defining Shapes In The Grid
The Grid
is indexed as follows:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
We need to create some shapes using combination of indices.
| Shape# | Indices | Shape Description |
|--------|----------------------------|------------------------------------------------------|
| Shape 0 | (0, 4, 24, 20) | Square Shape (4x4), Covers The Entire Grid
|
| Shape 1 | (0, 4, 20) | Triangle Shape (3x3), Covers The Top-Left Corner
|
| Shape 2 | (2, 24, 20) | Equilateral Triangle Shape (3x3), Covers The Middle
|
| Shape 3 | (0, 2, 20, 22) | Z-Shape, Covers The Left Side
|
| Shape 4 | (2, 14, 22, 10) | Diamond Shape, Covers The Middle
|
| Shape 5 | (0, 14, 24, 22) | Kite Shape, Covers The Middle With Buldge On Right
|
| Shape 6 | (2, 24, 22, 13, 11, 22, 20)| Serpienski Triangle Shape, Covers The Middle
|
| Shape 7 | (0, 14, 22) | Triangle Shape, Covers The Middle
|
| Shape 8 | (6, 8, 18, 16) | Square Shape (2x2), Covers The Middle
|
| Shape 9 | (4, 20, 10, 12, 2) | 2 x Triangle Shape, Covers The Middle With Buldge On Left
|
| Shape 10 | (0, 2, 12, 10) | Square Shape (2x2), Covers The Top-Left Corner
|
| Shape 11 | (10, 14, 22) | Triangle Shape, Covers The Bottom With Buldge Towards Bottom
|
| Shape 12 | (20, 12, 24) | Triangle Shape, Covers The Bottom With Buldge Towards Top
|
| Shape 13 | (10, 2, 12) | Triangle Shape, Covers The Top-Left Corner With Buldge Towards Right
|
| Shape 14 | (0, 2, 10) | Triangle Shape, Covers The Top-Left Corner With Buldge
|
var shape0 = new Array(0, 4, 24, 20);
...
var shape14 = new Array(0, 2, 10);
var middleShapeType = new Array(0, 4, 8, 15) // shape0, shape4, shape8, Special shape (Inverse Middle Shape)
var shapeType = new Array(shape0, shape1, shape2, shape3, shape4, shape5, shape6, shape7, shape8, shape9, shape10, shape11, shape12, shape13, shape14, shape0);
Defining Properties For The Grid
The entire Grid
is divided into 3 parts:
- Center Shape (Middle Shape)
- Corner Shape (Top-Left, Top-Right, Bottom-Left, Bottom-Right)
- Side Shape (Top, Bottom, Left, Right)
We have to define the following set of properties for each of the Shapes:
- Type (Taken from the
shapeType
array) :0-14
- Invert (Boolean, whether to invert the shape or not) :
True/False
- Turn (Number, how many times to turn/rotate the shape) :
0-3 represents 0, 90, 180, 270 degrees
// genCode is SHA256 Hashed Value i.e.
// var genCode = (hash.charCodeAt(0) << 24) | (hash.charCodeAt(1) << 16) | (hash.charCodeAt(2) << 8) | hash.charCodeAt(3);
genCode,
size,
middleType: middleShapeType[genCode & 3],
middleInvert: ((genCode >> 2) & 1) != 0,
cornerType: (genCode >> 3) & 15,
cornerInvert: ((genCode >> 7) & 1) != 0,
cornerTurn: (genCode >> 8) & 3,
sideType: (genCode >> 10) & 15,
sideInvert: ((genCode >> 14) & 1) != 0,
sideTurn: (genCode >> 15) & 3,
red: (genCode >> 27) & 31,
green: (genCode >> 21) & 31,
blue: (genCode >> 16) & 31,
Generating The Fluxicon Shapes
To generate the shapes, we need to define the path and color of the shape in a canvas. In order to do this, we do the following steps:
- Define the properties of the shape w.r.t. the canvas
shapeType
is smashed within the defined array sizeturn
is smashed within the range0-3
representing0, 90, 180, 270
degreesinvert
is set toTrue
if the shape is15
(Special Case)vertices
of the shapes are extracted from theshapeType
array intopoints
variableshapeScale
&shapeOffset
is calculated based on the size of the shape
- Fill the
Background
of the canvas with foreground or background color depending on theinvert
property - Build the path of the shape
- Translate the canvas to the center of the shape
- Rotate the canvas based on the
turn
property - Begin the path
- Move the canvas to the first vertex of the shape
- Loop through the vertices of the shape and draw the path
- Close the path
- Fill the shape with the foreground or background color depending on the
invert
property - Restore the context of the canvas
function generateShape(context2d, xCoordinate, yCoordinate, size, shape, invert, turn, foregroundColor, backGroundColor) {
shape = shape % shapeType.length; // To make sure the shape is within the range of the shapeType array
turn % 4; // To make sure the turn is 0, 90, 18 or 270 degrees
invert = shape == 15 ? !invert : invert; // Invert the shape if the shape is 15 (SPECIAL CASE)
var points = shapeType[shape];
var shapeScale = size / 4;
var shapeOffset = size / 2;
context2d.save();
// Fill The Background
context2d.fillStyle = invert ? foregroundColor : backGroundColor;
context2d.fillRect(xCoordinate, yCoordinate, size, size);
// Build The Shape Path
context2d.translate(xCoordinate + shapeOffset, yCoordinate + shapeOffset);
context2d.rotate(turn * (Math.PI / 2));
context2d.beginPath();
context2d.moveTo((points[0] % 5 * shapeScale - shapeOffset), (Math.floor(points[0] / 5) * shapeScale - shapeOffset));
for (var i = 1; i < points.length; i++) {
context2d.lineTo((points[i] % 5 * shapeScale - shapeOffset), (Math.floor(points[i] / 5) * shapeScale - shapeOffset));
}
context2d.closePath();
// Fill The Shape
context2d.fillStyle = invert ? backGroundColor : foregroundColor;
context2d.fill();
// Restore The Context
context2d.restore();
}
Generating The Fluxicon
Now that we have the Data
and the Shapes
defined, we can generate the Fluxicon iteratively by drawing each generated shape on the canvas. The iteration is as follows:
- Draw The Middle Shape
- Draw The Corner Shapes
- Top Left
- Top Right
- Bottom Right
- Bottom Left
- Draw The Side Shapes
- Top
- Right
- Bottom
- Left
The colors are generated based on the RGB
values of the Data
and the Shapes
are generated based on the properties of the Data
.
function generateFluxicon(data) {
var canvas = Canvas.createCanvas(data.size, data.size);
var context2d = canvas.getContext('2d');
var shapeDivision = data.size / 3;
var middleType = data.middleType;
...
var blue = data.blue;
var foreGroundColor = 'rgb(' + (red << 3) + ',' + (green << 3) + ',' + (blue << 3) + ')';
var backGroundColor = 'rgb(' + (255 - red) + ',' + (255 - green) + ',' + (255 - blue) + ')';
// Draw The Middle Shape
generateShape(context2d, shapeDivision, shapeDivision, shapeDivision, middleType, middleInvert, 0, foreGroundColor, backGroundColor);
// Draw The Corner Shapes (Top Left, Top Right, Bottom Right, Bottom Left)
generateShape(context2d, 0, 0, shapeDivision, cornerType, cornerInvert, cornerTurn++, foreGroundColor, backGroundColor);
generateShape(context2d, shapeDivision * 2, 0, shapeDivision, cornerType, cornerInvert, cornerTurn++, foreGroundColor, backGroundColor);
generateShape(context2d, shapeDivision * 2, shapeDivision * 2, shapeDivision, cornerType, cornerInvert, cornerTurn++, foreGroundColor, backGroundColor);
generateShape(context2d, 0, shapeDivision * 2, shapeDivision, cornerType, cornerInvert, cornerTurn++, foreGroundColor, backGroundColor);
// Draw The Side Shapes (Top, Right, Bottom, Left)
generateShape(context2d, shapeDivision, 0, shapeDivision, sideType, sideInvert, sideTurn++, foreGroundColor, backGroundColor);
generateShape(context2d, shapeDivision * 2, shapeDivision, shapeDivision, sideType, sideInvert, sideTurn++, foreGroundColor, backGroundColor);
generateShape(context2d, shapeDivision, shapeDivision * 2, shapeDivision, sideType, sideInvert, sideTurn++, foreGroundColor, backGroundColor);
generateShape(context2d, 0, shapeDivision, shapeDivision, sideType, sideInvert, sideTurn++, foreGroundColor, backGroundColor);
return canvas.toBuffer();
}
The generated Fluxicon is returned as a
Buffer
object, so that it can be converted into any desirable file format.