Skip to content

Instantly share code, notes, and snippets.

@rsms
Last active March 25, 2020 23:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rsms/13a5fbe20b430e1d20d1b09482614c44 to your computer and use it in GitHub Desktop.
Save rsms/13a5fbe20b430e1d20d1b09482614c44 to your computer and use it in GitHub Desktop.
function dominantColorRGBA(pxv :ArrayLike<int>, pxcount :int, stride :int) :RGBA {
let cm = new Map<int,int[]>()
// average and count RGB values
for (let i = 0; i < pxcount; i += stride) {
let r = pxv[i], g = pxv[i + 1], b = pxv[i + 2], a = pxv[i + 3]
// key = (a << 24) + (r << 16) + (g << 8) + b
let key = (r << 16) + (g << 8) + b
// update or store entry in temporary map.
// note that we premultiply alpha.
let e = cm.get(key)
if (e) {
// update existing entry
e[0] += r * a
e[1] += g * a
e[2] += b * a
e[3] += a
e[4]++ // increment count
} else {
// new RGB value
cm.set(key, [r * a, g * a, b * a, a, 1]);
}
}
// pick the RGB value with highest frequency
let [r, g, b, a, count] = Array.from(cm.values()).sort((a, b) => {
let acount = a[4], bcount = b[4]
return ( acount < bcount ? 1 :
bcount < acount ? -1 :
0 )
})[0]
return ( a == 0 ?
new RGBA(0, 0, 0, 0) :
new RGBA(
(r / a) / 255,
(g / a) / 255,
(b / a) / 255,
(a / count) / 255
)
)
}
let pixels = canvas.context2D().getImageData(0, 0, canvas.width, canvas.height).data
let pxcount = canvas.width * canvas.height
let stride = (pixels.length / pxcount) >>> 0 // bytes per pixel
let dominantColor = (
stride != 4 ? [255,255,255,255] :
dominantColorRGBA(pixels, pxcount, stride * Math.max(1, scale))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment