-
Notifications
You must be signed in to change notification settings - Fork 212
/
helpers.ts
65 lines (50 loc) · 1.91 KB
/
helpers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
export const getContext = (width, height) => {
const canvas = document.createElement('canvas')
canvas.setAttribute('width', width)
canvas.setAttribute('height', height)
return canvas.getContext('2d')
}
export const getImageData = (src: string, scale: number = 1): Promise<Uint8ClampedArray> => {
const img = new Image()
src = src || img.src
// Can't set cross origin to be anonymous for data url's
// https://github.com/mrdoob/three.js/issues/1305
if (src.startsWith('data')) img.crossOrigin = 'Anonymous'
return new Promise((resolve, reject) => {
img.onload = function () {
const width = img.width * scale
const height = img.height * scale
const context = getContext(width, height)
context.drawImage(img, 0, 0, width, height)
const { data } = context.getImageData(0, 0, width, height)
resolve(data)
}
const errorHandler = () => reject(new Error('An error occurred attempting to load image'))
img.onerror = errorHandler
img.onabort = errorHandler
img.src = src
})
}
export const getCounts = (data: Uint8ClampedArray, ignore: string[]): [] => {
const countMap = {}
for (let i = 0; i < data.length; i += 4 /* 4 gives us r, g, b, and a*/) {
let alpha: number = data[i + 3]
// skip FULLY transparent pixels
if (alpha === 0) continue
let rgbComponents: number[] = Array.from(data.subarray(i, i + 3))
// skip undefined data
if (rgbComponents.indexOf(undefined) !== -1) continue
let color: string = alpha && alpha !== 255
? `rgba(${[...rgbComponents, alpha].join(',')})`
: `rgb(${rgbComponents.join(',')})`
// skip colors in the ignore list
if (ignore.indexOf(color) !== -1) continue
if (countMap[color]) {
countMap[color].count++
} else {
countMap[color] = { color, count: 1 }
}
}
const counts = Object.values(countMap) as []
return counts.sort((a: any, b: any) => b.count - a.count)
}