Skip to content

Instantly share code, notes, and snippets.

@Lorti
Last active November 17, 2016 15:36
Show Gist options
  • Save Lorti/46426ae53a752e3e9188790a5c9d6f02 to your computer and use it in GitHub Desktop.
Save Lorti/46426ae53a752e3e9188790a5c9d6f02 to your computer and use it in GitHub Desktop.
import Jimp from 'jimp';
import { palette as quant } from 'neuquant-js';
const input = 'kapadokya.jpg';
function findClosest(palette, r, g, b) {
let minPos = 0;
let minD = Number.MAX_SAFE_INTEGER;
for (let i = 0, l = palette.length; i < l;) {
const dR = r - palette[i++];
const dG = g - palette[i++];
const dB = b - palette[i];
const d = dR * dR + dG * dG + dB * dB;
if (d < minD) {
minD = d;
minPos = i / 3 | 0;
}
i++;
}
return minPos;
}
function rgbToHex({ r, g, b }) {
function convert(c) {
const hex = c.toString(16);
return hex.length === 1 ? '0' + hex : hex;
}
return '#' + convert(r) + convert(g) + convert(b);
}
Jimp.read(input, (err, image) => {
if (err) {
throw err;
}
const strip = image.clone().resize(256, 3, Jimp.RESIZE_BICUBIC);
const palette = quant(strip.bitmap.data, {
netsize: 16,
samplefac: 10
});
strip.scan(0, 0, strip.bitmap.width, strip.bitmap.height, function (x, y, idx) {
const colorIndex = findClosest(
palette,
this.bitmap.data[idx],
this.bitmap.data[idx + 1],
this.bitmap.data[idx + 2]
);
this.bitmap.data[idx] = palette[colorIndex * 3];
this.bitmap.data[idx + 1] = palette[colorIndex * 3 + 1];
this.bitmap.data[idx + 2] = palette[colorIndex * 3 + 2];
});
strip.write('strip.png');
const groups = [];
let previous = '#';
for (let x = 0; x < strip.bitmap.width; x++) {
const color = rgbToHex(Jimp.intToRGBA(strip.getPixelColor(x, 1)));
if (color !== previous) {
groups.push({
color: color,
pixels: [x],
weight: 1,
center: x / strip.bitmap.width
});
} else {
const group = groups[groups.length - 1];
group.pixels.push(x);
group.weight += 1;
group.center = 100 * (group.pixels.reduce((a, b) => a + b) / group.weight) / strip.bitmap.width;
}
previous = color;
}
const weighted = groups.sort((a, b) => a.weight - b.weight);
const sorted = weighted.slice(-4).sort((a, b) => a.center - b.center);
const result = 'linear-gradient(90deg, ' + sorted.map((group) => {
return `${group.color} ${Math.round(group.center * 100) / 100}%`;
}).join(', ') + ')';
console.log(result);
});
@Lorti
Copy link
Author

Lorti commented Nov 17, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment