shapesnap
v1.2.1
Published
Transform images to SVG using primitive shapes
Downloads
65
Maintainers
Readme
🃏 Shapesnap 🃏
Transform images to SVG using primitive shapes.
This library renders raster images to SVG images The algorithm repeatedly generates and mutates shapes, keeping only those that closely match the original bitmap.
Effectively it plays the card game "snap" with shapes until it finds a good match.
The code has largely been ported from the last known good fork of cutout which itself is derived from Primitive.
As per original, this has
- No native, non-javascript dependencies (so no node-canvas, as that relies on Cairo)
- No browser specific APIs (even though it can be bundled for the browser without any problems)
- Modular and not tied to a single implementation, so it can fit in any project
New features
- Ported to Typescript and ES6
- Replaced d3 randomNormal with a faster random algorithm (gteat) for shape generation that has a greater central bell curve (anecdotally better fitting in fewer iterations).
- Fixed a race condition causing NaNs in randomNormal only seen after a 5K+ iterations caused by a bug in the original d3 randomNormal implementation.
- Replaced missing "dainty" utility lib npm dependency with a small function to do the same thing (thanks go to swanie21's svg info page svg-shapes for the crash course).
- Provided a direct runner.ts using Jimp to use with your own images. (Original used direct ndarrays or the cutout-cli project which is now unavailable).
- Added open licenced pexels.com example images.
- Cleaned up/modernised the code (an ongoing thing),
Additionally, I'm investigating further performance improvements using webworkers to split the variants work over multiple threads.
Examples with Increasing Detail
| Raster input | Svg result | |:----------------------------------------------|:----------------------------------------------| | | | | | | | | |
Usage
Note that this is only a quickly created script with a hardcoded config for my own testing but felt it would be useful for others to try it out before using the API.
Usage with tsx installed globally
npm install -g tsx
tsx runner.ts images/robot.png ./robot.svg
Usage with transpile and node
npm run build
node ./dist/runner.js images/robot.png ./robot.svg
API
Usage
Auto stepping with [options.steps]
return new ShapeSnap( target, [options] ).autostep().svg
Within a for loop
for (let i = 0; i < steps; i++) {
shapesnap.step(); // number of rendered shapes
}
return shapesnap.svg;
Constructor
new ShapeSnap( target, [options] )
Options
| Param | Type | Default | Description |
|----------------------------|-----------------------------------|---------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| target | NdArray | | The image to render to svg |
| [options] | Object | All of the below | Configuration options |
| [options.alpha] | number | 192 | The opacity of the shapes (0-255) |
| [options.amountOfShapes] | number | 40 | The number of shapes to try per step |
| [options.amountOfAttempts] | number | 2 | The number of times to mutate each candidate shape |
| [options.background] | Array.<number> | Auto calculated blend | Optional background color, expressed as an array of four numbers between 0 - 255 for respectively red, green, blue and transparency |
| [options.maxSize] | number | 24 | The maximum size of any shape in SVG pixels e.g. for radius it is 1x, for width 2x. |
| [options.shapeTypes] | Array.<string> | 'Circle', 'Cubic', 'Ellipse', 'Line', 'Quadratic', 'Rect', 'Square', 'Triangle'
| The types of shapes to use when generating the image, available are: Circle
, Cubic
, RotatedEllipse
, Ellipse
, Line
, Quadratic
, Rect
, RotatedRect
, Square
and Triangle
|
| [options.steps] | number | 2400 | The number of steps to attempt, this is directly relational to the number of final shapes in the image |
shapesnap.image ⇒ NdArray
Get the current image
shapesnap.svg ⇒ string
Get the current svg
shapesnap.shapes ⇒ ShapeColor[]
Get the current internal model of shapes
shapesnap.difference ⇒ number
Get the current difference
shapesnap.step() ⇒ Shapesnap
Add a single new shape
shapesnap.autostep( [callback: (progress:String) => void] ) ⇒ Shapesnap
Adds the option.steps number of steps with each 10% progression passed to the (optional) callback. If no callback is specified it outputs to the console.
Credits
- Primitive
- Primitive.js
- Geometrize
- Ismay for the original implementation.
- Piwodlaiwo for retaining a fork of the original.