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
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
import type { BlendColor32, Color32 } from '../_types'
|
|
2
|
+
import { BlendMode } from './blend-modes'
|
|
3
|
+
|
|
4
|
+
export const overwritePerfect: BlendColor32 = (src, _dst) => src
|
|
5
|
+
|
|
6
|
+
export const sourceOverPerfect: BlendColor32 = (src, dst) => {
|
|
7
|
+
const sa = (src >>> 24) & 0xFF
|
|
8
|
+
if (sa === 255) return src
|
|
9
|
+
if (sa === 0) return dst
|
|
10
|
+
|
|
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
|
|
13
|
+
|
|
14
|
+
const da = (dst >>> 24) & 0xFF
|
|
15
|
+
|
|
16
|
+
// Alpha Lerp inlined
|
|
17
|
+
const invA = 255 - sa
|
|
18
|
+
const r = (sr * sa + dr * invA) / 255 | 0
|
|
19
|
+
const g = (sg * sa + dg * invA) / 255 | 0
|
|
20
|
+
const b = (sb * sa + db * invA) / 255 | 0
|
|
21
|
+
const a = (255 * sa + da * invA) / 255 | 0
|
|
22
|
+
|
|
23
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const darkenPerfect: BlendColor32 = (src, dst) => {
|
|
27
|
+
const sa = (src >>> 24) & 0xFF
|
|
28
|
+
if (sa === 0) return dst
|
|
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
|
|
31
|
+
|
|
32
|
+
const br = sr < dr ? sr : dr
|
|
33
|
+
const bg = sg < dg ? sg : dg
|
|
34
|
+
const bb = sb < db ? sb : db
|
|
35
|
+
|
|
36
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
37
|
+
|
|
38
|
+
// Alpha Lerp inlined
|
|
39
|
+
const invA = 255 - sa
|
|
40
|
+
|
|
41
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
42
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
43
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
44
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
45
|
+
|
|
46
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** (src * dst) / 255 */
|
|
50
|
+
export const multiplyPerfect: BlendColor32 = (src, dst) => {
|
|
51
|
+
const sa = (src >>> 24) & 0xFF
|
|
52
|
+
if (sa === 0) return dst
|
|
53
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
54
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
55
|
+
|
|
56
|
+
// Consistent floor rounding for all channels
|
|
57
|
+
const br = (sr * dr / 255) | 0
|
|
58
|
+
const bg = (sg * dg / 255) | 0
|
|
59
|
+
const bb = (sb * db / 255) | 0
|
|
60
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
61
|
+
|
|
62
|
+
// Alpha Lerp inlined
|
|
63
|
+
const invA = 255 - sa
|
|
64
|
+
const da = (dst >>> 24) & 0xFF
|
|
65
|
+
|
|
66
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
67
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
68
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
69
|
+
const a = (255 * sa + da * invA) / 255 | 0
|
|
70
|
+
|
|
71
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** 255 - (255-src)/dst */
|
|
75
|
+
export const colorBurnPerfect: BlendColor32 = (src, dst) => {
|
|
76
|
+
const sa = (src >>> 24) & 0xFF
|
|
77
|
+
if (sa === 0) return dst
|
|
78
|
+
|
|
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
|
|
81
|
+
const br = dr === 255 ? 255 : sr === 0 ? 0 : Math.max(0, (255 - (((255 - dr) * 255 / sr) | 0)))
|
|
82
|
+
const bg = dg === 255 ? 255 : sg === 0 ? 0 : Math.max(0, (255 - (((255 - dg) * 255 / sg) | 0)))
|
|
83
|
+
const bb = db === 255 ? 255 : sb === 0 ? 0 : Math.max(0, (255 - (((255 - db) * 255 / sb) | 0)))
|
|
84
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
85
|
+
|
|
86
|
+
const invA = 255 - sa
|
|
87
|
+
const da = (dst >>> 24) & 0xFF
|
|
88
|
+
|
|
89
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
90
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
91
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
92
|
+
const a = (255 * sa + da * invA) / 255 | 0
|
|
93
|
+
|
|
94
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** src + dst - 255 */
|
|
98
|
+
export const linearBurnPerfect: BlendColor32 = (src, dst) => {
|
|
99
|
+
const sa = (src >>> 24) & 0xFF
|
|
100
|
+
if (sa === 0) return dst
|
|
101
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
102
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
103
|
+
|
|
104
|
+
// Math: Base + Blend - 255 (clamped to 0)
|
|
105
|
+
const brU = dr + sr - 255
|
|
106
|
+
const br = brU < 0 ? 0 : brU
|
|
107
|
+
const bgU = dg + sg - 255
|
|
108
|
+
const bg = bgU < 0 ? 0 : bgU
|
|
109
|
+
const bbU = db + sb - 255
|
|
110
|
+
const bb = bbU < 0 ? 0 : bbU
|
|
111
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
112
|
+
|
|
113
|
+
// Alpha Lerp inlined
|
|
114
|
+
const invA = 255 - sa
|
|
115
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
116
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
117
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
118
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
119
|
+
|
|
120
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const darkerPerfect: BlendColor32 = (src, dst) => {
|
|
124
|
+
const sa = (src >>> 24) & 0xFF
|
|
125
|
+
if (sa === 0) return dst
|
|
126
|
+
|
|
127
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
128
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
129
|
+
|
|
130
|
+
// 1. Calculate Luminosity (Photoshop Weights: R:0.3, G:0.59, B:0.11)
|
|
131
|
+
// Scaled by 256 for integer math: 77, 151, 28
|
|
132
|
+
const lumSrc = (sr * 77 + sg * 151 + sb * 28)
|
|
133
|
+
const lumDst = (dr * 77 + dg * 151 + db * 28)
|
|
134
|
+
|
|
135
|
+
// 2. Selection Logic
|
|
136
|
+
// Pick the perceptually darker pixel
|
|
137
|
+
let br, bg, bb
|
|
138
|
+
if (lumSrc < lumDst) {
|
|
139
|
+
br = sr
|
|
140
|
+
bg = sg
|
|
141
|
+
bb = sb
|
|
142
|
+
} else {
|
|
143
|
+
br = dr
|
|
144
|
+
bg = dg
|
|
145
|
+
bb = db
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
149
|
+
|
|
150
|
+
// 3. Alpha Lerp inlined
|
|
151
|
+
const invA = 255 - sa
|
|
152
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
153
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
154
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
155
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
156
|
+
|
|
157
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Math.max(src, dst) */
|
|
161
|
+
export const lightenPerfect: BlendColor32 = (src, dst) => {
|
|
162
|
+
const sa = (src >>> 24) & 0xFF
|
|
163
|
+
if (sa === 0) return dst
|
|
164
|
+
|
|
165
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
166
|
+
const br = (src & 0xFF) > dr ? (src & 0xFF) : dr
|
|
167
|
+
const bg = ((src >>> 8) & 0xFF) > dg ? ((src >>> 8) & 0xFF) : dg
|
|
168
|
+
const bb = ((src >>> 16) & 0xFF) > db ? ((src >>> 16) & 0xFF) : db
|
|
169
|
+
|
|
170
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
171
|
+
// Alpha Lerp inlined
|
|
172
|
+
const invA = 255 - sa
|
|
173
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
174
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
175
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
176
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
177
|
+
|
|
178
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* 255 - ((255 - src) * (255 - dst))
|
|
183
|
+
*/
|
|
184
|
+
export const screenPerfect: BlendColor32 = (src, dst) => {
|
|
185
|
+
const sa = (src >>> 24) & 0xFF
|
|
186
|
+
if (sa === 0) return dst
|
|
187
|
+
|
|
188
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
189
|
+
|
|
190
|
+
const br = 255 - (((255 - (src & 0xFF)) * (255 - dr) / 255) | 0)
|
|
191
|
+
const bg = 255 - (((255 - ((src >>> 8) & 0xFF)) * (255 - dg) / 255) | 0)
|
|
192
|
+
const bb = 255 - (((255 - ((src >>> 16) & 0xFF)) * (255 - db) / 255) | 0)
|
|
193
|
+
|
|
194
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
195
|
+
|
|
196
|
+
// Alpha Lerp inlined
|
|
197
|
+
const invA = 255 - sa
|
|
198
|
+
|
|
199
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
200
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
201
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
202
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
203
|
+
|
|
204
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** src === 255 ? 255 : Math.min(255, (dst << 8) / (255 - src)) */
|
|
208
|
+
export const colorDodgePerfect: BlendColor32 = (src, dst) => {
|
|
209
|
+
const sa = (src >>> 24) & 0xFF
|
|
210
|
+
if (sa === 0) return dst
|
|
211
|
+
|
|
212
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
213
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
214
|
+
|
|
215
|
+
const br = sr === 255 ? 255 : Math.min(255, ((dr * 255 / (255 - sr)) | 0))
|
|
216
|
+
const bg = sg === 255 ? 255 : Math.min(255, ((dg * 255 / (255 - sg)) | 0))
|
|
217
|
+
const bb = sb === 255 ? 255 : Math.min(255, ((db * 255 / (255 - sb)) | 0))
|
|
218
|
+
|
|
219
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
220
|
+
|
|
221
|
+
// Alpha Lerp inlined
|
|
222
|
+
const invA = 255 - sa
|
|
223
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
224
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
225
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
226
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
227
|
+
|
|
228
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** src + dst */
|
|
232
|
+
export const linearDodgePerfect: BlendColor32 = (src, dst) => {
|
|
233
|
+
const sa = (src >>> 24) & 0xFF
|
|
234
|
+
if (sa === 0) return dst
|
|
235
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
236
|
+
|
|
237
|
+
const brU = (src & 0xFF) + dr
|
|
238
|
+
const br = brU > 255 ? 255 : brU
|
|
239
|
+
const bgU = ((src >>> 8) & 0xFF) + dg
|
|
240
|
+
const bg = bgU > 255 ? 255 : bgU
|
|
241
|
+
const bbU = ((src >>> 16) & 0xFF) + db
|
|
242
|
+
const bb = bbU > 255 ? 255 : bbU
|
|
243
|
+
|
|
244
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
245
|
+
|
|
246
|
+
// Alpha Lerp inlined
|
|
247
|
+
const invA = 255 - sa
|
|
248
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
249
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
250
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
251
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
252
|
+
|
|
253
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export const lighterPerfect: BlendColor32 = (src, dst) => {
|
|
257
|
+
const sa = (src >>> 24) & 0xFF
|
|
258
|
+
if (sa === 0) return dst
|
|
259
|
+
|
|
260
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
261
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
262
|
+
|
|
263
|
+
// Calculate Luminosity (Photoshop uses Weights: R:0.3, G:0.59, B:0.11)
|
|
264
|
+
// We use integer math (scaled by 256) for speed.
|
|
265
|
+
const lumSrc = (sr * 77 + sg * 151 + sb * 28)
|
|
266
|
+
const lumDst = (dr * 77 + dg * 151 + db * 28)
|
|
267
|
+
|
|
268
|
+
// Selection Logic (Base result)
|
|
269
|
+
let br, bg, bb
|
|
270
|
+
if (lumSrc > lumDst) {
|
|
271
|
+
br = sr
|
|
272
|
+
bg = sg
|
|
273
|
+
bb = sb
|
|
274
|
+
} else {
|
|
275
|
+
br = dr
|
|
276
|
+
bg = dg
|
|
277
|
+
bb = db
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
281
|
+
|
|
282
|
+
// Alpha Lerp
|
|
283
|
+
const invA = 255 - sa
|
|
284
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
285
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
286
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
287
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
288
|
+
|
|
289
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** src < 128 ? (2 * src * dst) : (255 - 2 * (255 - src) * (255 - dst)) */
|
|
293
|
+
export const overlayPerfect: BlendColor32 = (src, dst) => {
|
|
294
|
+
const sa = (src >>> 24) & 0xFF
|
|
295
|
+
if (sa === 0) return dst
|
|
296
|
+
|
|
297
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
298
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
299
|
+
const br = dr < 128 ? (2 * sr * dr / 255) | 0 : 255 - ((2 * (255 - sr) * (255 - dr) / 255) | 0)
|
|
300
|
+
const bg = dg < 128 ? (2 * sg * dg / 255) | 0 : 255 - ((2 * (255 - sg) * (255 - dg) / 255) | 0)
|
|
301
|
+
const bb = db < 128 ? (2 * sb * db / 255) | 0 : 255 - ((2 * (255 - sb) * (255 - db) / 255) | 0)
|
|
302
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
303
|
+
|
|
304
|
+
// Alpha Lerp inlined
|
|
305
|
+
const invA = 255 - sa
|
|
306
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
307
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
308
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
309
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
310
|
+
|
|
311
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** ((255 - dst) * ((src * dst) >> 8) + dst * (255 - (((255 - src) * (255 - dst)) >> 8))) >> 8 */
|
|
315
|
+
export const softLightPerfect: BlendColor32 = (src, dst) => {
|
|
316
|
+
const sa = (src >>> 24) & 0xFF
|
|
317
|
+
if (sa === 0) return dst
|
|
318
|
+
|
|
319
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
320
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
321
|
+
const br = (((255 - dr) * ((sr * dr / 255) | 0) + dr * (255 - (((255 - sr) * (255 - dr) / 255) | 0))) / 255) | 0
|
|
322
|
+
const bg = (((255 - dg) * ((sg * dg / 255) | 0) + dg * (255 - (((255 - sg) * (255 - dg) / 255) | 0))) / 255) | 0
|
|
323
|
+
const bb = (((255 - db) * ((sb * db / 255) | 0) + db * (255 - (((255 - sb) * (255 - db) / 255) | 0))) / 255) | 0
|
|
324
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
325
|
+
|
|
326
|
+
// Alpha Lerp inlined
|
|
327
|
+
const invA = 255 - sa
|
|
328
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
329
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
330
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
331
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
332
|
+
|
|
333
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** If src < 128 (50% gray), Multiply; otherwise, Screen */
|
|
337
|
+
export const hardLightPerfect: BlendColor32 = (src, dst) => {
|
|
338
|
+
const sa = (src >>> 24) & 0xFF
|
|
339
|
+
if (sa === 0) return dst
|
|
340
|
+
|
|
341
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
342
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
343
|
+
const br = sr < 128 ? (2 * sr * dr / 255) | 0 : 255 - ((2 * (255 - sr) * (255 - dr) / 255) | 0)
|
|
344
|
+
const bg = sg < 128 ? (2 * sg * dg / 255) | 0 : 255 - ((2 * (255 - sg) * (255 - dg) / 255) | 0)
|
|
345
|
+
const bb = sb < 128 ? (2 * sb * db / 255) | 0 : 255 - ((2 * (255 - sb) * (255 - db) / 255) | 0)
|
|
346
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
347
|
+
|
|
348
|
+
// Alpha Lerp inlined
|
|
349
|
+
const invA = 255 - sa
|
|
350
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
351
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
352
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
353
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
354
|
+
|
|
355
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* If src < 128: Burn(dst, 2 * src)
|
|
360
|
+
* If src >= 128: Dodge(dst, 2 * (src - 128))
|
|
361
|
+
*/
|
|
362
|
+
export const vividLightPerfect: BlendColor32 = (src, dst) => {
|
|
363
|
+
const sa = (src >>> 24) & 0xFF
|
|
364
|
+
if (sa === 0) return dst
|
|
365
|
+
|
|
366
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
367
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
368
|
+
const br = sr < 128 ? (sr === 0 ? 0 : Math.max(0, (255 - (((255 - dr) * 255 / (2 * sr)) | 0)))) : (sr === 255 ? 255 : Math.min(255, ((dr * 255 / (2 * (255 - sr))) | 0)))
|
|
369
|
+
const bg = sg < 128 ? (sg === 0 ? 0 : Math.max(0, (255 - (((255 - dg) * 255 / (2 * sg)) | 0)))) : (sg === 255 ? 255 : Math.min(255, ((dg * 255 / (2 * (255 - sg))) | 0)))
|
|
370
|
+
const bb = sb < 128 ? (sb === 0 ? 0 : Math.max(0, (255 - (((255 - db) * 255 / (2 * sb)) | 0)))) : (sb === 255 ? 255 : Math.min(255, ((db * 255 / (2 * (255 - sb))) | 0)))
|
|
371
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
372
|
+
|
|
373
|
+
// Alpha Lerp inlined
|
|
374
|
+
const invA = 255 - sa
|
|
375
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
376
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
377
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
378
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
379
|
+
|
|
380
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/** dst + 2 * src - 255 (Clamped to 0-255) */
|
|
384
|
+
export const linearLightPerfect: BlendColor32 = (src, dst) => {
|
|
385
|
+
const sa = (src >>> 24) & 0xFF
|
|
386
|
+
if (sa === 0) return dst
|
|
387
|
+
|
|
388
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
389
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
390
|
+
const brU = dr + 2 * sr - 255
|
|
391
|
+
const br = brU < 0 ? 0 : brU > 255 ? 255 : brU
|
|
392
|
+
const bgU = dg + 2 * sg - 255
|
|
393
|
+
const bg = bgU < 0 ? 0 : bgU > 255 ? 255 : bgU
|
|
394
|
+
const bbU = db + 2 * sb - 255
|
|
395
|
+
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU
|
|
396
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
397
|
+
|
|
398
|
+
// Alpha Lerp inlined
|
|
399
|
+
const invA = 255 - sa
|
|
400
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
401
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
402
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
403
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
404
|
+
|
|
405
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** src < 128 ? min(dst, 2 * src) : max(dst, 2 * (src - 128)) */
|
|
409
|
+
export const pinLightPerfect: BlendColor32 = (src, dst) => {
|
|
410
|
+
const sa = (src >>> 24) & 0xFF
|
|
411
|
+
if (sa === 0) return dst
|
|
412
|
+
|
|
413
|
+
const dr = dst & 0xFF
|
|
414
|
+
const dg = (dst >>> 8) & 0xFF
|
|
415
|
+
const db = (dst >>> 16) & 0xFF
|
|
416
|
+
const sr = src & 0xFF
|
|
417
|
+
const sg = (src >>> 8) & 0xFF
|
|
418
|
+
const sb = (src >>> 16) & 0xFF
|
|
419
|
+
|
|
420
|
+
const br = sr < 128 ? (dr < (sr << 1) ? dr : (sr << 1)) : (dr > ((sr - 128) << 1) ? dr : ((sr - 128) << 1))
|
|
421
|
+
const bg = sg < 128 ? (dg < (sg << 1) ? dg : (sg << 1)) : (dg > ((sg - 128) << 1) ? dg : ((sg - 128) << 1))
|
|
422
|
+
const bb = sb < 128 ? (db < (sb << 1) ? db : (sb << 1)) : (db > ((sb - 128) << 1) ? db : ((sb - 128) << 1))
|
|
423
|
+
|
|
424
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
425
|
+
|
|
426
|
+
const invA = 255 - sa
|
|
427
|
+
const da = (dst >>> 24) & 0xFF
|
|
428
|
+
const r = (br * sa + dr * invA + 128) / 255 | 0
|
|
429
|
+
const g = (bg * sa + dg * invA + 128) / 255 | 0
|
|
430
|
+
const b = (bb * sa + db * invA + 128) / 255 | 0
|
|
431
|
+
const a = (255 * sa + da * invA + 128) / 255 | 0
|
|
432
|
+
|
|
433
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/** (Vivid Light logic forced to 0 or 255) */
|
|
437
|
+
export const hardMixPerfect: BlendColor32 = (src, dst) => {
|
|
438
|
+
const sa = (src >>> 24) & 0xFF
|
|
439
|
+
if (sa === 0) return dst
|
|
440
|
+
|
|
441
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
442
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
443
|
+
const br = (sr < 128 ? (sr === 0 ? 0 : Math.max(0, (255 - (((255 - dr) * 255 / (2 * sr)) | 0)))) : (sr === 255 ? 255 : Math.min(255, ((dr * 255 / (2 * (255 - sr))) | 0)))) < 128 ? 0 : 255
|
|
444
|
+
const bg = (sg < 128 ? (sg === 0 ? 0 : Math.max(0, (255 - (((255 - dg) * 255 / (2 * sg)) | 0)))) : (sg === 255 ? 255 : Math.min(255, ((dg * 255 / (2 * (255 - sg))) | 0)))) < 128 ? 0 : 255
|
|
445
|
+
const bb = (sb < 128 ? (sb === 0 ? 0 : Math.max(0, (255 - (((255 - db) * 255 / (2 * sb)) | 0)))) : (sb === 255 ? 255 : Math.min(255, ((db * 255 / (2 * (255 - sb))) | 0)))) < 128 ? 0 : 255
|
|
446
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
447
|
+
|
|
448
|
+
// Alpha Lerp inlined
|
|
449
|
+
const invA = 255 - sa
|
|
450
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
451
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
452
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
453
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
454
|
+
|
|
455
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/** Math.abs(src - dst) */
|
|
459
|
+
export const differencePerfect: BlendColor32 = (src, dst) => {
|
|
460
|
+
const sa = (src >>> 24) & 0xFF
|
|
461
|
+
if (sa === 0) return dst
|
|
462
|
+
|
|
463
|
+
const dr = dst & 0xFF
|
|
464
|
+
const dg = (dst >>> 8) & 0xFF
|
|
465
|
+
const db = (dst >>> 16) & 0xFF
|
|
466
|
+
const sr = src & 0xFF
|
|
467
|
+
const sg = (src >>> 8) & 0xFF
|
|
468
|
+
const sb = (src >>> 16) & 0xFF
|
|
469
|
+
|
|
470
|
+
const br = Math.abs(dr - sr)
|
|
471
|
+
const bg = Math.abs(dg - sg)
|
|
472
|
+
const bb = Math.abs(db - sb)
|
|
473
|
+
|
|
474
|
+
if (sa === 255) {
|
|
475
|
+
return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const invA = 255 - sa
|
|
479
|
+
const da = (dst >>> 24) & 0xFF
|
|
480
|
+
const r = (br * sa + dr * invA + 128) / 255 | 0
|
|
481
|
+
const g = (bg * sa + dg * invA + 128) / 255 | 0
|
|
482
|
+
const b = (bb * sa + db * invA + 128) / 255 | 0
|
|
483
|
+
const a = (255 * sa + da * invA + 128) / 255 | 0
|
|
484
|
+
|
|
485
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/** dst + src - ((dst * src) >> 7) */
|
|
489
|
+
export const exclusionPerfect: BlendColor32 = (src, dst) => {
|
|
490
|
+
const sa = (src >>> 24) & 0xFF
|
|
491
|
+
if (sa === 0) return dst
|
|
492
|
+
|
|
493
|
+
const dr = dst & 0xFF
|
|
494
|
+
const dg = (dst >>> 8) & 0xFF
|
|
495
|
+
const db = (dst >>> 16) & 0xFF
|
|
496
|
+
const sr = src & 0xFF
|
|
497
|
+
const sg = (src >>> 8) & 0xFF
|
|
498
|
+
const sb = (src >>> 16) & 0xFF
|
|
499
|
+
|
|
500
|
+
// Using >> 7 (divide by 128) instead of / 255
|
|
501
|
+
// This is equivalent to (2 * s * d) / 256
|
|
502
|
+
const br = dr + sr - ((dr * sr) >> 7)
|
|
503
|
+
const bg = dg + sg - ((dg * sg) >> 7)
|
|
504
|
+
const bb = db + sb - ((db * sb) >> 7)
|
|
505
|
+
|
|
506
|
+
if (sa === 255) {
|
|
507
|
+
return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const invA = 255 - sa
|
|
511
|
+
const da = (dst >>> 24) & 0xFF
|
|
512
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
513
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
514
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
515
|
+
const a = (255 * sa + da * invA) / 255 | 0
|
|
516
|
+
|
|
517
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/** Math.max(0, dst - src) */
|
|
521
|
+
export const subtractPerfect: BlendColor32 = (src, dst) => {
|
|
522
|
+
const sa = (src >>> 24) & 0xFF
|
|
523
|
+
if (sa === 0) return dst
|
|
524
|
+
|
|
525
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
526
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
527
|
+
const brU = dr - sr
|
|
528
|
+
const br = brU < 0 ? 0 : brU
|
|
529
|
+
const bgU = dg - sg
|
|
530
|
+
const bg = bgU < 0 ? 0 : bgU
|
|
531
|
+
const bbU = db - sb
|
|
532
|
+
const bb = bbU < 0 ? 0 : bbU
|
|
533
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
534
|
+
|
|
535
|
+
// Alpha Lerp inlined
|
|
536
|
+
const invA = 255 - sa
|
|
537
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
538
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
539
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
540
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
541
|
+
|
|
542
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/** sr === 0 ? 255 : Math.min(255, (dr << 8) / sr) */
|
|
546
|
+
export const dividePerfect: BlendColor32 = (src, dst) => {
|
|
547
|
+
const sa = (src >>> 24) & 0xFF
|
|
548
|
+
if (sa === 0) return dst
|
|
549
|
+
|
|
550
|
+
const dr = dst & 0xFF, dg = (dst >>> 8) & 0xFF, db = (dst >>> 16) & 0xFF
|
|
551
|
+
const sr = src & 0xFF, sg = (src >>> 8) & 0xFF, sb = (src >>> 16) & 0xFF
|
|
552
|
+
const br = sr === 0 ? 255 : Math.min(255, ((dr * 255 / sr) | 0))
|
|
553
|
+
const bg = sg === 0 ? 255 : Math.min(255, ((dg * 255 / sg) | 0))
|
|
554
|
+
const bb = sb === 0 ? 255 : Math.min(255, ((db * 255 / sb) | 0))
|
|
555
|
+
if (sa === 255) return (0xFF000000 | (bb << 16) | (bg << 8) | br) >>> 0 as Color32
|
|
556
|
+
|
|
557
|
+
// Alpha Lerp inlined
|
|
558
|
+
const invA = 255 - sa
|
|
559
|
+
const r = (br * sa + dr * invA) / 255 | 0
|
|
560
|
+
const g = (bg * sa + dg * invA) / 255 | 0
|
|
561
|
+
const b = (bb * sa + db * invA) / 255 | 0
|
|
562
|
+
const a = (255 * sa + ((dst >>> 24) & 0xFF) * invA) / 255 | 0
|
|
563
|
+
|
|
564
|
+
return ((a << 24) | (b << 16) | (g << 8) | r) >>> 0 as Color32
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export const PERFECT_BLENDER_REGISTRY = [
|
|
568
|
+
[BlendMode.overwrite, overwritePerfect],
|
|
569
|
+
[BlendMode.sourceOver, sourceOverPerfect],
|
|
570
|
+
|
|
571
|
+
[BlendMode.darken, darkenPerfect],
|
|
572
|
+
[BlendMode.multiply, multiplyPerfect],
|
|
573
|
+
[BlendMode.colorBurn, colorBurnPerfect],
|
|
574
|
+
[BlendMode.linearBurn, linearBurnPerfect],
|
|
575
|
+
[BlendMode.darkerColor, darkerPerfect],
|
|
576
|
+
|
|
577
|
+
[BlendMode.lighten, lightenPerfect],
|
|
578
|
+
[BlendMode.screen, screenPerfect],
|
|
579
|
+
[BlendMode.colorDodge, colorDodgePerfect],
|
|
580
|
+
[BlendMode.linearDodge, linearDodgePerfect],
|
|
581
|
+
[BlendMode.lighterColor, lighterPerfect],
|
|
582
|
+
|
|
583
|
+
[BlendMode.overlay, overlayPerfect],
|
|
584
|
+
[BlendMode.softLight, softLightPerfect],
|
|
585
|
+
[BlendMode.hardLight, hardLightPerfect],
|
|
586
|
+
[BlendMode.vividLight, vividLightPerfect],
|
|
587
|
+
[BlendMode.linearLight, linearLightPerfect],
|
|
588
|
+
[BlendMode.pinLight, pinLightPerfect],
|
|
589
|
+
[BlendMode.hardMix, hardMixPerfect],
|
|
590
|
+
|
|
591
|
+
[BlendMode.difference, differencePerfect],
|
|
592
|
+
[BlendMode.exclusion, exclusionPerfect],
|
|
593
|
+
[BlendMode.subtract, subtractPerfect],
|
|
594
|
+
[BlendMode.divide, dividePerfect],
|
|
595
|
+
] as const
|
|
596
|
+
|
|
597
|
+
export type RegisteredPerfectBlender = typeof PERFECT_BLENDER_REGISTRY[number][1]
|
|
598
|
+
export type PerfectBlendModeIndex = number & { readonly __brandBlendModeIndex: unique symbol }
|
|
599
|
+
|
|
600
|
+
export const PERFECT_BLEND_MODES: BlendColor32[] = []
|
|
601
|
+
for (const [index, blend] of PERFECT_BLENDER_REGISTRY) {
|
|
602
|
+
PERFECT_BLEND_MODES[index as PerfectBlendModeIndex] = blend
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
export const PERFECT_BLEND_TO_INDEX = new Map(
|
|
606
|
+
PERFECT_BLENDER_REGISTRY.map((entry, index) => {
|
|
607
|
+
return [
|
|
608
|
+
entry[1],
|
|
609
|
+
index as PerfectBlendModeIndex,
|
|
610
|
+
]
|
|
611
|
+
}),
|
|
612
|
+
) as { get: (blend: RegisteredPerfectBlender) => PerfectBlendModeIndex }
|
|
613
|
+
|
|
614
|
+
export const INDEX_TO_PERFECT_BLEND = new Map(
|
|
615
|
+
PERFECT_BLENDER_REGISTRY.map((entry, index) => {
|
|
616
|
+
return [
|
|
617
|
+
index as PerfectBlendModeIndex,
|
|
618
|
+
entry[1],
|
|
619
|
+
]
|
|
620
|
+
}),
|
|
621
|
+
) as { get: (index: PerfectBlendModeIndex) => RegisteredPerfectBlender }
|
|
622
|
+
|
|
623
|
+
export type PerfectBlendModes = {
|
|
624
|
+
[K in keyof typeof BlendMode]: RegisteredPerfectBlender
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
export const PERFECT_BLEND_MODE_BY_NAME: PerfectBlendModes = {
|
|
628
|
+
overwrite: overwritePerfect,
|
|
629
|
+
sourceOver: sourceOverPerfect,
|
|
630
|
+
darken: darkenPerfect,
|
|
631
|
+
multiply: multiplyPerfect,
|
|
632
|
+
colorBurn: colorBurnPerfect,
|
|
633
|
+
linearBurn: linearBurnPerfect,
|
|
634
|
+
darkerColor: darkerPerfect,
|
|
635
|
+
lighten: lightenPerfect,
|
|
636
|
+
screen: screenPerfect,
|
|
637
|
+
colorDodge: colorDodgePerfect,
|
|
638
|
+
linearDodge: linearDodgePerfect,
|
|
639
|
+
lighterColor: lighterPerfect,
|
|
640
|
+
overlay: overlayPerfect,
|
|
641
|
+
softLight: softLightPerfect,
|
|
642
|
+
hardLight: hardLightPerfect,
|
|
643
|
+
vividLight: vividLightPerfect,
|
|
644
|
+
linearLight: linearLightPerfect,
|
|
645
|
+
pinLight: pinLightPerfect,
|
|
646
|
+
hardMix: hardMixPerfect,
|
|
647
|
+
difference: differencePerfect,
|
|
648
|
+
exclusion: exclusionPerfect,
|
|
649
|
+
subtract: subtractPerfect,
|
|
650
|
+
divide: dividePerfect,
|
|
651
|
+
} as const
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// The enum index IS the permanent ID.
|
|
2
|
+
// do not change the order, Adding to it is ok.
|
|
3
|
+
export enum BlendMode {
|
|
4
|
+
overwrite,
|
|
5
|
+
sourceOver,
|
|
6
|
+
|
|
7
|
+
darken,
|
|
8
|
+
multiply,
|
|
9
|
+
colorBurn,
|
|
10
|
+
linearBurn,
|
|
11
|
+
darkerColor,
|
|
12
|
+
|
|
13
|
+
lighten,
|
|
14
|
+
screen,
|
|
15
|
+
colorDodge,
|
|
16
|
+
linearDodge,
|
|
17
|
+
lighterColor,
|
|
18
|
+
|
|
19
|
+
overlay,
|
|
20
|
+
softLight,
|
|
21
|
+
hardLight,
|
|
22
|
+
vividLight,
|
|
23
|
+
linearLight,
|
|
24
|
+
pinLight,
|
|
25
|
+
hardMix,
|
|
26
|
+
|
|
27
|
+
difference,
|
|
28
|
+
exclusion,
|
|
29
|
+
subtract,
|
|
30
|
+
divide,
|
|
31
|
+
}
|