Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/tooolbox/node-potrace

JavaScript port of Potrace, for NodeJS
https://github.com/tooolbox/node-potrace

Last synced: about 2 months ago
JSON representation

JavaScript port of Potrace, for NodeJS

Awesome Lists containing this project

README

        

# node-potrace
A NodeJS-compatible fork of [Potrace in JavaScript][potrace-by-kilobtye] with some additions, which is in turn a port of [the original Potrace][potrace] — a tool for tracing bitmaps.

![Node.js CI](https://github.com/tooolbox/node-potrace/workflows/Node.js%20CI/badge.svg)

## Example and demo

| **Original image** | **Potrace output** | **Posterized output** |
|---------------------------|------------------------------|-----------------------------------------|
| ![](test/sources/yao.jpg) | ![](https://cdn.rawgit.com/tooolbox/node-potrace/9ee822d/test/example-output.svg) | ![](https://cdn.rawgit.com/tooolbox/node-potrace/9ee822d/test/example-output-posterized.svg) |

(Example image inherited from [online demo of the browser version][potrace-js-demo])

## Usage

Install

```sh
npm install potrace
```

Basic usage

```js
var potrace = require('potrace'),
fs = require('fs');

potrace.trace('./path/to/image.png', function(err, svg) {
if (err) throw err;
fs.writeFileSync('./output.svg', svg);
});
```

You can also provide a configuration object as a second argument.

```js
var params = {
background: '#49ffd2',
color: 'blue',
threshold: 120
};

potrace.trace('./path/to/image.png', params, function(err, svg) {
/*...*/
});
```

If you want to run Potrace algorithm multiple times on the same image with different threshold setting and merge results together in a single file - `posterize` method does exactly that.

```js
potrace.posterize('./path/to/image.png', { threshold: 180, steps: 4 }, function(err, svg) {
/*...*/
});

// or if you know exactly where you want to break it on different levels

potrace.posterize('./path/to/image.png', { steps: [40, 85, 135, 180] }, function(err, svg) {
/*...*/
});
```

### Advanced usage and configuration

Both `trace` and `posterize` methods return instances of `Potrace` and `Posterizer` classes respectively to a callback function as third argument.

You can also instantiate these classes directly:

```js
var potrace = require('potrace');

// Tracing

var trace = new potrace.Potrace();

// You can also pass configuration object to the constructor
trace.setParameters({
threshold: 128,
color: '#880000'
});

trace.loadImage('path/to/image.png', function(err) {
if (err) throw err;

trace.getSVG(); // returns SVG document contents
trace.getPathTag(); // will return just tag
trace.getSymbol('traced-image'); // will return tag with given ID
});

// Posterization

var posterizer = new potrace.Posterize();

posterizer.loadImage('path/to/image.png', function(err) {
if (err) throw err;

posterizer.setParameter({
color: '#ccc',
background: '#222',
steps: 3,
threshold: 200,
fillStrategy: potrace.Posterize.FILL_MEAN
});

posterizer.getSVG();
// or
posterizer.getSymbol('posterized-image');
});
```

Callback function provided to `loadImage` methods will be executed in context of the `Potrace`/`Posterizer` instance, so if it doesn't go against your code style - you can just do

```js
new potrace.Potrace()
.loadImage('path/to/image.bmp', function() {
if (err) throw err;
this.getSymbol('foo');
});
```

[Jimp module][jimp] is used on the back end, so first argument accepted by `loadImage` method could be anything Jimp can read: a `Buffer`, local path or a url string. Supported formats are: PNG, JPEG or BMP. It also could be a Jimp instance (provided bitmap is not modified)

### Parameters

`Potrace` class expects following parameters:

- **turnPolicy** - how to resolve ambiguities in path decomposition. Possible values are exported as constants: `TURNPOLICY_BLACK`, `TURNPOLICY_WHITE`, `TURNPOLICY_LEFT`, `TURNPOLICY_RIGHT`, `TURNPOLICY_MINORITY`, `TURNPOLICY_MAJORITY`. Refer to [this document][potrace-algorithm] for more information (page 4)
(default: `TURNPOLICY_MINORITY`)
- **turdSize** - suppress speckles of up to this size
(default: 2)
- **alphaMax** - corner threshold parameter
(default: 1)
- **optCurve** - curve optimization
(default: true)
- **optTolerance** - curve optimization tolerance
(default: 0.2)
- **threshold** - threshold below which color is considered black.
Should be a number in range 0..255 or `THRESHOLD_AUTO` in which case threshold will be selected automatically using [Algorithm For Multilevel Thresholding][multilevel-thresholding]
(default: `THRESHOLD_AUTO`)
- **blackOnWhite** - specifies colors by which side from threshold should be turned into vector shape
(default: `true`)
- **color** - Fill color. Will be ignored when exporting as \. (default: `COLOR_AUTO`, which means black or white, depending on `blackOnWhite` property)
- **background** - Background color. Will be ignored when exporting as \. By default is not present (`COLOR_TRANSPARENT`)

---------------

`Posterizer` class has same methods as `Potrace`, in exception of `.getPathTag()`.
Configuration object is extended with following properties:

- **fillStrategy** - determines how fill color for each layer should be selected. Possible values are exported as constants:
- `FILL_DOMINANT` - most frequent color in range (used by default),
- `FILL_MEAN` - arithmetic mean (average),
- `FILL_MEDIAN` - median color,
- `FILL_SPREAD` - ignores color information of the image and just spreads colors equally in range 0..\ (or \..255 if `blackOnWhite` is set to `false`),
- **rangeDistribution** - how color stops for each layer should be selected. Ignored if `steps` is an array. Possible values are:
- `RANGES_AUTO` - Performs automatic thresholding (using [Algorithm For Multilevel Thresholding][multilevel-thresholding]). Preferable method for already posterized sources, but takes long time to calculate 5 or more thresholds (exponential time complexity)
*(used by default)*
- `RANGES_EQUAL` - Ignores color information of the image and breaks available color space into equal chunks
- **steps** - Specifies desired number of layers in resulting image. If a number provided - thresholds for each layer will be automatically calculated according to `rangeDistribution` parameter. If an array provided it expected to be an array with precomputed thresholds for each layer (in range 0..255)
(default: `STEPS_AUTO` which will result in `3` or `4`, depending on `threshold` value)
- **threshold** - Breaks image into foreground and background (and only foreground being broken into desired number of layers). Basically when provided it becomes a threshold for last (least opaque) layer and then `steps - 1` intermediate thresholds calculated. If **steps** is an array of thresholds and every value from the array is lower (or larger if **blackOnWhite** parameter set to `false`) than threshold - threshold will be added to the array, otherwise just ignored.
(default: `Potrace.THRESHOLD_AUTO`)
- *all other parameters that Potrace class accepts*

**Notes:**

- When number of `steps` is greater than 10 - an extra layer could be added to ensure presence of darkest/brightest colors if needed to ensure presence of probably-important-at-this-point details like shadows or line art.
- With big number of layers produced image will be looking brighter overall than original due to math error at the rendering phase because of how layers are composited.
- With default configuration `steps`, `threshold` and `rangeDistribution` settings all set to auto, resulting in a 4 thresholds/color stops being calculated with Multilevel Thresholding algorithm mentioned above. Calculation of 4 thresholds takes 3-5 seconds on average laptop. You may want to explicitly limit number of `steps` to 3 to moderately improve processing speed.

## Thanks to

- Peter Selinger for [original Potrace tool and algorithm][potrace]
- @kilobtye for original [javascript port][potrace-by-kilobtye]

## License

The GNU General Public License version 2 (GPLv2). Please see [License File](LICENSE) for more information.

[potrace]: http://potrace.sourceforge.net/
[potrace-algorithm]: http://potrace.sourceforge.net/potrace.pdf
[multilevel-thresholding]: http://www.iis.sinica.edu.tw/page/jise/2001/200109_01.pdf
[potrace-by-kilobtye]: https://github.com/kilobtye/potrace
[potrace-js-demo]: http://kilobtye.github.io/potrace/
[jimp]: https://github.com/oliver-moran/jimp