pixel-data-js 0.5.2 → 0.8.0
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/dist/index.dev.cjs +871 -257
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +814 -231
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +871 -257
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +171 -100
- package/dist/index.prod.js +814 -231
- package/dist/index.prod.js.map +1 -1
- package/package.json +1 -1
- package/src/Algorithm/floodFillSelection.ts +1 -1
- package/src/{blend-modes.ts → BlendModes/blend-modes-fast.ts} +215 -217
- package/src/BlendModes/blend-modes-perfect.ts +651 -0
- package/src/BlendModes/blend-modes.ts +31 -0
- package/src/IndexedImage/IndexedImage.ts +32 -49
- package/src/IndexedImage/indexedImageToAverageColor.ts +65 -0
- package/src/PixelData/PixelData.ts +31 -0
- package/src/PixelData/applyMaskToPixelData.ts +1 -1
- package/src/PixelData/blendColorPixelData.ts +4 -3
- package/src/PixelData/blendPixelData.ts +4 -3
- package/src/PixelData/clearPixelData.ts +1 -1
- package/src/PixelData/fillPixelData.ts +1 -1
- package/src/PixelData/invertPixelData.ts +1 -1
- package/src/PixelData/pixelDataToAlphaMask.ts +1 -1
- package/src/PixelData/reflectPixelData.ts +42 -0
- package/src/PixelData/rotatePixelData.ts +56 -0
- package/src/_types.ts +3 -3
- package/src/index.ts +7 -2
- package/src/PixelData.ts +0 -20
|
@@ -1,45 +1,39 @@
|
|
|
1
|
-
import type { BlendColor32, Color32 } from '
|
|
1
|
+
import type { BlendColor32, Color32 } from '../_types'
|
|
2
|
+
import { BlendMode } from './blend-modes'
|
|
2
3
|
|
|
3
|
-
export const
|
|
4
|
+
export const overwriteFast: BlendColor32 = (src, _dst) => src
|
|
4
5
|
|
|
5
|
-
export const
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
// Pattern: (src * a + dst * (255 - a)) >> 8
|
|
11
|
-
// We process RB and G separately so they don't overflow into each other
|
|
12
|
-
const rbMask = 0xFF00FF
|
|
13
|
-
const gMask = 0x00FF00
|
|
6
|
+
export const sourceOverFast: BlendColor32 = (src, dst) => {
|
|
7
|
+
const sa = (src >>> 24) & 0xFF
|
|
8
|
+
if (sa === 255) return src
|
|
9
|
+
if (sa === 0) return dst
|
|
14
10
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const dRB = dst & rbMask
|
|
18
|
-
const dG = dst & gMask
|
|
11
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
12
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
19
13
|
|
|
20
|
-
const
|
|
14
|
+
const da = (dst >>> 24) & 0xFF
|
|
21
15
|
|
|
22
|
-
|
|
23
|
-
const
|
|
16
|
+
// Alpha Lerp inlined
|
|
17
|
+
const invA = 255 - sa
|
|
18
|
+
const r = (sr * sa + dr * invA) >> 8
|
|
19
|
+
const g = (sg * sa + dg * invA) >> 8
|
|
20
|
+
const b = (sb * sa + db * invA) >> 8
|
|
21
|
+
const a = (255 * sa + da * invA) >> 8
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
const outA = (a + (((dst >>> 24) & 0xFF) * invA >> 8))
|
|
27
|
-
return ((outA << 24) | outRB | outG) >>> 0 as Color32
|
|
23
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
28
24
|
}
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
export const darkenColor32: BlendColor32 = (src, dst) => {
|
|
26
|
+
export const darkenFast: BlendColor32 = (src, dst) => {
|
|
32
27
|
const sa = (src >>> 24) & 0xFF
|
|
33
28
|
if (sa === 0) return dst
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const bb = Math.min((src >> 16) & 0xFF, (dst >> 16) & 0xFF)
|
|
29
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
30
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
37
31
|
|
|
38
|
-
|
|
32
|
+
const br = sr < dr ? sr : dr
|
|
33
|
+
const bg = sg < dg ? sg : dg
|
|
34
|
+
const bb = sb < db ? sb : db
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
const dg = (dst >> 8) & 0xFF
|
|
42
|
-
const db = (dst >> 16) & 0xFF
|
|
36
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
43
37
|
|
|
44
38
|
// Alpha Lerp inlined
|
|
45
39
|
const invA = 255 - sa
|
|
@@ -52,64 +46,71 @@ export const darkenColor32: BlendColor32 = (src, dst) => {
|
|
|
52
46
|
}
|
|
53
47
|
|
|
54
48
|
/** (src * dst) / 255 */
|
|
55
|
-
export const
|
|
49
|
+
export const multiplyFast: BlendColor32 = (src, dst) => {
|
|
56
50
|
const sa = (src >>> 24) & 0xFF
|
|
57
51
|
if (sa === 0) return dst
|
|
52
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
53
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
const bb = (((src >> 16) & 0xFF) * db) >> 8
|
|
55
|
+
// Consistent floor rounding for all channels
|
|
56
|
+
const br = (sr * dr) >> 8
|
|
57
|
+
const bg = (sg * dg) >> 8
|
|
58
|
+
const bb = (sb * db) >> 8
|
|
64
59
|
|
|
65
60
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
66
61
|
|
|
67
62
|
// Alpha Lerp inlined
|
|
68
63
|
const invA = 255 - sa
|
|
64
|
+
const da = (dst >>> 24) & 0xFF
|
|
65
|
+
|
|
69
66
|
const r = (br * sa + dr * invA) >> 8
|
|
70
67
|
const g = (bg * sa + dg * invA) >> 8
|
|
71
68
|
const b = (bb * sa + db * invA) >> 8
|
|
72
|
-
const a = (255 * sa +
|
|
69
|
+
const a = (255 * sa + da * invA) >> 8
|
|
73
70
|
|
|
74
71
|
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
75
72
|
}
|
|
76
73
|
|
|
77
74
|
/** 255 - (255-src)/dst */
|
|
78
|
-
export const
|
|
75
|
+
export const colorBurnFast: BlendColor32 = (src, dst) => {
|
|
79
76
|
const sa = (src >>> 24) & 0xFF
|
|
80
77
|
if (sa === 0) return dst
|
|
81
78
|
|
|
82
|
-
const sr = src & 0xFF, sg = (src
|
|
83
|
-
const dr = dst & 0xFF, dg = (dst
|
|
79
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
80
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
84
81
|
|
|
85
|
-
const br = dr === 255 ? 255 : Math.max(0, 255 - ((255 - dr) << 8) /
|
|
86
|
-
const bg = dg === 255 ? 255 : Math.max(0, 255 - ((255 - dg) << 8) /
|
|
87
|
-
const bb = db === 255 ? 255 : Math.max(0, 255 - ((255 - db) << 8) /
|
|
82
|
+
const br = dr === 255 ? 255 : sr === 0 ? 0 : Math.max(0, 255 - (((255 - dr) << 8) / sr) | 0)
|
|
83
|
+
const bg = dg === 255 ? 255 : sg === 0 ? 0 : Math.max(0, 255 - (((255 - dg) << 8) / sg) | 0)
|
|
84
|
+
const bb = db === 255 ? 255 : sb === 0 ? 0 : Math.max(0, 255 - (((255 - db) << 8) / sb) | 0)
|
|
88
85
|
|
|
89
86
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
90
87
|
|
|
91
|
-
// Alpha Lerp inlined
|
|
92
88
|
const invA = 255 - sa
|
|
89
|
+
const da = (dst >>> 24) & 0xFF
|
|
90
|
+
|
|
93
91
|
const r = (br * sa + dr * invA) >> 8
|
|
94
92
|
const g = (bg * sa + dg * invA) >> 8
|
|
95
93
|
const b = (bb * sa + db * invA) >> 8
|
|
96
|
-
const a = (255 * sa +
|
|
94
|
+
const a = (255 * sa + da * invA) >> 8
|
|
97
95
|
|
|
98
96
|
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
/** src + dst - 255 */
|
|
102
|
-
export const
|
|
100
|
+
export const linearBurnFast: BlendColor32 = (src, dst) => {
|
|
103
101
|
const sa = (src >>> 24) & 0xFF
|
|
104
102
|
if (sa === 0) return dst
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
const sr = src & 0xFF, sg = (src >> 8) & 0xFF, sb = (src >> 16) & 0xFF
|
|
103
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
104
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
108
105
|
|
|
109
106
|
// Math: Base + Blend - 255 (clamped to 0)
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
const
|
|
107
|
+
const brU = dr + sr - 255
|
|
108
|
+
const bgU = dg + sg - 255
|
|
109
|
+
const bbU = db + sb - 255
|
|
110
|
+
|
|
111
|
+
const br = brU < 0 ? 0 : brU
|
|
112
|
+
const bg = bgU < 0 ? 0 : bgU
|
|
113
|
+
const bb = bbU < 0 ? 0 : bbU
|
|
113
114
|
|
|
114
115
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
115
116
|
|
|
@@ -123,12 +124,12 @@ export const linearBurnColor32: BlendColor32 = (src, dst) => {
|
|
|
123
124
|
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
export const
|
|
127
|
+
export const darkerFast: BlendColor32 = (src, dst) => {
|
|
127
128
|
const sa = (src >>> 24) & 0xFF
|
|
128
129
|
if (sa === 0) return dst
|
|
129
130
|
|
|
130
|
-
const dr = dst & 0xFF, dg = (dst
|
|
131
|
-
const sr = src & 0xFF, sg = (src
|
|
131
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
132
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
132
133
|
|
|
133
134
|
// 1. Calculate Luminosity (Photoshop Weights: R:0.3, G:0.59, B:0.11)
|
|
134
135
|
// Scaled by 256 for integer math: 77, 151, 28
|
|
@@ -161,7 +162,7 @@ export const darkerColor32: BlendColor32 = (src, dst) => {
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
/** Math.max(src, dst) */
|
|
164
|
-
export const
|
|
165
|
+
export const lightenFast: BlendColor32 = (src, dst) => {
|
|
165
166
|
const sa = (src >>> 24) & 0xFF
|
|
166
167
|
if (sa === 0) return dst
|
|
167
168
|
const br = Math.max(src & 0xFF, dst & 0xFF)
|
|
@@ -187,15 +188,15 @@ export const lightenColor32: BlendColor32 = (src, dst) => {
|
|
|
187
188
|
/**
|
|
188
189
|
* 255 - ((255 - src) * (255 - dst))
|
|
189
190
|
*/
|
|
190
|
-
export const
|
|
191
|
+
export const screenFast: BlendColor32 = (src, dst) => {
|
|
191
192
|
const sa = (src >>> 24) & 0xFF
|
|
192
193
|
if (sa === 0) return dst
|
|
193
194
|
|
|
194
|
-
const dr = dst & 0xFF, dg = (dst
|
|
195
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
195
196
|
|
|
196
197
|
const br = 255 - (((255 - (src & 0xFF)) * (255 - dr)) >> 8)
|
|
197
|
-
const bg = 255 - (((255 - ((src
|
|
198
|
-
const bb = 255 - (((255 - ((src
|
|
198
|
+
const bg = 255 - (((255 - ((src >>> 8) & 0xFF)) * (255 - dg)) >> 8)
|
|
199
|
+
const bb = 255 - (((255 - ((src >>> 16) & 0xFF)) * (255 - db)) >> 8)
|
|
199
200
|
|
|
200
201
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
201
202
|
|
|
@@ -210,16 +211,16 @@ export const screenColor32: BlendColor32 = (src, dst) => {
|
|
|
210
211
|
}
|
|
211
212
|
|
|
212
213
|
/** src === 255 ? 255 : Math.min(255, (dst << 8) / (255 - src)) */
|
|
213
|
-
export const
|
|
214
|
+
export const colorDodgeFast: BlendColor32 = (src, dst) => {
|
|
214
215
|
const sa = (src >>> 24) & 0xFF
|
|
215
216
|
if (sa === 0) return dst
|
|
216
217
|
|
|
217
|
-
const dr = dst & 0xFF, dg = (dst
|
|
218
|
-
const sr = src & 0xFF, sg = (src
|
|
218
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
219
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
219
220
|
|
|
220
|
-
const br = sr === 255 ? 255 : Math.min(255, (dr << 8) / (255 - sr))
|
|
221
|
-
const bg = sg === 255 ? 255 : Math.min(255, (dg << 8) / (255 - sg))
|
|
222
|
-
const bb = sb === 255 ? 255 : Math.min(255, (db << 8) / (255 - sb))
|
|
221
|
+
const br = sr === 255 ? 255 : Math.min(255, ((dr << 8) / (255 - sr)) | 0)
|
|
222
|
+
const bg = sg === 255 ? 255 : Math.min(255, ((dg << 8) / (255 - sg)) | 0)
|
|
223
|
+
const bb = sb === 255 ? 255 : Math.min(255, ((db << 8) / (255 - sb)) | 0)
|
|
223
224
|
|
|
224
225
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
225
226
|
|
|
@@ -234,15 +235,18 @@ export const colorDodgeColor32: BlendColor32 = (src, dst) => {
|
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
/** src + dst */
|
|
237
|
-
export const
|
|
238
|
+
export const linearDodgeFast: BlendColor32 = (src, dst) => {
|
|
238
239
|
const sa = (src >>> 24) & 0xFF
|
|
239
240
|
if (sa === 0) return dst
|
|
241
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
240
242
|
|
|
241
|
-
const
|
|
243
|
+
const brU = (src & 0xFF) + dr
|
|
244
|
+
const bgU = ((src >>> 8) & 0xFF) + dg
|
|
245
|
+
const bbU = ((src >>> 16) & 0xFF) + db
|
|
242
246
|
|
|
243
|
-
const br =
|
|
244
|
-
const bg =
|
|
245
|
-
const bb =
|
|
247
|
+
const br = brU > 255 ? 255 : brU
|
|
248
|
+
const bg = bgU > 255 ? 255 : bgU
|
|
249
|
+
const bb = bbU > 255 ? 255 : bbU
|
|
246
250
|
|
|
247
251
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
248
252
|
|
|
@@ -256,12 +260,12 @@ export const linearDodgeColor32: BlendColor32 = (src, dst) => {
|
|
|
256
260
|
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
257
261
|
}
|
|
258
262
|
|
|
259
|
-
export const
|
|
263
|
+
export const lighterFast: BlendColor32 = (src, dst) => {
|
|
260
264
|
const sa = (src >>> 24) & 0xFF
|
|
261
265
|
if (sa === 0) return dst
|
|
262
266
|
|
|
263
|
-
const dr = dst & 0xFF, dg = (dst
|
|
264
|
-
const sr = src & 0xFF, sg = (src
|
|
267
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
268
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
265
269
|
|
|
266
270
|
// Calculate Luminosity (Photoshop uses Weights: R:0.3, G:0.59, B:0.11)
|
|
267
271
|
// We use integer math (scaled by 256) for speed.
|
|
@@ -293,12 +297,12 @@ export const lighterColor32: BlendColor32 = (src, dst) => {
|
|
|
293
297
|
}
|
|
294
298
|
|
|
295
299
|
/** src < 128 ? (2 * src * dst) : (255 - 2 * (255 - src) * (255 - dst)) */
|
|
296
|
-
export const
|
|
300
|
+
export const overlayFast: BlendColor32 = (src, dst) => {
|
|
297
301
|
const sa = (src >>> 24) & 0xFF
|
|
298
302
|
if (sa === 0) return dst
|
|
299
303
|
|
|
300
|
-
const sr = src & 0xFF, sg = (src
|
|
301
|
-
const dr = dst & 0xFF, dg = (dst
|
|
304
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
305
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
302
306
|
|
|
303
307
|
const br = dr < 128 ? (2 * sr * dr) >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8)
|
|
304
308
|
const bg = dg < 128 ? (2 * sg * dg) >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8)
|
|
@@ -316,13 +320,13 @@ export const overlayColor32: BlendColor32 = (src, dst) => {
|
|
|
316
320
|
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
317
321
|
}
|
|
318
322
|
|
|
319
|
-
/**
|
|
320
|
-
export const
|
|
323
|
+
/** ((255 - dst) * ((src * dst) >> 8) + dst * (255 - (((255 - src) * (255 - dst)) >> 8))) >> 8 */
|
|
324
|
+
export const softLightFast: BlendColor32 = (src, dst) => {
|
|
321
325
|
const sa = (src >>> 24) & 0xFF
|
|
322
326
|
if (sa === 0) return dst
|
|
323
327
|
|
|
324
|
-
const dr = dst & 0xFF, dg = (dst
|
|
325
|
-
const sr = src & 0xFF, sg = (src
|
|
328
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
329
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
326
330
|
|
|
327
331
|
const br = ((255 - dr) * ((sr * dr) >> 8) + dr * (255 - (((255 - sr) * (255 - dr)) >> 8))) >> 8
|
|
328
332
|
const bg = ((255 - dg) * ((sg * dg) >> 8) + dg * (255 - (((255 - sg) * (255 - dg)) >> 8))) >> 8
|
|
@@ -341,12 +345,12 @@ export const softLightColor32: BlendColor32 = (src, dst) => {
|
|
|
341
345
|
}
|
|
342
346
|
|
|
343
347
|
/** If src < 128 (50% gray), Multiply; otherwise, Screen */
|
|
344
|
-
export const
|
|
348
|
+
export const hardLightFast: BlendColor32 = (src, dst) => {
|
|
345
349
|
const sa = (src >>> 24) & 0xFF
|
|
346
350
|
if (sa === 0) return dst
|
|
347
351
|
|
|
348
|
-
const dr = dst & 0xFF, dg = (dst
|
|
349
|
-
const sr = src & 0xFF, sg = (src
|
|
352
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
353
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
350
354
|
|
|
351
355
|
const br = sr < 128 ? (2 * sr * dr) >> 8 : 255 - ((2 * (255 - sr) * (255 - dr)) >> 8)
|
|
352
356
|
const bg = sg < 128 ? (2 * sg * dg) >> 8 : 255 - ((2 * (255 - sg) * (255 - dg)) >> 8)
|
|
@@ -368,24 +372,16 @@ export const hardLightColor32: BlendColor32 = (src, dst) => {
|
|
|
368
372
|
* If src < 128: Burn(dst, 2 * src)
|
|
369
373
|
* If src >= 128: Dodge(dst, 2 * (src - 128))
|
|
370
374
|
*/
|
|
371
|
-
export const
|
|
375
|
+
export const vividLightFast: BlendColor32 = (src, dst) => {
|
|
372
376
|
const sa = (src >>> 24) & 0xFF
|
|
373
377
|
if (sa === 0) return dst
|
|
374
378
|
|
|
375
|
-
const dr = dst & 0xFF, dg = (dst
|
|
376
|
-
const sr = src & 0xFF, sg = (src
|
|
377
|
-
|
|
378
|
-
const br = sr < 128
|
|
379
|
-
? (sr === 0 ? 0 : Math.max(0, 255 - (((255 - dr) << 8) / (2 * sr))))
|
|
380
|
-
: (sr === 255 ? 255 : Math.min(255, (dr << 8) / (2 * (255 - sr))))
|
|
379
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
380
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
381
381
|
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const bb = sb < 128
|
|
387
|
-
? (sb === 0 ? 0 : Math.max(0, 255 - (((255 - db) << 8) / (2 * sb))))
|
|
388
|
-
: (sb === 255 ? 255 : Math.min(255, (db << 8) / (2 * (255 - sb))))
|
|
382
|
+
const br = sr < 128 ? (sr === 0 ? 0 : Math.max(0, 255 - (((255 - dr) << 8) / (2 * sr)) | 0)) : (sr === 255 ? 255 : Math.min(255, ((dr << 8) / (2 * (255 - sr))) | 0))
|
|
383
|
+
const bg = sg < 128 ? (sg === 0 ? 0 : Math.max(0, 255 - (((255 - dg) << 8) / (2 * sg)) | 0)) : (sg === 255 ? 255 : Math.min(255, ((dg << 8) / (2 * (255 - sg))) | 0))
|
|
384
|
+
const bb = sb < 128 ? (sb === 0 ? 0 : Math.max(0, 255 - (((255 - db) << 8) / (2 * sb)) | 0)) : (sb === 255 ? 255 : Math.min(255, ((db << 8) / (2 * (255 - sb))) | 0))
|
|
389
385
|
|
|
390
386
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
391
387
|
|
|
@@ -400,16 +396,20 @@ export const vividLightColor32: BlendColor32 = (src, dst) => {
|
|
|
400
396
|
}
|
|
401
397
|
|
|
402
398
|
/** dst + 2 * src - 255 (Clamped to 0-255) */
|
|
403
|
-
export const
|
|
399
|
+
export const linearLightFast: BlendColor32 = (src, dst) => {
|
|
404
400
|
const sa = (src >>> 24) & 0xFF
|
|
405
401
|
if (sa === 0) return dst
|
|
406
402
|
|
|
407
|
-
const dr = dst & 0xFF, dg = (dst
|
|
408
|
-
const sr = src & 0xFF, sg = (src
|
|
403
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
404
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
405
|
+
|
|
406
|
+
const brU = dr + 2 * sr - 255
|
|
407
|
+
const bgU = dg + 2 * sg - 255
|
|
408
|
+
const bbU = db + 2 * sb - 255
|
|
409
409
|
|
|
410
|
-
const br =
|
|
411
|
-
const bg =
|
|
412
|
-
const bb =
|
|
410
|
+
const br = brU < 0 ? 0 : brU > 255 ? 255 : brU
|
|
411
|
+
const bg = bgU < 0 ? 0 : bgU > 255 ? 255 : bgU
|
|
412
|
+
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU
|
|
413
413
|
|
|
414
414
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
415
415
|
|
|
@@ -424,16 +424,16 @@ export const linearLightColor32: BlendColor32 = (src, dst) => {
|
|
|
424
424
|
}
|
|
425
425
|
|
|
426
426
|
/** src < 128 ? min(dst, 2 * src) : max(dst, 2 * (src - 128)) */
|
|
427
|
-
export const
|
|
427
|
+
export const pinLightFast: BlendColor32 = (src, dst) => {
|
|
428
428
|
const sa = (src >>> 24) & 0xFF
|
|
429
429
|
if (sa === 0) return dst
|
|
430
430
|
|
|
431
|
-
const dr = dst & 0xFF, dg = (dst
|
|
432
|
-
const sr = src & 0xFF, sg = (src
|
|
431
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
432
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
433
433
|
|
|
434
|
-
const br = sr < 128 ?
|
|
435
|
-
const bg = sg < 128 ?
|
|
436
|
-
const bb = sb < 128 ?
|
|
434
|
+
const br = sr < 128 ? (dr < 2 * sr ? dr : 2 * sr) : (dr > 2 * sr - 256 ? dr : 2 * sr - 256)
|
|
435
|
+
const bg = sg < 128 ? (dg < 2 * sg ? dg : 2 * sg) : (dg > 2 * sg - 256 ? dg : 2 * sg - 256)
|
|
436
|
+
const bb = sb < 128 ? (db < 2 * sb ? db : 2 * sb) : (db > 2 * sb - 256 ? db : 2 * sb - 256)
|
|
437
437
|
|
|
438
438
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
439
439
|
|
|
@@ -448,24 +448,16 @@ export const pinLightColor32: BlendColor32 = (src, dst) => {
|
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
/** (Vivid Light logic forced to 0 or 255) */
|
|
451
|
-
export const
|
|
451
|
+
export const hardMixFast: BlendColor32 = (src, dst) => {
|
|
452
452
|
const sa = (src >>> 24) & 0xFF
|
|
453
453
|
if (sa === 0) return dst
|
|
454
454
|
|
|
455
|
-
const dr = dst & 0xFF, dg = (dst
|
|
456
|
-
const sr = src & 0xFF, sg = (src
|
|
457
|
-
|
|
458
|
-
const br = (sr < 128
|
|
459
|
-
? (sr === 0 ? 0 : Math.max(0, 255 - (((255 - dr) << 8) / (2 * sr))))
|
|
460
|
-
: (sr === 255 ? 255 : Math.min(255, (dr << 8) / (2 * (255 - sr))))) < 128 ? 0 : 255
|
|
461
|
-
|
|
462
|
-
const bg = (sg < 128
|
|
463
|
-
? (sg === 0 ? 0 : Math.max(0, 255 - (((255 - dg) << 8) / (2 * sg))))
|
|
464
|
-
: (sg === 255 ? 255 : Math.min(255, (dg << 8) / (2 * (255 - sg))))) < 128 ? 0 : 255
|
|
455
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
456
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
465
457
|
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
|
|
458
|
+
const br = (sr < 128 ? (sr === 0 ? 0 : Math.max(0, 255 - (((255 - dr) << 8) / (2 * sr)) | 0)) : (sr === 255 ? 255 : Math.min(255, ((dr << 8) / (2 * (255 - sr))) | 0))) < 128 ? 0 : 255
|
|
459
|
+
const bg = (sg < 128 ? (sg === 0 ? 0 : Math.max(0, 255 - (((255 - dg) << 8) / (2 * sg)) | 0)) : (sg === 255 ? 255 : Math.min(255, ((dg << 8) / (2 * (255 - sg))) | 0))) < 128 ? 0 : 255
|
|
460
|
+
const bb = (sb < 128 ? (sb === 0 ? 0 : Math.max(0, 255 - (((255 - db) << 8) / (2 * sb)) | 0)) : (sb === 255 ? 255 : Math.min(255, ((db << 8) / (2 * (255 - sb))) | 0))) < 128 ? 0 : 255
|
|
469
461
|
|
|
470
462
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
471
463
|
|
|
@@ -480,15 +472,19 @@ export const hardMixColor32: BlendColor32 = (src, dst) => {
|
|
|
480
472
|
}
|
|
481
473
|
|
|
482
474
|
/** Math.abs(src - dst) */
|
|
483
|
-
export const
|
|
475
|
+
export const differenceFast: BlendColor32 = (src, dst) => {
|
|
484
476
|
const sa = (src >>> 24) & 0xFF
|
|
485
477
|
if (sa === 0) return dst
|
|
486
478
|
|
|
487
|
-
const dr = dst & 0xFF, dg = (dst
|
|
479
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
488
480
|
|
|
489
|
-
const
|
|
490
|
-
const
|
|
491
|
-
const
|
|
481
|
+
const brD = (src & 0xFF) - dr
|
|
482
|
+
const bgD = ((src >>> 8) & 0xFF) - dg
|
|
483
|
+
const bbD = ((src >>> 16) & 0xFF) - db
|
|
484
|
+
|
|
485
|
+
const br = brD < 0 ? -brD : brD
|
|
486
|
+
const bg = bgD < 0 ? -bgD : bgD
|
|
487
|
+
const bb = bbD < 0 ? -bbD : bbD
|
|
492
488
|
|
|
493
489
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
494
490
|
|
|
@@ -503,12 +499,12 @@ export const differenceColor32: BlendColor32 = (src, dst) => {
|
|
|
503
499
|
}
|
|
504
500
|
|
|
505
501
|
/** dst + src - ((dst * src) >> 7) */
|
|
506
|
-
export const
|
|
502
|
+
export const exclusionFast: BlendColor32 = (src, dst) => {
|
|
507
503
|
const sa = (src >>> 24) & 0xFF
|
|
508
504
|
if (sa === 0) return dst
|
|
509
505
|
|
|
510
|
-
const dr = dst & 0xFF, dg = (dst
|
|
511
|
-
const sr = src & 0xFF, sg = (src
|
|
506
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
507
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
512
508
|
|
|
513
509
|
const br = dr + sr - ((dr * sr) >> 7)
|
|
514
510
|
const bg = dg + sg - ((dg * sg) >> 7)
|
|
@@ -527,16 +523,20 @@ export const exclusionColor32: BlendColor32 = (src, dst) => {
|
|
|
527
523
|
}
|
|
528
524
|
|
|
529
525
|
/** Math.max(0, dst - src) */
|
|
530
|
-
export const
|
|
526
|
+
export const subtractFast: BlendColor32 = (src, dst) => {
|
|
531
527
|
const sa = (src >>> 24) & 0xFF
|
|
532
528
|
if (sa === 0) return dst
|
|
533
529
|
|
|
534
|
-
const dr = dst & 0xFF, dg = (dst
|
|
535
|
-
const sr = src & 0xFF, sg = (src
|
|
530
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
531
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
532
|
+
|
|
533
|
+
const brU = dr - sr
|
|
534
|
+
const bgU = dg - sg
|
|
535
|
+
const bbU = db - sb
|
|
536
536
|
|
|
537
|
-
const br =
|
|
538
|
-
const bg =
|
|
539
|
-
const bb =
|
|
537
|
+
const br = brU < 0 ? 0 : brU
|
|
538
|
+
const bg = bgU < 0 ? 0 : bgU
|
|
539
|
+
const bb = bbU < 0 ? 0 : bbU
|
|
540
540
|
|
|
541
541
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
542
542
|
|
|
@@ -551,16 +551,16 @@ export const subtractColor32: BlendColor32 = (src, dst) => {
|
|
|
551
551
|
}
|
|
552
552
|
|
|
553
553
|
/** sr === 0 ? 255 : Math.min(255, (dr << 8) / sr) */
|
|
554
|
-
export const
|
|
554
|
+
export const divideFast: BlendColor32 = (src, dst) => {
|
|
555
555
|
const sa = (src >>> 24) & 0xFF
|
|
556
556
|
if (sa === 0) return dst
|
|
557
557
|
|
|
558
|
-
const dr = dst & 0xFF, dg = (dst
|
|
559
|
-
const sr = src & 0xFF, sg = (src
|
|
558
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
559
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
560
560
|
|
|
561
|
-
const br = sr === 0 ? 255 : Math.min(255, (dr << 8) / sr)
|
|
562
|
-
const bg = sg === 0 ? 255 : Math.min(255, (dg << 8) / sg)
|
|
563
|
-
const bb = sb === 0 ? 255 : Math.min(255, (db << 8) / sb)
|
|
561
|
+
const br = sr === 0 ? 255 : Math.min(255, ((dr << 8) / sr) | 0)
|
|
562
|
+
const bg = sg === 0 ? 255 : Math.min(255, ((dg << 8) / sg) | 0)
|
|
563
|
+
const bb = sb === 0 ? 255 : Math.min(255, ((db << 8) / sb) | 0)
|
|
564
564
|
|
|
565
565
|
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
566
566
|
|
|
@@ -574,95 +574,93 @@ export const divideColor32: BlendColor32 = (src, dst) => {
|
|
|
574
574
|
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
575
575
|
}
|
|
576
576
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
subtract,
|
|
606
|
-
divide,
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
const BLENDER_REGISTRY = [
|
|
610
|
-
[BlendMode.overwrite, overwriteColor32],
|
|
611
|
-
[BlendMode.sourceOver, sourceOverColor32],
|
|
612
|
-
|
|
613
|
-
[BlendMode.darken, darkenColor32],
|
|
614
|
-
[BlendMode.multiply, multiplyColor32],
|
|
615
|
-
[BlendMode.colorBurn, colorBurnColor32],
|
|
616
|
-
[BlendMode.linearBurn, linearBurnColor32],
|
|
617
|
-
[BlendMode.darkerColor, darkerColor32],
|
|
618
|
-
|
|
619
|
-
[BlendMode.lighten, lightenColor32],
|
|
620
|
-
[BlendMode.screen, screenColor32],
|
|
621
|
-
[BlendMode.colorDodge, colorDodgeColor32],
|
|
622
|
-
[BlendMode.linearDodge, linearDodgeColor32],
|
|
623
|
-
[BlendMode.lighterColor, lighterColor32],
|
|
624
|
-
|
|
625
|
-
[BlendMode.overlay, overlayColor32],
|
|
626
|
-
[BlendMode.softLight, softLightColor32],
|
|
627
|
-
[BlendMode.hardLight, hardLightColor32],
|
|
628
|
-
[BlendMode.vividLight, vividLightColor32],
|
|
629
|
-
[BlendMode.linearLight, linearLightColor32],
|
|
630
|
-
[BlendMode.pinLight, pinLightColor32],
|
|
631
|
-
[BlendMode.hardMix, hardMixColor32],
|
|
632
|
-
|
|
633
|
-
[BlendMode.difference, differenceColor32],
|
|
634
|
-
[BlendMode.exclusion, exclusionColor32],
|
|
635
|
-
[BlendMode.subtract, subtractColor32],
|
|
636
|
-
[BlendMode.divide, divideColor32],
|
|
577
|
+
export const FAST_BLENDER_REGISTRY = [
|
|
578
|
+
[BlendMode.overwrite, overwriteFast],
|
|
579
|
+
[BlendMode.sourceOver, sourceOverFast],
|
|
580
|
+
|
|
581
|
+
[BlendMode.darken, darkenFast],
|
|
582
|
+
[BlendMode.multiply, multiplyFast],
|
|
583
|
+
[BlendMode.colorBurn, colorBurnFast],
|
|
584
|
+
[BlendMode.linearBurn, linearBurnFast],
|
|
585
|
+
[BlendMode.darkerColor, darkerFast],
|
|
586
|
+
|
|
587
|
+
[BlendMode.lighten, lightenFast],
|
|
588
|
+
[BlendMode.screen, screenFast],
|
|
589
|
+
[BlendMode.colorDodge, colorDodgeFast],
|
|
590
|
+
[BlendMode.linearDodge, linearDodgeFast],
|
|
591
|
+
[BlendMode.lighterColor, lighterFast],
|
|
592
|
+
|
|
593
|
+
[BlendMode.overlay, overlayFast],
|
|
594
|
+
[BlendMode.softLight, softLightFast],
|
|
595
|
+
[BlendMode.hardLight, hardLightFast],
|
|
596
|
+
[BlendMode.vividLight, vividLightFast],
|
|
597
|
+
[BlendMode.linearLight, linearLightFast],
|
|
598
|
+
[BlendMode.pinLight, pinLightFast],
|
|
599
|
+
[BlendMode.hardMix, hardMixFast],
|
|
600
|
+
|
|
601
|
+
[BlendMode.difference, differenceFast],
|
|
602
|
+
[BlendMode.exclusion, exclusionFast],
|
|
603
|
+
[BlendMode.subtract, subtractFast],
|
|
604
|
+
[BlendMode.divide, divideFast],
|
|
637
605
|
] as const
|
|
638
606
|
|
|
639
|
-
export type
|
|
640
|
-
export type
|
|
607
|
+
export type RegisteredFastBlender = typeof FAST_BLENDER_REGISTRY[number][1]
|
|
608
|
+
export type FastBlendModeIndex = number & { readonly __brandBlendModeIndex: unique symbol }
|
|
641
609
|
|
|
642
|
-
export const
|
|
610
|
+
export const FAST_BLEND_MODES: BlendColor32[] = []
|
|
643
611
|
|
|
644
|
-
for (const [index, blend] of
|
|
645
|
-
|
|
612
|
+
for (const [index, blend] of FAST_BLENDER_REGISTRY) {
|
|
613
|
+
FAST_BLEND_MODES[index as FastBlendModeIndex] = blend
|
|
646
614
|
}
|
|
647
615
|
|
|
648
|
-
export const
|
|
649
|
-
|
|
616
|
+
export const FAST_BLEND_TO_INDEX = new Map<RegisteredFastBlender, FastBlendModeIndex>(
|
|
617
|
+
FAST_BLENDER_REGISTRY.map((entry, index) => {
|
|
650
618
|
return [
|
|
651
619
|
entry[1],
|
|
652
|
-
index as
|
|
620
|
+
index as FastBlendModeIndex,
|
|
653
621
|
]
|
|
654
622
|
}),
|
|
655
623
|
) as {
|
|
656
|
-
get: (blend:
|
|
624
|
+
get: (blend: RegisteredFastBlender) => FastBlendModeIndex
|
|
657
625
|
}
|
|
658
626
|
|
|
659
|
-
export const
|
|
660
|
-
|
|
627
|
+
export const INDEX_TO_FAST_BLEND = new Map<FastBlendModeIndex, RegisteredFastBlender>(
|
|
628
|
+
FAST_BLENDER_REGISTRY.map((entry, index) => {
|
|
661
629
|
return [
|
|
662
|
-
index as
|
|
630
|
+
index as FastBlendModeIndex,
|
|
663
631
|
entry[1],
|
|
664
632
|
]
|
|
665
633
|
}),
|
|
666
634
|
) as {
|
|
667
|
-
get: (index:
|
|
635
|
+
get: (index: FastBlendModeIndex) => RegisteredFastBlender
|
|
668
636
|
}
|
|
637
|
+
|
|
638
|
+
export type FastBlendModes = {
|
|
639
|
+
[K in keyof typeof BlendMode]: RegisteredFastBlender
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
export const FAST_BLEND_MODE_BY_NAME: FastBlendModes = {
|
|
643
|
+
overwrite: overwriteFast,
|
|
644
|
+
sourceOver: sourceOverFast,
|
|
645
|
+
darken: darkenFast,
|
|
646
|
+
multiply: multiplyFast,
|
|
647
|
+
colorBurn: colorBurnFast,
|
|
648
|
+
linearBurn: linearBurnFast,
|
|
649
|
+
darkerColor: darkerFast,
|
|
650
|
+
lighten: lightenFast,
|
|
651
|
+
screen: screenFast,
|
|
652
|
+
colorDodge: colorDodgeFast,
|
|
653
|
+
linearDodge: linearDodgeFast,
|
|
654
|
+
lighterColor: lighterFast,
|
|
655
|
+
overlay: overlayFast,
|
|
656
|
+
softLight: softLightFast,
|
|
657
|
+
hardLight: hardLightFast,
|
|
658
|
+
vividLight: vividLightFast,
|
|
659
|
+
linearLight: linearLightFast,
|
|
660
|
+
pinLight: pinLightFast,
|
|
661
|
+
hardMix: hardMixFast,
|
|
662
|
+
difference: differenceFast,
|
|
663
|
+
exclusion: exclusionFast,
|
|
664
|
+
subtract: subtractFast,
|
|
665
|
+
divide: divideFast,
|
|
666
|
+
} as const
|