splashy 6.0.47 → 6.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/package.json +2 -2
- package/src/quantize.js +28 -13
package/README.md
CHANGED
|
@@ -63,6 +63,12 @@ Type: [ImageSource](https://github.com/akfish/node-vibrant#imagesource)
|
|
|
63
63
|
|
|
64
64
|
The raw content for detecting the color information.
|
|
65
65
|
|
|
66
|
+
#### returns
|
|
67
|
+
|
|
68
|
+
A `Promise` resolving to an array of up to 6 hex colors.
|
|
69
|
+
|
|
70
|
+
Every 10th pixel is sampled. White (every channel above 250) and mostly transparent (alpha below 125) pixels are ignored. When white pixels are the only opaque samples, such as a blank page or a white icon on a transparent background, they are counted instead, so the palette is white. When no sample reaches the alpha threshold, such as a fully transparent image, the result is `[]`.
|
|
71
|
+
|
|
66
72
|
## Related
|
|
67
73
|
|
|
68
74
|
- [color-microservice](https://github.com/Kikobeats/color-microservice) – Get color information from any URL image microservice.
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "splashy",
|
|
3
3
|
"description": "Given an image, extract predominant & palette colors",
|
|
4
4
|
"homepage": "https://github.com/microlinkhq/splashy",
|
|
5
|
-
"version": "6.0.
|
|
5
|
+
"version": "6.0.49",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Kiko Beats",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"standard-version": "latest"
|
|
66
66
|
},
|
|
67
67
|
"engines": {
|
|
68
|
-
"node": ">=
|
|
68
|
+
"node": ">= 20"
|
|
69
69
|
},
|
|
70
70
|
"files": [
|
|
71
71
|
"src"
|
package/src/quantize.js
CHANGED
|
@@ -132,7 +132,7 @@ const medianCutApply = (histo, vbox) => {
|
|
|
132
132
|
const gw = vbox.g2 - vbox.g1 + 1
|
|
133
133
|
const bw = vbox.b2 - vbox.b1 + 1
|
|
134
134
|
const maxw = Math.max(rw, gw, bw)
|
|
135
|
-
if (vbox.count() === 1) return [vbox.copy()]
|
|
135
|
+
if (maxw === 1 || vbox.count() === 1) return [vbox.copy()]
|
|
136
136
|
|
|
137
137
|
const axis = maxw === rw ? 'r' : maxw === gw ? 'g' : 'b'
|
|
138
138
|
const { partialsum, total } = partialSums(histo, vbox, axis)
|
|
@@ -166,26 +166,31 @@ const medianCutApply = (histo, vbox) => {
|
|
|
166
166
|
const iterate = (histo, queue, target) => {
|
|
167
167
|
let ncolors = queue.size()
|
|
168
168
|
let niters = 0
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
const unsplittable = []
|
|
170
|
+
while (niters++ < MAX_ITERATIONS && queue.size() && ncolors < target) {
|
|
171
171
|
const vbox = queue.pop()
|
|
172
172
|
if (!vbox.count()) {
|
|
173
173
|
queue.push(vbox)
|
|
174
174
|
continue
|
|
175
175
|
}
|
|
176
176
|
const [vbox1, vbox2] = medianCutApply(histo, vbox)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
ncolors++
|
|
177
|
+
if (!vbox2) {
|
|
178
|
+
unsplittable.push(vbox1)
|
|
179
|
+
continue
|
|
181
180
|
}
|
|
181
|
+
queue.push(vbox1)
|
|
182
|
+
queue.push(vbox2)
|
|
183
|
+
ncolors++
|
|
182
184
|
}
|
|
185
|
+
unsplittable.forEach(vbox => queue.push(vbox))
|
|
183
186
|
}
|
|
184
187
|
|
|
185
|
-
const
|
|
186
|
-
a >= MIN_ALPHA && !(r > WHITE_THRESHOLD && g > WHITE_THRESHOLD && b > WHITE_THRESHOLD)
|
|
188
|
+
const isWhite = (r, g, b) => r > WHITE_THRESHOLD && g > WHITE_THRESHOLD && b > WHITE_THRESHOLD
|
|
187
189
|
|
|
188
|
-
const
|
|
190
|
+
const isSampled = (r, g, b, a, includeWhite) =>
|
|
191
|
+
a >= MIN_ALPHA && (includeWhite || !isWhite(r, g, b))
|
|
192
|
+
|
|
193
|
+
const sample = (rgba, pixelCount, step, maxColors, includeWhite) => {
|
|
189
194
|
const histo = new Uint32Array(HISTO_SIZE)
|
|
190
195
|
const uniqueKeys = []
|
|
191
196
|
const uniqueColors = []
|
|
@@ -201,7 +206,7 @@ const sample = (rgba, pixelCount, step, maxColors) => {
|
|
|
201
206
|
const r = rgba[offset]
|
|
202
207
|
const g = rgba[offset + 1]
|
|
203
208
|
const b = rgba[offset + 2]
|
|
204
|
-
if (!isSampled(r, g, b, rgba[offset + 3])) continue
|
|
209
|
+
if (!isSampled(r, g, b, rgba[offset + 3], includeWhite)) continue
|
|
205
210
|
count++
|
|
206
211
|
if (uniqueKeys.length <= maxColors) {
|
|
207
212
|
const key = (r << 16) | (g << 8) | b
|
|
@@ -224,9 +229,19 @@ const sample = (rgba, pixelCount, step, maxColors) => {
|
|
|
224
229
|
return { count, uniqueColors, histo, vbox: new VBox(rmin, rmax, gmin, gmax, bmin, bmax, histo) }
|
|
225
230
|
}
|
|
226
231
|
|
|
232
|
+
const sampleWithWhiteFallback = (rgba, pixelCount, step, maxColors) => {
|
|
233
|
+
const withoutWhite = sample(rgba, pixelCount, step, maxColors, false)
|
|
234
|
+
return withoutWhite.count ? withoutWhite : sample(rgba, pixelCount, step, maxColors, true)
|
|
235
|
+
}
|
|
236
|
+
|
|
227
237
|
module.exports = (rgba, pixelCount, { step, maxColors }) => {
|
|
228
|
-
const { count, uniqueColors, histo, vbox } =
|
|
229
|
-
|
|
238
|
+
const { count, uniqueColors, histo, vbox } = sampleWithWhiteFallback(
|
|
239
|
+
rgba,
|
|
240
|
+
pixelCount,
|
|
241
|
+
step,
|
|
242
|
+
maxColors
|
|
243
|
+
)
|
|
244
|
+
if (!count) return []
|
|
230
245
|
if (uniqueColors.length <= maxColors) return uniqueColors
|
|
231
246
|
|
|
232
247
|
const byCount = new PQueue((a, b) => a.count() - b.count())
|