Merge pull request #160 from lokesh/dev

chore: Merging dev into master for minor release v2.1
This commit is contained in:
Lokesh Dhakar
2019-07-14 09:30:40 -07:00
committed by GitHub
39 changed files with 3282 additions and 10299 deletions

17
.editorconfig Normal file
View File

@@ -0,0 +1,17 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 4
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

19
.eslintrc.js Normal file
View File

@@ -0,0 +1,19 @@
module.exports = {
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
"one-var": ["warn", { "initialized": "never" }]
}
}

75
.jscsrc
View File

@@ -1,75 +0,0 @@
{
"requireSpaceAfterLineComment": true,
"requireSpaceAfterKeywords": [
"do",
"for",
"if",
"else",
"switch",
"case",
"try",
"catch",
"void",
"while",
"with",
"return",
"typeof"
],
"requireSpaceBeforeBlockStatements": true,
"requireParenthesesAroundIIFE": true,
"requireSpacesInConditionalExpression": true,
"disallowMultipleVarDecl": true,
"requireBlocksOnNewline": true,
"disallowEmptyBlocks": true,
"disallowSpacesInsideParentheses": true,
"disallowSpaceAfterObjectKeys": true,
"requireSpaceBeforeObjectValues": true,
"requireCommaBeforeLineBreak": true,
"requireOperatorBeforeLineBreak": [
"?",
"=",
"+",
"-",
"/",
"*",
"==",
"===",
"!=",
"!==",
">",
">=",
"<",
"<="
],
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
"requireSpaceBeforeBinaryOperators": [
"=",
"+",
"-",
"/",
"*",
"==",
"===",
"!=",
"!=="
],
"requireSpaceAfterBinaryOperators": [
"=",
",",
"+",
"-",
"/",
"*",
"==",
"===",
"!=",
"!=="
],
"disallowMixedSpacesAndTabs" : true,
"disallowTrailingWhitespace": true,
"disallowTrailingComma": true,
"requireLineFeedAtFileEnd": true,
"requireCapitalizedConstructors": true
}

View File

@@ -1,35 +0,0 @@
{
"bitwise":true,
"browser":true,
"camelcase":true,
"curly":true,
"eqeqeq":true,
"forin":true,
"freeze":true,
"indent":2,
"latedef":true,
"maxdepth": 6,
"maxparams": 6,
"maxstatements": 50,
"newcap": true,
"noarg":true,
"noempty":true,
"nonbsp":true,
"nonew":true,
"quotmark":"single",
"trailing":true,
"undef":true,
"unused":"vars",
"immed":true,
"browser": true,
"jquery":true,
"predef": [
"alert",
"confirm",
"console",
"escape",
"define",
"module",
"require"
]
}

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
12.4.0

18
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,18 @@
## Running tests
Run Cypress integration tests in Chrome browser.
- `npm run dev` to start local server.
- `npm run test`
## Adding tests
- Update `cypress/test-pages/index.html` as needed or create a new test page if you need new examples.
- Add new tests in `cypress/integration/apis_spec.js`
## Making a new release
- Update version number in `src/color-thief.js` and `package.json`
- Run `npm run build`
- Push to Github repo
- Create a new Github release along with tag. Naming convention for both ```v2.8.1```

View File

@@ -1,6 +0,0 @@
## How to make a release and deploy
- Update version number in `src/color-thief.js` and `package.json`
- Run `grunt build`
- Push to Github repo
- Create a new Github release along with tag. Naming convention for both ```v2.8.1```

View File

@@ -1,50 +0,0 @@
module.exports = function(grunt) {
grunt.initConfig({
connect: {
server: {
options: {
port: 8000
}
}
},
jshint: {
files: ['src/color-thief.js']
},
jscs: {
src: [
'src/color-thief.js'
],
options: {
config: ".jscsrc"
}
},
uglify: {
options: {
preserveComments: 'some',
sourceMap: false
},
dist: {
files: {
'dist/color-thief.min.js': ['src/color-thief.js']
}
}
},
watch: {
test: {
files: ['src/color-thief.js'],
tasks: ['jshint', 'jscs']
}
}
});
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-jscs');
grunt.registerTask('default', ['connect', 'watch']);
grunt.registerTask('test', ['jshint', 'jscs']);
grunt.registerTask('build', ['uglify']);
};

View File

@@ -8,16 +8,12 @@ A script for grabbing the color palette from an image. Uses Javascript and the c
## How to use ## How to use
### Get the dominant color from an image ### Get the dominant color from an image
```js ```js
var colorThief = new ColorThief(); var colorThief = new ColorThief();
colorThief.getColor(sourceImage); colorThief.getColor(sourceImage);
``` ```
```js
getColor(sourceImage[, quality])
returns [num, num, num]
```
### Build a color palette from an image ### Build a color palette from an image
In this example, we build an 8 color palette. In this example, we build an 8 color palette.
@@ -27,7 +23,10 @@ var colorThief = new ColorThief();
colorThief.getPalette(sourceImage, 8); colorThief.getPalette(sourceImage, 8);
``` ```
```js ### API
getPalette(sourceImage[, colorCount, quality])
returns [ [num, num, num], [num, num, num], ... ]
``` | Method | Return | Description |
| --- | --- | --- |
| `getColor(image [, quality])` | `[Number, Number, Number]` | WIP |
| `getPalette(image [, colorCount, quality]` | `[[Number, Number, Number], ...]` | WIP |

View File

@@ -1,26 +0,0 @@
{
"name": "color-thief",
"homepage": "http://lokeshdhakar.com/projects/color-thief/",
"authors": [
"Lokesh Dhakar"
],
"description": "Grab the dominant color or color palette from an image.",
"main": "src/color-thief.js",
"keywords": [
"color",
"palette",
"sampling",
"image",
"picture",
"photo",
"canvas"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

20
build/build.js Normal file
View File

@@ -0,0 +1,20 @@
const minify = require('@node-minify/core');
const uglify = require('@node-minify/uglify-es');
minify({
compressor: uglify,
input: './src/color-thief.js',
output: './dist/color-thief.min.js',
options: {
output: {
comments: 'some'
}
},
callback: function(err, min) {
if (err) {
console.log('⚠ERROR:' + err);
} else {
console.log('✅ Minification completed');
}
}
});

1
cypress.json Normal file
View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -0,0 +1,73 @@
function rgbCount(text) {
const vals = text.split(',');
for (const val of vals) {
if (val < 0 || val > 255) {
throw 'Invalid RGB color value';
}
}
return vals.length / 3
}
describe('getColor()', function() {
beforeEach(function() {
cy.visit('http://localhost:8080/cypress/test-pages/index.html');
})
it('returns valid color from black image', function() {
cy.get('[data-image="black.png"] .output-color').should(($el) => {
const count = rgbCount($el.text())
expect(count).to.equal(1);
});
})
it('returns valid color from red image', function() {
cy.get('[data-image="red.png"] .output-color').should(($el) => {
const count = rgbCount($el.text())
expect(count).to.equal(1);
});
})
it('returns valid color from rainbow image', function() {
cy.get('[data-image="rainbow-horizontal.png"] .output-color').should(($el) => {
const count = rgbCount($el.text())
expect(count).to.equal(1);
});
})
// ⚠BREAKS
// it('returns valid color from white image', function() {
// cy.get('[data-image="white.png"] .output-color').should(($el) => {
// const count = rgbCount($el.text())
// expect(count).to.equal(1);
// });
// })
// ⚠BREAKS
// it('returns valid color from transparent image', function() {
// cy.get('[data-image="transparent.png"] .output-color').should(($el) => {
// const count = rgbCount($el.text())
// expect(count).to.equal(1);
// });
// })
})
function testPaletteCount(num) {
it(`returns ${num} color when colorCount set to ${num}`, function() {
cy.get(`[data-image="rainbow-horizontal.png"] .palette[data-count="${num}"] .output-palette`).should(($el) => {
const count = rgbCount($el.text())
expect(count).to.equal(num);
});
})
}
describe('getPalette()', function() {
beforeEach(function() {
cy.visit('http://localhost:8080/cypress/test-pages/index.html');
})
// FULL TEST LIST = [1, 2, 3, 5, 7, 10, 20];
// Non-breaking tests
let testCounts = [5, 7];
testCounts.forEach((count) => testPaletteCount(count))
})

17
cypress/plugins/index.js Normal file
View File

@@ -0,0 +1,17 @@
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

View File

@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

20
cypress/support/index.js Normal file
View File

@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,57 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Color Thief</title>
<link rel="stylesheet" href="./screen.css">
</head>
<body>
<div id="example-images"></div>
<script id='image-tpl' type='text/x-mustache'>
{{#.}}
<div class="image-section" data-image="{{.}}">
<h2>{{.}}</h2>
<img class="image" src="./img/{{.}}" />
<div class="output"></div>
</div>
{{/.}}
</script>
<script id="color-tpl" type="text/x-mustache">
<div class="color">
<h3>getColor(img)</h3>
<div class="swatches">
<div class="swatch" style="background-color: rgb({{color.0}}, {{color.1}}, {{color.2}})"></div>
</div>
<code>
<div class="output-color">{{colorStr}}</div>
<div class="time">{{elapsedTime}}ms</div>
</code>
</div>
</script>
<script id="palette-tpl" type="text/x-mustache">
<div class="palette" data-count="{{count}}">
<h3>getPalette(img, {{count}})</h3>
<div class="swatches">
{{#palette}}
<div class="swatch" style="background-color: rgb({{0}}, {{1}}, {{2}})"></div>
{{/palette}}
</div>
<code>
<div class="output-palette">{{paletteStr}}</div>
<div class="time">{{elapsedTime}}ms</div>
</code>
</div>
</script>
<script src="/src/color-thief.js"></script>
<script src="/node_modules/mustache/mustache.js"></script>
<script src="index.js"></script>
</body>
</html>

View File

@@ -0,0 +1,58 @@
var colorThief = new ColorThief();
var images = [
'black.png',
'red.png',
'rainbow-horizontal.png',
'rainbow-vertical.png',
// 'transparent.png',
// 'white.png',
];
// Render example images
var examplesHTML = Mustache.to_html(document.getElementById('image-tpl').innerHTML, images);
document.getElementById('example-images').innerHTML = examplesHTML;
// Once images are loaded, process them
document.querySelectorAll('.image').forEach((image) => {
const section = image.closest('.image-section');
if (this.complete) {
showColorsForImage(image, section);
} else {
image.addEventListener('load', function() {
showColorsForImage(image, section);
});
}
})
// Run Color Thief functions and display results below image.
// We also log execution time of functions for display.
const showColorsForImage = function(image, section) {
// getColor(img)
let start = Date.now();
let result = colorThief.getColor(image);
let elapsedTime = Date.now() - start;
const colorHTML = Mustache.to_html(document.getElementById('color-tpl').innerHTML, {
color: result,
colorStr: result.toString(),
elapsedTime
})
// getPalette(img)
let paletteHTML = '';
let colorCounts = [null, 1, 2, 3, 5, 7, 10, 20];
colorCounts.forEach((count) => {
let start = Date.now();
let result = colorThief.getPalette(image, count);
let elapsedTime = Date.now() - start;
paletteHTML += Mustache.to_html(document.getElementById('palette-tpl').innerHTML, {
count,
palette: result,
paletteStr: result.toString(),
elapsedTime
})
});
const outputEl = section.querySelector('.output');
outputEl.innerHTML += colorHTML + paletteHTML;
};

View File

@@ -0,0 +1,95 @@
:root {
/* Colors */
--color: #000;
--bg-color: #f9f9f9;
--primary-color: #fc4c02;
--secondary-color: #f68727;
--muted-color: #999;
--code-color: var(--primary-color);
--code-bg-color: #fff;
/* Typography */
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
--code-font: Menlo, Consolas, Monaco, Lucida Console, monospace;
--bold: 700;
--x-bold: 900;
--line-height: 1.5em;
--line-height-heading: 1.3em;
/* Breakpoints */
--sm-screen: 640px;
}
/* Base
* *----------------------------------------------- */
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
background: var(--bg-color);
}
/* Typography
* *----------------------------------------------- */
html {
font-size: 16px;
font-family: var(--font);
line-height: var(--line-height);
-webkit-font-smoothing: antialiased;
}
h1,
h2,
h3 {
font-weight: var(--x-bold);
line-height: var(--line-height-heading);
letter-spacing: -0.005em;
}
h2 {
margin: 0 0 0.25em 0;
font-size: 1.5rem;
}
h3 {
margin: 1em 0 0.25em 0;
font-size: 1.06rem;
}
code {
font-family: var(--code-font);
overflow-wrap: break-word;
}
/* -- Layout ------------------------------------------------------------------ */
.image-section {
border-bottom: 1px solid #ccc;
padding: 16px 16px 32px 16px;
margin-bottom: 32px;
}
.swatch {
display: inline-block;
background: #dddddd;
}
.color .swatch {
width: 6rem;
height: 3rem;
}
.palette .swatch {
width: 3rem;
height: 2rem;
}
.time {
color: var(--muted-color);
font-weight: normal;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 137 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

9111
examples/js/jquery.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,224 +0,0 @@
/**! normalize.css v2.1.1 | MIT License | git.io/normalize
// HTML5 display definitions
// Correct `block` display not defined in IE 8/9.
article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary
display: block
// Correct `inline-block` display not defined in IE 8/9.
audio, canvas, video
display: inline-block
audio:not([controls])
// Prevent modern browsers from displaying `audio` without controls.
display: none
// Remove excess height in iOS 5 devices.
height: 0
// Address styling not present in IE 8/9.
[hidden]
display: none
// Base
html
// Prevent system color scheme's background color being used in Firefox, IE, and Opera.
background: #fff
// Prevent system color scheme's text color being used in Firefox, IE, and Opera.
color: #000
// Set default font family to sans-serif.
font-family: sans-serif
// Prevent iOS text size adjust after orientation change, without disabling user zoom.
-ms-text-size-adjust: 100%
-webkit-text-size-adjust: 100%
// Remove default margin.
body
margin: 0
// Links
a
// Address `outline` inconsistency between Chrome and other browsers.
&:focus
outline: thin dotted
// Improve readability when focused and also mouse hovered in all browsers.
&:active, &:hover
outline: 0
// Typography
// Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome.
h1
font-size: 2em
margin: 0.67em 0
// Address styling not present in IE 8/9, Safari 5, and Chrome.
abbr[title]
border-bottom: 1px dotted
// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
b, strong
font-weight: bold
// Address styling not present in Safari 5 and Chrome.
dfn
font-style: italic
// Address differences between Firefox and other browsers.
hr
-moz-box-sizing: content-box
box-sizing: content-box
height: 0
// Address styling not present in IE 8/9.
mark
background: #ff0
color: #000
// Correct font family set oddly in Safari 5 and Chrome.
code, kbd, pre, samp
font-family: monospace, serif
font-size: 1em
// Improve readability of pre-formatted text in all browsers.
pre
white-space: pre-wrap
// Set consistent quote types.
q
quotes: '\201C' '\201D' '\2018' '\2019'
// Address inconsistent and variable font size in all browsers.
small
font-size: 80%
// Prevent `sub` and `sup` affecting `line-height` in all browsers.
sub, sup
font-size: 75%
line-height: 0
position: relative
vertical-align: baseline
sup
top: -0.5em
sub
bottom: -0.25em
// Embedded content
// Remove border when inside `a` element in IE 8/9.
img
border: 0
// Correct overflow displayed oddly in IE 9.
svg:not(:root)
overflow: hidden
// Figures
// Address margin not present in IE 8/9 and Safari 5.
figure
margin: 0
// Forms
// Define consistent border, margin, and padding.
fieldset
border: 1px solid #c0c0c0
margin: 0 2px
padding: 0.35em 0.625em 0.75em
legend
// Correct `color` not being inherited in IE 8/9.
border: 0
// Remove padding so people aren't caught out if they zero out fieldsets.
padding: 0
button, input, select, textarea
// Correct font family not being inherited in all browsers.
font-family: inherit
// Correct font size not being inherited in all browsers.
font-size: 100%
// Address margins set differently in Firefox 4+, Safari 5, and Chrome.
margin: 0
// Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet.
button, input
line-height: normal
// Address inconsistent `text-transform` inheritance for `button` and `select`.
// All other form control elements do not inherit `text-transform` values.
// Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
// Correct `select` style inheritance in Firefox 4+ and Opera.
button, select
text-transform: none
button, html input[type='button'], input[type='reset'], input[type='submit']
// Avoid the WebKit bug in Android 4.0.* where `html input[type='button'] { -webkit-appearance: button }` destroys native `audio` and `video` controls.
// Correct inability to style clickable `input` types in iOS.
-webkit-appearance: button
// Improve usability and consistency of cursor style between image-type `input` and others.
cursor: pointer
// Re-set default cursor for disabled elements.
button[disabled], html input[disabled]
cursor: default
input
&[type='checkbox'], &[type='radio']
// Address box sizing set to `content-box` in IE 8/9.
box-sizing: border-box
// Remove excess padding in IE 8/9.
padding: 0
&[type='search']
// Address `appearance` set to `searchfield` in Safari 5 and Chrome.
-webkit-appearance: textfield
// Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof).
-moz-box-sizing: content-box
-webkit-box-sizing: content-box
box-sizing: content-box
// Remove inner padding and search cancel button in Safari 5 and Chrome on OS X.
&::-webkit-search-cancel-button, &::-webkit-search-decoration
-webkit-appearance: none
// Remove inner padding and border in Firefox 4+.
button::-moz-focus-inner, input::-moz-focus-inner
border: 0
padding: 0
textarea
// Remove default vertical scrollbar in IE 8/9.
overflow: auto
// Improve readability and alignment in all browsers.
vertical-align: top
// Tables
// Remove most spacing between table cells.
table
border-collapse: collapse
border-spacing: 0

View File

@@ -1,405 +0,0 @@
@import "compass/css3"
@import "compass/utilities/general/clearfix"
@import "normalize"
// COLORS & BACKGROUNDS --------------------------------------------------------
$yellow: #fdf485
$orange: #e67e39
$blue: #4ae
$green: #61c227
$gray: #777
$gray-light: #aaa
$gray-dark: #222
$color: $gray
$bg-color: #f3f3f3
$border-color: darken($bg-color, 5%)
$header-bg-color: #fff
$section-heading-color: $orange
$heading-color: $gray-dark
$link-color: $blue
$code-color: $gray-light
// TYPE --------------------------------------------------------
$body-font-family: "Karla", "lucida grande", sans-serif
$heading-font-family: "Montserrat", "Helvetica", sans-serif
$code-font-family: "Karla", "lucida grande", sans-serif
// LAYOUT --------------------------------------------------------
$gutter: 30px
$max-column-width: 600px
$sharing-section-z-index: 10
// UI COMPONENTS --------------------------------------------------------
$radius: 8px
/* Typography
*----------------------------------------------- */
html
font: 87% / 1.5 $body-font-family, sans-serif
font-weight: 400
@media (min-width: 40rem)
html
font-size: 100%
@media (min-width: 64rem)
html
font-size: 106%
body
color: $color
background-color: $bg-color
h1, h2, h3, h4, h5
color: $heading-color
line-height: 1.2em
font-family: $heading-font-family
font-weight: 700
h1
font-size: 4rem
margin: 0 0 0.2em 0
line-height: 1.1em
@media (min-width: 40rem)
h1
font-size: 4.5rem
@media (min-width: 64rem)
h1
font-size: 5rem
h2
color: $section-heading-color
margin-bottom: 1.5rem
font-size: 1.5rem
text-transform: uppercase
@media (min-width: 40rem)
h2
font-size: 2rem
h3
font-size: 1.2rem
margin-bottom: .5rem
p
margin: 0 auto 2em auto
text-align: left
.lead
max-width: 50rem
margin-bottom: 1.4rem
font-size: 1.1rem
@media (min-width: 40rem)
.lead
font-size: 1.25rem
strong
font-weight: bold
a
color: $link-color
text-decoration: none
&:hover
text-decoration: underline
::-moz-selection,
::selection
background: $orange
color: white
/* Code
* ========================================================================== */
code
color: $code-color
+border-radius($radius)
font-family: Consolas, Courier, monospace
font-size: 0.9rem
padding: 0.1rem 0.3rem
position: relative
top: -1px
/* Lists
* ========================================================================== */
ul
margin: 0
text-align: left
@media (min-width: 40rem)
ul
display: inline-block
/* Buttons
* ========================================================================== */
.button
display: block
padding: 0.7rem 2rem
margin-bottom: 0.5rem
border: none
color: #fff
background-color: $link-color
font-size: 1.1rem
font-weight: bold
text-transform: uppercase
+border-radius($radius)
vertical-align: middle
white-space: nowrap
&:hover
background: darken($link-color, 10%)
text-decoration: none
@media (min-width: 40rem)
.button
display: inline-block
margin: 0 0.25rem
.button-minor
padding: 0.35rem 1rem
border: 2px solid $link-color
color: $link-color
background-color: transparent
font-size: 0.8rem
&:hover
color: white
/* Elements
* ========================================================================== */
hr
border: 0
border-top: 2px solid $border-color
margin: 2rem auto
width: 3rem
@media (min-width: 40rem)
hr
margin: 2.5rem auto
/* -- Layout ------------------------------------------------------------------ */
*, *:before, *:after
+box-sizing("border-box")
body
margin: 0
padding: 0
background: $bg-color
section
border-top: 2px solid $border-color
text-align: center
padding: 1.5rem 0
&:first-of-type
border-top: none
@media (min-width: 40rem)
section
padding: 2rem 0
.container
margin: 0 auto
max-width: 40rem
width: 90%
/* -- Header -- */
header
padding: 4rem 0 2rem 0
background-color: $header-bg-color
text-align: center
p
text-align: center
@media (min-width: 40rem)
header
padding: 2rem 0
/* -- Examples -- */
.image-section
margin-bottom: 80px
.image-wrap
position: relative
line-height: 1em
.examples-section
.image-section
.target-image
+border-bottom-radius($radius)
.image-section.with-color-thief-output
.target-image
+border-bottom-radius(0)
.run-functions-button
position: absolute
top: 50%
left: 50%
width: 8rem
height: 8rem
margin-top: -4rem
margin-left: -4rem
border: none
+border-radius(50%)
color: $color
background-color: $yellow
font-size: 2rem
font-weight: bold
cursor: pointer
text-transform: uppercase
outline: none
&:hover
+scale(1.1)
+transition(transform .2s)
&:active
+scale(0.9)
&.hide
background-color: $yellow
color: $color
+transition(transform .6s, top .6s cubic-bezier(0.220, -0.370, 0.750, 0.750))
top: 105%
+scale(0)
// Use Modernizr to check for touch support
.touch
.touch-label
display: inline
.no-touch-label
display: none
.no-touch
.touch-label
display: none
.no-touch-label
display: inline
.target-image
display: block
width: 100%
+border-top-radius($radius)
.color-thief-output
display: none
padding: 1.5rem
background-color: white
border: 1px solid $border-color
border-top-width: 0
+border-bottom-radius($radius)
.function-title
margin-top: 0
.function
margin-bottom: 1.5rem
.swatch
display: inline-block
margin: 0
background: #dddddd
@media (min-width: 40rem)
.swatch
margin-right: -2px
.get-color
.swatch
width: 6rem
height: 3rem
.get-palette
.swatch
width: 3rem
height: 2rem
@media (min-width: 40rem)
.get-palette
.swatch
width: 4rem
height: 2.7rem
canvas
display: none
/* -- Credits -- */
footer
padding: 2rem 0
background-color: $header-bg-color
text-align: center
p
text-align: center
.button
margin-top: 0.5rem
/* -- Sharing -- */
.sharing-section
position: fixed
z-index: $sharing-section-z-index
top: 20px
right: 0
/* -- Drag and drop ------------------------------------------------------------------ */
.drag-drop-section
display: none
.drop-zone
height: 25rem
margin-bottom: 4rem
background-color: $gray-dark
+border-radius($radius)
&.dragging
font-weight: 700
+box-shadow(inset 0 0 0 8px $link-color)
.drop-zone-label
color: $link-color
.default-label
display: none
.dragging-label
display: block
.drop-zone-label
position: relative
top: 11rem
color: $yellow
font-size: 1.8rem
text-align: center
pointer-events: none
text-transform: uppercase
+border-radius($radius)
@media (min-width: 40rem)
.drop-zone-label
top: 10.5rem
font-size: 2.4rem
.dragging-label
display: none
.dropped-image
.run-functions-button
display: none
.targetImage
// width: 100%

110
index.html Executable file → Normal file
View File

@@ -16,111 +16,49 @@
</head> </head>
<body> <body>
<header>
<div class="container">
<h1 class="logo">Color Thief</h1>
<p class="lead">
Grab the color palette from an image.<br /> Uses Javascript and the canvas tag to make it happen.
</p>
<a href="https://github.com/lokesh/color-thief/" class="button">
Download from Github</small>
</a>
</div>
</header>
<section id="examples" class="examples-section">
<div class="container">
<h2>Examples</h2>
<div id="example-images"></div> <div id="example-images"></div>
</div>
</section>
<section id="drag-drop" class="drag-drop-section"> <script id='image-tpl' type='text/x-mustache'>
<div class="container"> {{#.}}
<h2>Try it yourself</h2> <div class="image-section" data-image="{{.}}">
<div id="drop-zone" class="drop-zone"> <h2>{{.}}</h2>
<div class="drop-zone-label default-label">Drag an image here</div> <img class="image" src="./examples/img/{{.}}" />
<div class="drop-zone-label dragging-label">Drop it!</div> <div class="output"></div>
</div> </div>
<div id="dragged-images" class="dragged-images"></div> {{/.}}
</div>
</section>
<footer>
<div class="container">
<p>
Created by Lokesh Dhakar<br />
<a href="https://twitter.com/lokesh" class="button button-minor">Follow me on Twitter</a>
</p>
</div>
</footer>
<div id="sharing" class="sharing-section">
<a href="https://twitter.com/share" class="twitter-share-button" data-via="lokesh" data-size="large">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
</div>
<!-- Mustache templates -->
<script id='image-section-template' type='text/x-mustache'>
{{#images}}
<div class="image-section {{class}}">
<div class="image-wrap">
<button class="run-functions-button">
<span class="no-touch-label">Click</span>
<span class="touch-label">Tap</span>
</button>
<img class="target-image" src="{{file}}" />
</div>
<div class="color-thief-output"></div>
</div>
{{/images}}
</script> </script>
<script id="color-thief-output-template" type="text/x-mustache"> <script id="color-tpl" type="text/x-mustache">
<div class="function get-color"> <div class="color">
<h3 class="function-title">Dominant Color</h3> <h3>getColor(img)</h3>
<div class="swatches"> <div class="swatches">
<div class="swatch" style="background-color: rgb({{color.0}}, {{color.1}}, {{color.2}})"></div> <div class="swatch" style="background-color: rgb({{color.0}}, {{color.1}}, {{color.2}})"></div>
</div> </div>
<div class="function-code"> <code>
<code>colorThief.getColor(image):{{elapsedTimeForGetColor}}ms</code> <div class="output-color">{{colorStr}}</div>
<div class="time">{{elapsedTime}}ms</div>
</code>
</div> </div>
</div> </script>
<div class="function get-palette">
<h3 class="function-title">Palette</h3> <script id="palette-tpl" type="text/x-mustache">
<div class="function-output"> <div class="palette" data-count="{{count}}">
<h3>getPalette(img, {{count}})</h3>
<div class="swatches"> <div class="swatches">
{{#palette}} {{#palette}}
<div class="swatch" style="background-color: rgb({{0}}, {{1}}, {{2}})"></div> <div class="swatch" style="background-color: rgb({{0}}, {{1}}, {{2}})"></div>
{{/palette}} {{/palette}}
</div> </div>
</div> <code>
<div class="function-code"> <div class="output-palette">{{paletteStr}}</div>
<code>colorThief.getPalette(image):{{elapsedTimeForGetPalette}}ms</code> <div class="time">{{elapsedTime}}ms</div>
</div> </code>
</div> </div>
</script> </script>
<script src="src/color-thief.js"></script> <script src="src/color-thief.js"></script>
<script src="examples/js/jquery.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.0.1/mustache.min.js"></script>
<script src="examples/js/mustache.js"></script>
<script src="examples/js/demo.js"></script> <script src="examples/js/demo.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-2196019-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body> </body>
</html> </html>

2549
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "color-thief", "name": "color-thief",
"version": "2.0.2", "version": "2.0.1",
"author": { "author": {
"name": "Lokesh Dhakar", "name": "Lokesh Dhakar",
"email": "lokesh.dhakar@gmail.com", "email": "lokesh.dhakar@gmail.com",
@@ -21,23 +21,22 @@
"type": "git", "type": "git",
"url": "https://github.com/lokesh/color-thief.git" "url": "https://github.com/lokesh/color-thief.git"
}, },
"bugs": { "license": "MIT",
"url": "https://github.com/lokesh/color-thief/issues" "scripts": {
"build": "node ./build/build.js",
"dev": "./node_modules/http-server/bin/http-server",
"test": "./node_modules/.bin/cypress open"
}, },
"licenses": [
{
"type": "MIT",
"url": "https://raw.githubusercontent.com/lokesh/color-thief/master/LICENSE/"
}
],
"main": "dist/color-thief.min.js", "main": "dist/color-thief.min.js",
"devDependencies": { "devDependencies": {
"grunt": "~1.0.1", "@node-minify/core": "^4.0.5",
"grunt-contrib-watch": "^1.0.0", "@node-minify/uglify-es": "^4.0.5",
"grunt-contrib-connect": "^1.0.2", "cypress": "^3.3.1",
"grunt-contrib-uglify": "~2.0.0", "eslint": "^5.16.0",
"grunt-contrib-jshint": "~1.0.0", "http-server": "^0.11.1",
"grunt-jscs": "^1.8.0", "mustache": "^3.0.1"
"grunt-contrib-jshint": "^0.11.2" },
"engines": {
"node": ">=10.15.3"
} }
} }

View File

@@ -10,7 +10,7 @@
* *
* License * License
* ------- * -------
* Copyright 2011, 2015 Lokesh Dhakar * Copyright Lokesh Dhakar
* Released under the MIT license * Released under the MIT license
* https://raw.githubusercontent.com/lokesh/color-thief/master/LICENSE * https://raw.githubusercontent.com/lokesh/color-thief/master/LICENSE
* *
@@ -24,26 +24,17 @@
It also simplifies some of the canvas context manipulation It also simplifies some of the canvas context manipulation
with a set of helper functions. with a set of helper functions.
*/ */
var CanvasImage = function (image) { var CanvasImage = function (image) {
this.canvas = document.createElement('canvas'); this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d'); this.context = this.canvas.getContext('2d');
document.body.appendChild(this.canvas);
this.width = this.canvas.width = image.width; this.width = this.canvas.width = image.width;
this.height = this.canvas.height = image.height; this.height = this.canvas.height = image.height;
this.context.drawImage(image, 0, 0, this.width, this.height); this.context.drawImage(image, 0, 0, this.width, this.height);
}; };
CanvasImage.prototype.clear = function () {
this.context.clearRect(0, 0, this.width, this.height);
};
CanvasImage.prototype.update = function (imageData) {
this.context.putImageData(imageData, 0, 0);
};
CanvasImage.prototype.getPixelCount = function () { CanvasImage.prototype.getPixelCount = function () {
return this.width * this.height; return this.width * this.height;
}; };
@@ -52,11 +43,6 @@ CanvasImage.prototype.getImageData = function () {
return this.context.getImageData(0, 0, this.width, this.height); return this.context.getImageData(0, 0, this.width, this.height);
}; };
CanvasImage.prototype.removeCanvas = function () {
this.canvas.parentNode.removeChild(this.canvas);
};
var ColorThief = function () {}; var ColorThief = function () {};
/* /*
@@ -132,14 +118,11 @@ ColorThief.prototype.getPalette = function(sourceImage, colorCount, quality) {
var cmap = MMCQ.quantize(pixelArray, colorCount); var cmap = MMCQ.quantize(pixelArray, colorCount);
var palette = cmap? cmap.palette() : null; var palette = cmap? cmap.palette() : null;
// Clean up
image.removeCanvas();
return palette; return palette;
}; };
ColorThief.prototype.getColorFromUrl = function(imageUrl, callback, quality) { ColorThief.prototype.getColorFromUrl = function(imageUrl, callback, quality) {
sourceImage = document.createElement("img"); let sourceImage = document.createElement("img");
var thief = this; var thief = this;
sourceImage.addEventListener('load' , function(){ sourceImage.addEventListener('load' , function(){
var palette = thief.getPalette(sourceImage, 5, quality); var palette = thief.getPalette(sourceImage, 5, quality);
@@ -151,19 +134,19 @@ ColorThief.prototype.getColorFromUrl = function(imageUrl, callback, quality) {
ColorThief.prototype.getImageData = function(imageUrl, callback) { ColorThief.prototype.getImageData = function(imageUrl, callback) {
xhr = new XMLHttpRequest(); let xhr = new XMLHttpRequest();
xhr.open('GET', imageUrl, true); xhr.open('GET', imageUrl, true);
xhr.responseType = 'arraybuffer' xhr.responseType = 'arraybuffer'
xhr.onload = function(e) { xhr.onload = function() {
if (this.status == 200) { if (this.status == 200) {
uInt8Array = new Uint8Array(this.response) let uInt8Array = new Uint8Array(this.response)
i = uInt8Array.length i = uInt8Array.length
binaryString = new Array(i); let binaryString = new Array(i);
for (var i = 0; i < uInt8Array.length; i++){ for (var i = 0; i < uInt8Array.length; i++){
binaryString[i] = String.fromCharCode(uInt8Array[i]) binaryString[i] = String.fromCharCode(uInt8Array[i])
} }
data = binaryString.join('') let data = binaryString.join('')
base64 = window.btoa(data) let base64 = window.btoa(data)
callback ("data:image/png;base64,"+base64) callback ("data:image/png;base64,"+base64)
} }
} }
@@ -173,7 +156,7 @@ ColorThief.prototype.getImageData = function(imageUrl, callback) {
ColorThief.prototype.getColorAsync = function(imageUrl, callback, quality) { ColorThief.prototype.getColorAsync = function(imageUrl, callback, quality) {
var thief = this; var thief = this;
this.getImageData(imageUrl, function(imageData){ this.getImageData(imageUrl, function(imageData){
sourceImage = document.createElement("img"); let sourceImage = document.createElement("img");
sourceImage.addEventListener('load' , function(){ sourceImage.addEventListener('load' , function(){
var palette = thief.getPalette(sourceImage, 5, quality); var palette = thief.getPalette(sourceImage, 5, quality);
var dominantColor = palette[0]; var dominantColor = palette[0];
@@ -243,10 +226,10 @@ var newPixels = myPixels.map(function(p) {
*/ */
var MMCQ = (function() { var MMCQ = (function() {
// private constants // private constants
var sigbits = 5, var sigbits = 5;
rshift = 8 - sigbits, var rshift = 8 - sigbits;
maxIterations = 1000, var maxIterations = 1000;
fractByPopulations = 0.75; var fractByPopulations = 0.75;
// get reduced-space color index for a pixel // get reduced-space color index for a pixel
function getColorIndex(r, g, b) { function getColorIndex(r, g, b) {
@@ -255,8 +238,8 @@ var MMCQ = (function() {
// Simple priority queue // Simple priority queue
function PQueue(comparator) { function PQueue(comparator) {
var contents = [], var contents = [];
sorted = false; var sorted = false;
function sort() { function sort() {
contents.sort(comparator); contents.sort(comparator);
@@ -310,11 +293,11 @@ var MMCQ = (function() {
return vbox._volume; return vbox._volume;
}, },
count: function(force) { count: function(force) {
var vbox = this, var vbox = this;
histo = vbox.histo; var histo = vbox.histo;
if (!vbox._count_set || force) { if (!vbox._count_set || force) {
var npix = 0, var npix = 0;
index, i, j, k; var index; var i; var j; var k;
for (i = vbox.r1; i <= vbox.r2; i++) { for (i = vbox.r1; i <= vbox.r2; i++) {
for (j = vbox.g1; j <= vbox.g2; j++) { for (j = vbox.g1; j <= vbox.g2; j++) {
for (k = vbox.b1; k <= vbox.b2; k++) { for (k = vbox.b1; k <= vbox.b2; k++) {
@@ -333,16 +316,17 @@ var MMCQ = (function() {
return new VBox(vbox.r1, vbox.r2, vbox.g1, vbox.g2, vbox.b1, vbox.b2, vbox.histo); return new VBox(vbox.r1, vbox.r2, vbox.g1, vbox.g2, vbox.b1, vbox.b2, vbox.histo);
}, },
avg: function(force) { avg: function(force) {
var vbox = this, var vbox = this;
histo = vbox.histo; var histo = vbox.histo;
if (!vbox._avg || force) { if (!vbox._avg || force) {
var ntot = 0, var ntot = 0;
mult = 1 << (8 - sigbits), var mult = 1 << (8 - sigbits);
rsum = 0, var rsum = 0;
gsum = 0, var gsum = 0;
bsum = 0, var bsum = 0;
hval, var hval;
i, j, k, histoindex; var i, j, k;
var histoindex;
for (i = vbox.r1; i <= vbox.r2; i++) { for (i = vbox.r1; i <= vbox.r2; i++) {
for (j = vbox.g1; j <= vbox.g2; j++) { for (j = vbox.g1; j <= vbox.g2; j++) {
for (k = vbox.b1; k <= vbox.b2; k++) { for (k = vbox.b1; k <= vbox.b2; k++) {
@@ -358,7 +342,7 @@ var MMCQ = (function() {
if (ntot) { if (ntot) {
vbox._avg = [~~(rsum/ntot), ~~(gsum/ntot), ~~(bsum/ntot)]; vbox._avg = [~~(rsum/ntot), ~~(gsum/ntot), ~~(bsum/ntot)];
} else { } else {
// console.log('empty box'); // console.log('empty box');
vbox._avg = [ vbox._avg = [
~~(mult * (vbox.r1 + vbox.r2 + 1) / 2), ~~(mult * (vbox.r1 + vbox.r2 + 1) / 2),
~~(mult * (vbox.g1 + vbox.g2 + 1) / 2), ~~(mult * (vbox.g1 + vbox.g2 + 1) / 2),
@@ -369,10 +353,10 @@ var MMCQ = (function() {
return vbox._avg; return vbox._avg;
}, },
contains: function(pixel) { contains: function(pixel) {
var vbox = this, var vbox = this;
rval = pixel[0] >> rshift, var rval = pixel[0] >> rshift;
gval = pixel[1] >> rshift, var gval = pixel[1] >> rshift;
bval = pixel[2] >> rshift; var bval = pixel[2] >> rshift;
return (rval >= vbox.r1 && rval <= vbox.r2 && return (rval >= vbox.r1 && rval <= vbox.r2 &&
gval >= vbox.g1 && gval <= vbox.g2 && gval >= vbox.g1 && gval <= vbox.g2 &&
bval >= vbox.b1 && bval <= vbox.b2); bval >= vbox.b1 && bval <= vbox.b2);
@@ -411,8 +395,10 @@ var MMCQ = (function() {
return this.nearest(color); return this.nearest(color);
}, },
nearest: function(color) { nearest: function(color) {
var vboxes = this.vboxes, var vboxes = this.vboxes;
d1, d2, pColor; var d1;
var d2;
var pColor;
for (var i=0; i<vboxes.size(); i++) { for (var i=0; i<vboxes.size(); i++) {
d2 = Math.sqrt( d2 = Math.sqrt(
Math.pow(color[0] - vboxes.peek(i).color[0], 2) + Math.pow(color[0] - vboxes.peek(i).color[0], 2) +
@@ -437,8 +423,8 @@ var MMCQ = (function() {
vboxes[0].color = [0,0,0]; vboxes[0].color = [0,0,0];
// force lightest color to white if everything > 251 // force lightest color to white if everything > 251
var idx = vboxes.length-1, var idx = vboxes.length-1;
highest = vboxes[idx].color; var highest = vboxes[idx].color;
if (highest[0] > 251 && highest[1] > 251 && highest[2] > 251) if (highest[0] > 251 && highest[1] > 251 && highest[2] > 251)
vboxes[idx].color = [255,255,255]; vboxes[idx].color = [255,255,255];
} }
@@ -447,9 +433,9 @@ var MMCQ = (function() {
// histo (1-d array, giving the number of pixels in // histo (1-d array, giving the number of pixels in
// each quantized region of color space), or null on error // each quantized region of color space), or null on error
function getHisto(pixels) { function getHisto(pixels) {
var histosize = 1 << (3 * sigbits), var histosize = 1 << (3 * sigbits);
histo = new Array(histosize), var histo = new Array(histosize);
index, rval, gval, bval; var index; var rval; var gval; var bval;
pixels.forEach(function(pixel) { pixels.forEach(function(pixel) {
rval = pixel[0] >> rshift; rval = pixel[0] >> rshift;
gval = pixel[1] >> rshift; gval = pixel[1] >> rshift;
@@ -461,10 +447,10 @@ var MMCQ = (function() {
} }
function vboxFromPixels(pixels, histo) { function vboxFromPixels(pixels, histo) {
var rmin=1000000, rmax=0, var rmin=1000000; var rmax=0;
gmin=1000000, gmax=0, var gmin=1000000; var gmax=0;
bmin=1000000, bmax=0, var bmin=1000000; var bmax=0;
rval, gval, bval; var rval; var gval; var bval;
// find min/max // find min/max
pixels.forEach(function(pixel) { pixels.forEach(function(pixel) {
rval = pixel[0] >> rshift; rval = pixel[0] >> rshift;
@@ -483,19 +469,19 @@ var MMCQ = (function() {
function medianCutApply(histo, vbox) { function medianCutApply(histo, vbox) {
if (!vbox.count()) return; if (!vbox.count()) return;
var rw = vbox.r2 - vbox.r1 + 1, var rw = vbox.r2 - vbox.r1 + 1;
gw = vbox.g2 - vbox.g1 + 1, var gw = vbox.g2 - vbox.g1 + 1;
bw = vbox.b2 - vbox.b1 + 1, var bw = vbox.b2 - vbox.b1 + 1;
maxw = pv.max([rw, gw, bw]); var maxw = pv.max([rw, gw, bw]);
// only one pixel, no split // only one pixel, no split
if (vbox.count() == 1) { if (vbox.count() == 1) {
return [vbox.copy()]; return [vbox.copy()];
} }
/* Find the partial sum arrays along the selected axis. */ /* Find the partial sum arrays along the selected axis. */
var total = 0, var total = 0;
partialsum = [], var partialsum = [];
lookaheadsum = [], var lookaheadsum = [];
i, j, k, sum, index; var i; var j; var k; var sum; var index;
if (maxw == rw) { if (maxw == rw) {
for (i = vbox.r1; i <= vbox.r2; i++) { for (i = vbox.r1; i <= vbox.r2; i++) {
sum = 0; sum = 0;
@@ -539,9 +525,9 @@ var MMCQ = (function() {
lookaheadsum[i] = total-d; lookaheadsum[i] = total-d;
}); });
function doCut(color) { function doCut(color) {
var dim1 = color + '1', var dim1 = color + '1';
dim2 = color + '2', var dim2 = color + '2';
left, right, vbox1, vbox2, d2, count2=0; var left; var right; var vbox1; var vbox2; var d2; var count2=0;
for (i = vbox[dim1]; i <= vbox[dim2]; i++) { for (i = vbox[dim1]; i <= vbox[dim2]; i++) {
if (partialsum[i] > total / 2) { if (partialsum[i] > total / 2) {
vbox1 = vbox.copy(); vbox1 = vbox.copy();
@@ -579,8 +565,8 @@ var MMCQ = (function() {
// XXX: check color content and convert to grayscale if insufficient // XXX: check color content and convert to grayscale if insufficient
var histo = getHisto(pixels), var histo = getHisto(pixels);
histosize = 1 << (3 * sigbits); // histosize = 1 << (3 * sigbits);
// check that we aren't below maxcolors already // check that we aren't below maxcolors already
var nColors = 0; var nColors = 0;
@@ -590,15 +576,15 @@ var MMCQ = (function() {
} }
// get the beginning vbox from the colors // get the beginning vbox from the colors
var vbox = vboxFromPixels(pixels, histo), var vbox = vboxFromPixels(pixels, histo);
pq = new PQueue(function(a,b) { return pv.naturalOrder(a.count(), b.count()); }); var pq = new PQueue(function(a,b) { return pv.naturalOrder(a.count(), b.count()); });
pq.push(vbox); pq.push(vbox);
// inner function to do the iteration // inner function to do the iteration
function iter(lh, target) { function iter(lh, target) {
var ncolors = 1, var ncolors = 1;
niters = 0, var niters = 0;
vbox; var vbox;
while (niters < maxIterations) { while (niters < maxIterations) {
vbox = lh.pop(); vbox = lh.pop();
if (!vbox.count()) { /* just put it back */ if (!vbox.count()) { /* just put it back */
@@ -607,9 +593,9 @@ var MMCQ = (function() {
continue; continue;
} }
// do the cut // do the cut
var vboxes = medianCutApply(histo, vbox), var vboxes = medianCutApply(histo, vbox);
vbox1 = vboxes[0], var vbox1 = vboxes[0];
vbox2 = vboxes[1]; var vbox2 = vboxes[1];
if (!vbox1) { if (!vbox1) {
// console.log("vbox1 not defined; shouldn't happen!"); // console.log("vbox1 not defined; shouldn't happen!");