splashy 6.0.48 → 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 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.48",
5
+ "version": "6.0.49",
6
6
  "main": "src/index.js",
7
7
  "author": {
8
8
  "name": "Kiko Beats",
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
- while (niters++ < MAX_ITERATIONS) {
170
- if (ncolors >= target) return
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
- queue.push(vbox1)
178
- if (vbox2) {
179
- queue.push(vbox2)
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 isSampled = (r, g, b, a) =>
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 sample = (rgba, pixelCount, step, maxColors) => {
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 } = sample(rgba, pixelCount, step, maxColors)
229
- if (!count) return false
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())