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);
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
.
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);
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,
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();
}
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.