Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
"node": ">=0.10.21"
},
"dependencies": {},
"devDependencies": {},
"scripts": {}
"devDependencies": {
"mocha": "^7.1.2"
},
"scripts": {
"test": "mocha"
}
}
14 changes: 7 additions & 7 deletions quantize.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,10 +426,15 @@ var MMCQ = (function() {
// inner function to do the iteration

function iter(lh, target) {
var ncolors = 1,
var ncolors = lh.size(),
niters = 0,
vbox;
while (niters < maxIterations) {
if (ncolors >= target) return;
if (niters++ > maxIterations) {
// console.log("infinite loop; perhaps too few pixels!");
return;
}
vbox = lh.pop();
if (!vbox.count()) { /* just put it back */
lh.push(vbox);
Expand All @@ -450,11 +455,6 @@ var MMCQ = (function() {
lh.push(vbox2);
ncolors++;
}
if (ncolors >= target) return;
if (niters++ > maxIterations) {
// console.log("infinite loop; perhaps too few pixels!");
return;
}
}
}

Expand All @@ -471,7 +471,7 @@ var MMCQ = (function() {
}

// next set - generate the median cuts using the (npix * vol) sorting.
iter(pq2, maxcolors - pq2.size());
iter(pq2, maxcolors);

// calculate the actual colors
var cmap = new CMap();
Expand Down
114 changes: 114 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
const assert = require('assert');
const quantize = require('./quantize');

/**
* Calls the quantize function for the arrayOfPixels with every allowed value of maximumColorCount
* Asserts that the response palette includes the requested number of colors
* Asserts that the response palette, and every color it contains, is in the correct format
* @param {Array} arrayOfPixels as an input array of the format [[190,197,190], [202,204,200], [207,214,210], [211,214,211], [205,207,207]]
*/
function validateResultForAllCounts(arrayOfPixels) {
// console.log("Input pixels:");
// console.log(arrayOfPixels);

for (let count = 2; count <= 256; count < 16 ? count++ : count *= 2) {
let colorMap = quantize(arrayOfPixels, count);
let palette = colorMap.palette();
// console.log("Output palette:");
// console.log(palette);

validatePalette(palette);
// assert.equal(palette.length, count);
console.log(`Actual: ${palette.length}, Expected: ${count}`);
}
}

/**
* Asserts that the specified palette, and every color it contains, is in the correct format
* @param {Array} palette as an array of the format [[204, 204, 204], [208,212,212], [188,196,188], [212,204,196]]
*/
function validatePalette(palette) {
assert(Array.isArray(palette));
palette.forEach(color => {
validateColor(color);
});
}

/**
* Asserts that the specified color is in the correct format
* @param {Array} color as an array of the format [204, 204, 204]
*/
function validateColor(color) {
assert(Array.isArray(color));
assert.equal(color.length, 3);
color.forEach(level => {
assert(level >= 0);
assert(level < 256);
});
}

describe('quantize', function () {
it('works on 1-pixel 1-color images', function (done) {
let arrayOfPixels = [[190,197,190]];

validateResultForAllCounts(arrayOfPixels);
done();
});
it('works on 5-pixel 1-color images', function (done) {
let arrayOfPixels = [[190,197,190], [190,197,190], [190,197,190], [190,197,190], [190,197,190]];

validateResultForAllCounts(arrayOfPixels);
done();
});
it('works on 1000-pixel 1-color images', function (done) {
let arrayOfPixels = [];
let pixel = [190,197,190];
for (let i=0; i < 1000; i++) {
arrayOfPixels.push(pixel);
}

validateResultForAllCounts(arrayOfPixels);
done();
});

it('works on 5-pixel 5-color images', function (done) {
let arrayOfPixels = [[190,197,190], [202,204,200], [207,214,210], [211,214,211], [205,207,207]];

validateResultForAllCounts(arrayOfPixels);
done();
});
it('works on 1000-pixel 5-color images', function (done) {
let arrayOfPixels = [];
for (let i=0; i < 1000/5; i++) {
arrayOfPixels.push([190,197,190]);
arrayOfPixels.push([202,204,200]);
arrayOfPixels.push([207,214,210]);
arrayOfPixels.push([211,214,211]);
arrayOfPixels.push([205,207,207]);
}

validateResultForAllCounts(arrayOfPixels);
done();
});

it('works on 20-pixel 20-color images', function (done) {
let arrayOfPixels = [];
for (let i=0; i < 20; i++) {
arrayOfPixels.push([0,0,i*5]);
}

validateResultForAllCounts(arrayOfPixels);
done();
});
it('works on 1000-pixel 20-color images', function (done) {
let arrayOfPixels = [];
for (let p=0; p < 1000/20; p++) {
for (let i=0; i < 20; i++) {
arrayOfPixels.push([0,0,i*5]);
}
}

validateResultForAllCounts(arrayOfPixels);
done();
});
})