Getting hex colours from a image
General feedback

There are a few ways that some of the loops can be simplified (see below). These may or may not improve the high CPU issue.

The code makes some repeated calls to functions with the same values in close proximity (e.g. calling th() with each value of rgb twice in rgbToHex()). Storing the returned values and re-using the stored values would make the code more efficient.

I'd consider suggesting the use of functional approaches (E.g. with Array.map(), Array.reduce()) but I wouldn't in this case, given that execution time is an issue.

Targeted feedback

There are some places where const could be used for any variable that doesn't get re-assigned - e.g. vals in ExtractColours::calculateCenter(), plen in ExtractColours::kmeans(), etc. This avoid unintentional re-assignment. 



There are places where parseInt() is called without a radix - e.g.


let idx = parseInt(String(Math.random() * plen));



and


let h = parseInt(i).toString(16);



The radix should always be specified1 because it doesn't always default to 10. 



Let's look at that method ExtractColours::calculateCenter(). The variable plen could be assigned to points.length (like it is in ExtractColours::kmeans()), instead of incrementing that in the second for loop. And then the division of each array element by plen could be moved into the previous for loop.

And vals is declared and assigned like this:


let vals = [];
let plen = 0;

for (let i = 0; i &lt; n; i++) { vals.push(0); }



This could be simplified using Array.fill()

const vals = Array(n).fill(0);


1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#Octal_interpretations_with_no_radix