├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── index.js ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | *.log 4 | .DS_Store 5 | bundle.js 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | *.log 4 | .DS_Store 5 | bundle.js 6 | test 7 | test.js 8 | demo/ -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2014 Matt DesLauriers 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # get-rgba-palette 2 | 3 | [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) 4 | 5 | Gets a palette of prominent colors from a flat array of RGBA pixels. 6 | 7 | ![img](http://i.imgur.com/arnLlX0.png) 8 | 9 | Full example: 10 | 11 | ```js 12 | var palette = require('get-rgba-palette') 13 | var pixels = require('get-image-pixels') 14 | var load = require('img') 15 | var baboon = require('baboon-image-uri') 16 | 17 | load(baboon, function(err, img) { 18 | //get flat RGBA pixels array 19 | var px = pixels(img) 20 | 21 | //get 5 prominent colors from our image 22 | var colors = palette(px, 5) 23 | }) 24 | ``` 25 | 26 | [RequireBin demo](http://requirebin.com/?gist=1f49e56f22fa9caa94d7) 27 | 28 | Returns RGB colors in the form of: 29 | 30 | ```[ [255, 0, 0], [128, 23, 52], [124, 0, 62], etc.. ]``` 31 | 32 | ## Usage 33 | 34 | [![NPM](https://nodei.co/npm/get-rgba-palette.png)](https://nodei.co/npm/get-rgba-palette/) 35 | 36 | #### `palette(pixels[, count, quality, filter])` 37 | 38 | Gets an array of RGB colors from an image (`pixels` is a flat RGBA array). Defaults to a `count` of 5 colors and a `quality` setting of 10. 39 | 40 | `quality` determines the step between each pixel when computing the quantization; higher number means fuzzier quality. Must be > 0. 41 | 42 | `filter` allows you to threshold the RGBA values given to the quantize function. It passes `(pixels, index)` -- the flat array and index to the RGBA component. Return true to accept the color, or false to reject. 43 | 44 | If not specified, the filter function defaults to: 45 | 46 | ```js 47 | function filter (pixels, index) { 48 | // offset 3 --> alpha 49 | return pixels[index + 3] >= 127 50 | } 51 | ``` 52 | 53 | #### `palette.bins(pixels[, count, quality, filter])` 54 | 55 | Instead of returning RGB colors, this returns the "bins" for each computed color. This can give you a very rough overview of the distribution of colours in the image. This is fairly arbitrary as the bin `size` does not always represent the exact number of pixels for that color in the image. 56 | 57 | Returns an array of objects: 58 | 59 | ```js 60 | { 61 | color: [255, 0, 0], 62 | size: 12414, 63 | amount: 0.65 64 | } 65 | ``` 66 | 67 | Where `amount` is a percentage for that bin, normalized from the sum of the sizes in the returned bins. 68 | 69 | ## License 70 | 71 | MIT, see [LICENSE.md](http://github.com/mattdesl/get-rgba-palette/blob/master/LICENSE.md) for details. 72 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var quantize = require('quantize') 2 | 3 | module.exports = function(pixels, count, quality, filter) { 4 | return compute(pixels, count, quality, filter).map(function(vb) { 5 | return vb.color 6 | }) 7 | } 8 | 9 | module.exports.bins = function(pixels, count, quality, filter) { 10 | var vboxes = compute(pixels, count, quality, filter) 11 | 12 | vboxes = vboxes.map(function(vb) { 13 | return { 14 | color: vb.color, 15 | size: vb.vbox.count()*vb.vbox.volume(), 16 | amount: 0 17 | } 18 | }) 19 | 20 | //total bin size 21 | var sum = vboxes.reduce(function(prev, vb) { 22 | return prev + vb.size 23 | }, 0) 24 | 25 | //normalize amount 26 | vboxes.forEach(function(vb) { 27 | vb.amount = vb.size/sum 28 | }) 29 | return vboxes 30 | } 31 | 32 | function defaultFilter (pixels, index) { 33 | return pixels[index + 3] >= 127 34 | } 35 | 36 | function compute(pixels, count, quality, filter) { 37 | count = typeof count === 'number' ? (count|0) : 5 38 | quality = typeof quality === 'number' ? (quality|0) : 10 39 | filter = typeof filter === 'function' ? filter : defaultFilter 40 | if (quality <= 0) 41 | throw new Error('quality must be > 0') 42 | 43 | // Store the RGB values in an array format suitable for quantize function 44 | var pixelArray = [], 45 | step = 4*quality 46 | 47 | for (var i=0, len=pixels.length; i color works same as default export') 49 | 50 | t.throws(palette.bind(null, gradient, 2, 0), '0 quality should throw error') 51 | t.end() 52 | }) 53 | 54 | test("gets bins from an empty array without crashing", function(t) { 55 | //a red image 56 | var red = array(100) 57 | .map(function() { return RED }) 58 | .reduce(concat) 59 | 60 | t.deepEqual(palette.bins(red, 1, 1, alwaysFalseFilter), [], 'should return empty array') 61 | t.end() 62 | }) 63 | 64 | function sum(prev, a) { 65 | return prev + a.amount 66 | } 67 | 68 | function alwaysFalseFilter(pixels, index) { 69 | return false; 70 | } 71 | --------------------------------------------------------------------------------