# node-vibrant
**Repository Path**: mirrors_TooTallNate/node-vibrant
## Basic Information
- **Project Name**: node-vibrant
- **Description**: Extract prominent colors from an image
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-18
- **Last Updated**: 2026-07-04
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# node-vibrant
[](https://travis-ci.org/akfish/node-vibrant)
Extract prominent colors from an image.
* [v3.0 Dev Branch](https://github.com/akfish/node-vibrant/tree/develop)
## Install
Install 2.x.x version:
```bash
$ npm install node-vibrant
```
Install 3.0.0 pre-release version:
```bash
$ npm install node-vibrant@3.0.0-alpha.2
```
## Update Notes
- Some major refactor/rewriting comes with `node-vibrant@2.0.0`:
- Closely matches latest Android M `Palette` API with new features such as `Builder` and `Filter`
- Optimization: **~4x speed-up** over original implementation
- Implement image downsampling for both node.js and browsers
- More stream-lined design
- Better test coverage for both node.js and browser environment
- `node-vibrant@1.x` is a node.js port of [Vibrant.js](https://github.com/jariz/vibrant.js), which is a javascript port of the [awesome Palette class](https://developer.android.com/reference/android/support/v7/graphics/Palette.html) in the Android support library.
## Features
- Identical (asynchronous) API for both node.js and browser environment
- Support browserify
- Consistent results (*See [Result Consistency](#result-consistency))
## Usage
### node.js / browserify
CoffeeScript/ES5:
```coffee
# Use in node.js or bundle with browserify
Vibrant = require('node-vibrant')
# Using builder
Vibrant.from('path/to/image').getPalette (err, palette) ->
console.log palette
# Using constructor
v = new Vibrant('path/to/image', opts)
v.getPalette (err, palette) ->
console.log(swatches)
```
ES6:
```js
import * as Vibrant from 'node-vibrant'
// Using builder
Vibrant.from('path/to/image').getPalette((err, palette) => console.log(palette))
// Using constructor
let v = new Vibrant('path/to/image', opts)
v.getPalette((err, palette) => console.log(palette))
```
### Browser
```html
```
## Contribution Guidelines
1. Make changes
2. Write test specs if necessary
3. Pass tests
4. Commit **source files only** (without compiled files)
## References
### `Vibrant`
Main class of `node-vibrant`.
#### `Vibrant.from(image)`
Make a `Builder` for an image. Returns a `Builder` instance.
Name | Type | Description
------- | ---------------------------------- | ---------------------------------------
`image` | `string`, `HTMLImageElement`(browser only), or `Buffer`(node.js only) | Path to image file (support HTTP/HTTPs)
#### `constructor(image, opts)`
Name | Type | Description
------- | ---------------------------------- | ---------------------------------------
`image` | `string` or `Buffer`(node.js only) | Path to image file (support HTTP/HTTPs)
`opts` | object | Options (optional)
##### `opts`
Field | Default | Description
-------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------
`colorCount` | 64 | amount of colors in initial palette from which the swatches will be generated
`quality` | 5 | Scale down factor used in downsampling stage. `1` means no downsampling. If `maxDimension` is set, this value will not be used.
`generator` | `Vibrant.Generator.Default` | An `Generator` instance
`maxDimension` | `undefined` | The max size of the image's longer side used in downsampling stage. This field will override `quality`.
`filters` | `[]` | An array of filters
`Image` | `Image.Node` or `Image.Browser` | An `Image` implementation class
`Quantizer` | `Vibrant.Quantizer.MMCQ` | A `Quantizer` implementation class
#### `getPalette(cb)`
Name | Type | Description
---- | ---------- | -----------------
`cb` | `function` | callback function
##### `cb(err, palette)`
Name | Type | Description
--------- | --------------- | ------------------
`err` | `object` | Error (if thrown)
`palette` | `Array` | Resulting swatches
#### `getSwatches(cb)`
Alias of `getPalette`.
### `Vibrant.Builder`
Helper class for change configurations and create a `Vibrant` instance. Methods of a `Builder` instance can be chained like:
```coffee
Vibrant.from(src)
.quality(1)
.clearFilters()
# ...
getPalette (err, palette) ->
```
#### `constructor(src, opts)`
Arguments are the same as `Vibrant.constructor`.
#### `quality(q)`
Sets `opts.quality` to `q`. Returns this `Builder` instance.
#### `maxColorCount(n)`
Sets `opts.colorCount` to `n`. Returns this `Builder` instance.
#### `maxDimension(d)`
Sets `opts.maxDimension` to `d`. Returns this `Builder` instance.
#### `addFilter(f)`
Adds a filter function. Returns this `Builder` instance.
#### `removeFilter(f)`
Removes a filter function. Returns this `Builder` instance.
#### `clearFilters()`
Clear all filters. Returns this `Builder` instance.
#### `useImage(image)`
Specifies which `Image` implementation class to use. Returns this `Builder` instance.
#### `useQuantizer(quantizer)`
Specifies which `Quantizer` implementation class to use. Returns this `Builder` instance.
#### `useGenerator(generator)`
Sets `opts.generator` to `generator`. Returns this `Builder` instance.
#### `build()`
Builds and returns a `Vibrant` instance as configured.
#### `getPalette(cb)`
Builds a `Vibrant` instance as configured and calls its `getPalette` method.
#### `getSwatches(cb)`
Alias of `getPalette`.
### `Vibrant.Swatch`
Represents a color swatch generated from an image's palette.
#### `constructor(rgb, population)`
Internal use.
Name | Type | Description
------------ | --------------- | -----------------------------------
`rgb` | `Array` | `[r, g, b]`
`population` | `Number` | Population of the color in an image
#### `getHsl()`
#### `getPopulation()`
#### `getRgb()`
#### `getHex()`
#### `getTitleTextColor()`
Returns an appropriate color to use for any 'body' text which is displayed over this `Swatch`'s color.
#### `getBodyTextColor()`
Returns an appropriate color to use for any 'title' text which is displayed over this `Swatch`'s color.
### `Vibrant.Util`
Utility methods. Internal usage.
#### `clone(o)`
Make a deep copy of `o`.
#### `defaults()`
Same as underscore.js's `defaults`. Re-implemented to reduce browserify package size.
#### `hexToRgb(hex)`
#### `rgbToHex(r, g, b)`
#### `hslToRgb(h, s, l)`
#### `rgbToHsl(r, g, b)`
#### `xyzToRgb(x, y, z)`
#### `rgbToXyz(r, g, b)`
#### `xyzToCIELab(x, y, z)`
#### `rgbToCIELab(l, a, b)`
#### `deltaE94(lab1, lab2)`
Computes CIE delta E 1994 diff between `lab1` and `lab2`. The 2 colors are in CIE-Lab color space. Used in tests to compare 2 colors' perceptual similarity.
#### `rgbDiff(rgb1, rgb2)`
Compute CIE delta E 1994 diff between `rgb1` and `rgb2`.
#### `hexDiff(hex1, hex2)`
Compute CIE delta E 1994 diff between `hex1` and `hex2`.
#### `getColorDiffStatus(d)`
Gets a string to describe the meaning of the color diff. Used in tests.
Delta E | Perception | Returns
-------- | -------------------------------------- | -----------
<= 1.0 | Not perceptible by human eyes. | `"Perfect"`
1 - 2 | Perceptible through close observation. | `"Close"`
2 - 10 | Perceptible at a glance. | `"Good"`
11 - 49 | Colors are more similar than opposite | `"Similar"`
50 - 100 | Colors are exact opposite | `Wrong`
### `Vibrant.Filter`
A collection of built-in filters.
#### `Filter(r, g, b, a): function`
A `Filter` provides a mechanism for exercising fine-grained control over which colors are valid within a resulting. It takes color's rgba value and returns `true` if the color is allowed.
#### `Filter.Default`
Keeps the original `vibrant.js`'s filtering behavior as reference.
### `Vibrant.Quantizer`
Base class of a `Quantizer`.
#### `Quantizer.MMCQ`
Default quantizer. ~4x faster than baseline quantizer.
### `Vibrant.Generator`
Base class for `Generator`.
#### `Generator.Default`
Default `Generator` implementation.
##### `constructor(opts)`
##### `opts`
Field | Default | Description
------------------------- | ------- | ---------------------------------------------------------------------------------------------------------
`targetDarkLuma` | 0.26 | target luma value for generating the dark swatches, values should be in the range [0 1]
`maxDarkLuma` | 0.45 | maximal luma threshold for generating the dark swatches, values should be in the range [0 1]
`minLightLuma` | 0.55 | minimal luma threshold for generating the light swatches, values should be in the range [0 1]
`targetLightLuma` | 0.74 | target luma value for generating the light swatches, values should be in the range [0 1]
`minNormalLuma` | 0.3 | minimal luma threshold for generating the Vibrant and Muted swatches, values should be in the range [0 1]
`targetNormalLuma` | 0.5 | target luma value for generating the Vibrant and Muted swatches, values should be in the range [0 1]
`maxNormalLuma` | 0.7 | maximal luma threshold for generating the Vibrant and Muted swatches, values should be in the range [0 1]
`targetMutedSaturation` | 0.3 | target saturation for generating the Muted swatch, values should be in the range [0 1]
`maxMutesSaturation` | 0.4 | maximal saturation threshold for generating the Muted swatches, values should be in the range [0 1]
`targetVibrantSaturation` | 1.0 | target saturation value for generating the Vibrant swatches, values should be in the range [0 1]
`minVibrantSaturation` | 0.35 | minimal saturation threshold for generating the Vibrant swatches, values should be in the range [0 1]
`weightSaturation` | 3 | saturation weight coefficient for determining each swatch, actual impact depends on other weights
`weightLuma` | 6 | luma weight coefficient for determining each swatch, actual impact depends on other weights
`weightPopulation` | 1 | population weight coefficient for determining each swatch, actual impact depends on other weights
## Gulp Tasks
Task | Description
-------------- | --------------------------------------
`detaul` | [`coffee`, `browser`]
`coffee` | Compile node.js target
`browser` | Compile broser target (browserify)
`benchmark` | Runs benchmarks
`test` | Runs node.js test specs
`browser-test` | Runs browser test specs (with `karma`)
## Notes
### Intentional Deviation From `vibrant.js`
- `node-vibrant` takes image path, not the image object as parameter for the obvious reason that node.js environment has no access to HTML DOM object.
- `node-vibrant` provides asynchronous API since most node.js image processing library is asynchronous. And the original `vibrant.js` workflow is asynchronous any way (though you will have to handle the image loading yourself, while `node-vibrant` does it for you).
- `node-vibrant` uses one single `opts` object to hold all options for future expansions. And it feels more node.js-like.
- `node-vibrant` uses method call to initiate image processing instead of constructor so that developers can use it with `Promise`.
### Result Consistency
The results is consistent within each user's browser instance regardelss of visible region or display size of the image, unlike the original `vibrant.js` implementation.
However, due to the very nature of HTML5 canvas element, image rendering is platform/machine-dependent. Thus the resulting swatches in browser environment varies and may not be the same as in node.js nor in another machine. See [Canvas Fingerprinting](https://en.wikipedia.org/wiki/Canvas_fingerprinting).
The test specs use CIE delta E 1994 color difference to measure inconsistencies across platforms. It compares the generated color on node.js, Chrome, Firefox and IE11. At `quality` == 1 (no downsampling) and no filters, the results are rather consistent. Color diffs between browsers are mostly not perceptible by human eyes. Downsampling _will_ cause perceptible inconsistent results across browsers due to differences in canvas implementations.
