pixel-data-js 0.1.0 → 0.2.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 +225 -106
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +219 -106
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +225 -106
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +194 -99
- package/dist/index.prod.js +219 -106
- package/dist/index.prod.js.map +1 -1
- package/package.json +1 -1
- package/src/ImageData/blit.ts +64 -32
- package/src/ImageData/mask.ts +150 -0
- package/src/ImageData/read-write-pixels.ts +66 -1
- package/src/ImageData/serialization.ts +1 -1
- package/src/_types.ts +29 -9
- package/src/index.ts +5 -3
package/dist/index.prod.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ type BlendColor32 = (src: Color32, dst: Color32) => Color32;
|
|
|
11
11
|
type ImageDataLike = {
|
|
12
12
|
width: number;
|
|
13
13
|
height: number;
|
|
14
|
-
data: Uint8ClampedArray
|
|
14
|
+
data: Uint8ClampedArray<ArrayBuffer>;
|
|
15
15
|
};
|
|
16
16
|
type SerializedImageData = {
|
|
17
17
|
width: number;
|
|
@@ -21,103 +21,28 @@ type SerializedImageData = {
|
|
|
21
21
|
type Base64EncodedUInt8Array = string & {
|
|
22
22
|
readonly __brandBase64UInt8Array: unique symbol;
|
|
23
23
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
declare function packColor(r: number, g: number, b: number, a: number): Color32;
|
|
30
|
-
declare function packRGBA({ r, g, b, a }: RGBA): Color32;
|
|
31
|
-
declare const unpackRed: (packed: Color32) => number;
|
|
32
|
-
declare const unpackGreen: (packed: Color32) => number;
|
|
33
|
-
declare const unpackBlue: (packed: Color32) => number;
|
|
34
|
-
declare const unpackAlpha: (packed: Color32) => number;
|
|
35
|
-
declare function unpackColor(packed: Color32): RGBA;
|
|
36
|
-
declare function unpackColorTo(packed: Color32, scratch?: RGBA): RGBA;
|
|
37
|
-
declare function colorDistance(a: Color32, b: Color32): number;
|
|
38
|
-
/**
|
|
39
|
-
* Linearly interpolates between two 32-bit colors using a floating-point weight.
|
|
40
|
-
* * This is the preferred method for UI animations or scenarios where high
|
|
41
|
-
* precision is required. It uses the standard `a + t * (b - a)` formula
|
|
42
|
-
* for each channel.
|
|
43
|
-
* @param a - The starting color as a 32-bit integer (AABBGGRR).
|
|
44
|
-
* @param b - The target color as a 32-bit integer (AABBGGRR).
|
|
45
|
-
* @param t - The interpolation factor between 0.0 and 1.0.
|
|
46
|
-
* @returns The interpolated 32-bit color.
|
|
47
|
-
*/
|
|
48
|
-
declare function lerpColor32(a: Color32, b: Color32, t: number): Color32;
|
|
49
|
-
/**
|
|
50
|
-
* Linearly interpolates between two 32-bit colors using integer fixed-point math.
|
|
51
|
-
* Highly optimized for image processing and real-time blitting. It processes
|
|
52
|
-
* channels in parallel using bitmasks (RB and GA pairs).
|
|
53
|
-
* @note Subject to a 1-bit drift (rounding down) due to fast bit-shift division.
|
|
54
|
-
* @param src - The source (foreground) color as a 32-bit integer.
|
|
55
|
-
* @param dst - The destination (background) color as a 32-bit integer.
|
|
56
|
-
* @param w - The blend weight as a byte value from 0 to 255. Where 0 is 100% dst and 255 is 100% src
|
|
57
|
-
* @returns The blended 32-bit color.
|
|
58
|
-
*/ declare function lerpColor32Fast(src: Color32, dst: Color32, w: number): Color32;
|
|
59
|
-
declare function color32ToHex(color: Color32): string;
|
|
60
|
-
/**
|
|
61
|
-
* Converts a 32-bit integer (0xAABBGGRR) to a CSS rgba() string.
|
|
62
|
-
* Example: 0xFF0000FF -> "rgba(255,0,0,1)"
|
|
63
|
-
*/
|
|
64
|
-
declare function color32ToCssRGBA(color: Color32): string;
|
|
65
|
-
|
|
66
|
-
declare function base64EncodeArrayBuffer(buffer: ArrayBufferLike): Base64EncodedUInt8Array;
|
|
67
|
-
declare function base64DecodeArrayBuffer(encoded: Base64EncodedUInt8Array): Uint8ClampedArray;
|
|
68
|
-
/**
|
|
69
|
-
* Serialize for use in JSON. Pixel data is stored as base64 encoded string.
|
|
70
|
-
*/
|
|
71
|
-
declare function serializeImageData<T extends ImageDataLike>(imageData: T): SerializedImageData;
|
|
72
|
-
declare function serializeNullableImageData<T extends ImageDataLike | null>(imageData: T): T extends null ? null : SerializedImageData;
|
|
73
|
-
declare function deserializeRawImageData<T extends SerializedImageData>(serialized: T): ImageDataLike;
|
|
74
|
-
declare function deserializeImageData<T extends SerializedImageData>(serialized: T): ImageData;
|
|
75
|
-
declare function deserializeNullableImageData<T extends SerializedImageData | null>(serialized: T): T extends null ? null : ImageData;
|
|
76
|
-
|
|
77
|
-
type BlendImageDataOptions = {
|
|
78
|
-
dx?: number;
|
|
79
|
-
dy?: number;
|
|
80
|
-
sx?: number;
|
|
81
|
-
sy?: number;
|
|
82
|
-
sw?: number;
|
|
83
|
-
sh?: number;
|
|
84
|
-
opacity?: number;
|
|
85
|
-
alpha?: number;
|
|
86
|
-
mask?: Uint8Array | null;
|
|
87
|
-
maskMode?: 'binary' | 'alpha';
|
|
88
|
-
blendFn?: BlendColor32;
|
|
24
|
+
type Rect = {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
w: number;
|
|
28
|
+
h: number;
|
|
89
29
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
* @param opts.alpha - Global strength of the blit (0 to 255). Overrides 'opacity' if provided.
|
|
107
|
-
* @param opts.mask - An optional Uint8Array acting as a stencil or alpha mask.
|
|
108
|
-
* Must match source dimensions.
|
|
109
|
-
* @param opts.maskMode - 'binary' ignores pixels where mask is 0.
|
|
110
|
-
* 'alpha' scales source alpha by mask value (0-255).
|
|
111
|
-
* @param opts.blendFn - The math logic used to combine pixels.
|
|
112
|
-
* Defaults to `sourceOverColor32`.
|
|
113
|
-
* * @example
|
|
114
|
-
* blendImageData32(ctx.getImageData(0,0,100,100), sprite, {
|
|
115
|
-
* blendFn: COLOR_32_BLEND_MODES.multiply,
|
|
116
|
-
* mask: brushMask,
|
|
117
|
-
* maskMode: 'alpha'
|
|
118
|
-
* });
|
|
119
|
-
*/
|
|
120
|
-
declare function blendImageData(dst: ImageData, src: ImageData, opts: BlendImageDataOptions): void;
|
|
30
|
+
declare enum MaskType {
|
|
31
|
+
ALPHA = 0,
|
|
32
|
+
BINARY = 1
|
|
33
|
+
}
|
|
34
|
+
interface BaseMaskData {
|
|
35
|
+
readonly width: number;
|
|
36
|
+
readonly height: number;
|
|
37
|
+
readonly data: Uint8Array;
|
|
38
|
+
}
|
|
39
|
+
interface AlphaMask extends BaseMaskData {
|
|
40
|
+
readonly type: MaskType.ALPHA;
|
|
41
|
+
}
|
|
42
|
+
interface BinaryMask extends BaseMaskData {
|
|
43
|
+
readonly type: MaskType.BINARY;
|
|
44
|
+
}
|
|
45
|
+
type AnyMask = AlphaMask | BinaryMask;
|
|
121
46
|
|
|
122
47
|
declare const sourceOverColor32: BlendColor32;
|
|
123
48
|
/**
|
|
@@ -166,12 +91,182 @@ declare const COLOR_32_BLEND_MODES: {
|
|
|
166
91
|
colorBurn: BlendColor32;
|
|
167
92
|
};
|
|
168
93
|
|
|
94
|
+
type BlendImageDataOptions = {
|
|
95
|
+
/**
|
|
96
|
+
* The x-coordinate in the destination image where the blend begins.
|
|
97
|
+
* @default 0
|
|
98
|
+
*/
|
|
99
|
+
dx?: number;
|
|
100
|
+
/**
|
|
101
|
+
* The y-coordinate in the destination image where the blend begins.
|
|
102
|
+
* @default 0
|
|
103
|
+
*/
|
|
104
|
+
dy?: number;
|
|
105
|
+
/**
|
|
106
|
+
* The x-coordinate of the top-left corner of the sub-rectangle
|
|
107
|
+
* of the source image to extract.
|
|
108
|
+
* @default 0
|
|
109
|
+
*/
|
|
110
|
+
sx?: number;
|
|
111
|
+
/**
|
|
112
|
+
* The y-coordinate of the top-left corner of the sub-rectangle
|
|
113
|
+
* of the source image to extract.
|
|
114
|
+
* @default 0
|
|
115
|
+
*/
|
|
116
|
+
sy?: number;
|
|
117
|
+
/**
|
|
118
|
+
* The width of the sub-rectangle of the source image to extract.
|
|
119
|
+
* Defaults to the full remaining width of the source.
|
|
120
|
+
*/
|
|
121
|
+
sw?: number;
|
|
122
|
+
/**
|
|
123
|
+
* The height of the sub-rectangle of the source image to extract.
|
|
124
|
+
* Defaults to the full remaining height of the source.
|
|
125
|
+
*/
|
|
126
|
+
sh?: number;
|
|
127
|
+
/**
|
|
128
|
+
* Overall layer opacity, typically ranging from 0.0 (transparent) to 1.0 (opaque).
|
|
129
|
+
* @default 1.0
|
|
130
|
+
*/
|
|
131
|
+
opacity?: number;
|
|
132
|
+
/**
|
|
133
|
+
* Same as opacity but is 0-255 and faster when processing. If Present opacity is ignored.
|
|
134
|
+
* @default undefined
|
|
135
|
+
*/
|
|
136
|
+
alpha?: number;
|
|
137
|
+
/**
|
|
138
|
+
* An optional alpha mask buffer.
|
|
139
|
+
* The values in this array (0-255) determine the intensity of the blend
|
|
140
|
+
* at each corresponding pixel.
|
|
141
|
+
*/
|
|
142
|
+
mask?: AnyMask | null;
|
|
143
|
+
/**
|
|
144
|
+
* The specific blending function/algorithm to use for pixel math
|
|
145
|
+
* (e.g., Multiply, Screen, Overlay).
|
|
146
|
+
*/
|
|
147
|
+
blendFn?: BlendColor32;
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Blits source ImageData into a destination ImageData using 32-bit integer bitwise blending.
|
|
151
|
+
* This function bypasses standard Canvas API limitations by operating directly on
|
|
152
|
+
* Uint32Array views. It supports various blend modes, binary/alpha masking, and
|
|
153
|
+
* automatic clipping of both source and destination bounds.
|
|
154
|
+
* @example
|
|
155
|
+
* blendImageData32(ctx.getImageData(0,0,100,100), sprite, {
|
|
156
|
+
* blendFn: COLOR_32_BLEND_MODES.multiply,
|
|
157
|
+
* mask: brushMask,
|
|
158
|
+
* maskMode: MaskMode.ALPHA
|
|
159
|
+
* });
|
|
160
|
+
*/
|
|
161
|
+
declare function blendImageData(dst: ImageDataLike, src: ImageDataLike, opts: BlendImageDataOptions): void;
|
|
162
|
+
|
|
163
|
+
type ApplyMaskOptions = {
|
|
164
|
+
/**
|
|
165
|
+
* The x-coordinate in the destination image where the mask begins.
|
|
166
|
+
* @default 0
|
|
167
|
+
*/
|
|
168
|
+
dx?: number;
|
|
169
|
+
/**
|
|
170
|
+
* The y-coordinate in the destination image where the mask begins.
|
|
171
|
+
* @default 0
|
|
172
|
+
*/
|
|
173
|
+
dy?: number;
|
|
174
|
+
/**
|
|
175
|
+
* The x-coordinate of the top-left corner of the sub-rectangle
|
|
176
|
+
* of the source image to extract.
|
|
177
|
+
* @default 0
|
|
178
|
+
*/
|
|
179
|
+
sx?: number;
|
|
180
|
+
/**
|
|
181
|
+
* The y-coordinate of the top-left corner of the sub-rectangle
|
|
182
|
+
* of the source image to extract.
|
|
183
|
+
* @default 0
|
|
184
|
+
*/
|
|
185
|
+
sy?: number;
|
|
186
|
+
/**
|
|
187
|
+
* The width of the sub-rectangle of the source image to extract.
|
|
188
|
+
* Defaults to the full remaining width of the source.
|
|
189
|
+
*/
|
|
190
|
+
sw?: number;
|
|
191
|
+
/**
|
|
192
|
+
* The height of the sub-rectangle of the source image to extract.
|
|
193
|
+
* Defaults to the full remaining height of the source.
|
|
194
|
+
*/
|
|
195
|
+
sh?: number;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Applies a binary (on/off) mask to an RGBA buffer.
|
|
199
|
+
* If mask value is 0, pixel becomes transparent.
|
|
200
|
+
*/
|
|
201
|
+
declare function applyBinaryMask(dst: ImageDataLike, mask: BinaryMask, opts?: ApplyMaskOptions): ImageDataLike | undefined;
|
|
202
|
+
/**
|
|
203
|
+
* Applies a smooth alpha mask to an RGBA buffer.
|
|
204
|
+
* Multiplies existing Alpha by (maskValue / 255).
|
|
205
|
+
*/
|
|
206
|
+
declare function applyAlphaMask(dst: ImageData, mask: AlphaMask, opts?: ApplyMaskOptions): void;
|
|
207
|
+
|
|
169
208
|
declare function makeImageDataColor32Adapter(imageData: ImageDataLike): {
|
|
170
209
|
inBounds: (x: number, y: number) => boolean;
|
|
171
210
|
imageData: ImageDataLike;
|
|
172
|
-
data32: Uint32Array<
|
|
211
|
+
data32: Uint32Array<ArrayBuffer>;
|
|
173
212
|
setPixel: (x: number, y: number, color: Color32) => void;
|
|
174
213
|
getPixel: (x: number, y: number) => Color32 | undefined;
|
|
175
214
|
};
|
|
215
|
+
declare function extractPixelData(imageData: ImageDataLike, rect: Rect): Uint8ClampedArray;
|
|
216
|
+
declare function extractPixelData(imageData: ImageDataLike, x: number, y: number, w: number, h: number): Uint8ClampedArray;
|
|
217
|
+
declare function copyImageData({ data, width, height }: ImageDataLike): ImageData;
|
|
218
|
+
declare function copyImageDataLike({ data, width, height }: ImageDataLike): ImageDataLike;
|
|
219
|
+
|
|
220
|
+
declare function base64EncodeArrayBuffer(buffer: ArrayBufferLike): Base64EncodedUInt8Array;
|
|
221
|
+
declare function base64DecodeArrayBuffer(encoded: Base64EncodedUInt8Array): Uint8ClampedArray<ArrayBuffer>;
|
|
222
|
+
/**
|
|
223
|
+
* Serialize for use in JSON. Pixel data is stored as base64 encoded string.
|
|
224
|
+
*/
|
|
225
|
+
declare function serializeImageData<T extends ImageDataLike>(imageData: T): SerializedImageData;
|
|
226
|
+
declare function serializeNullableImageData<T extends ImageDataLike | null>(imageData: T): T extends null ? null : SerializedImageData;
|
|
227
|
+
declare function deserializeRawImageData<T extends SerializedImageData>(serialized: T): ImageDataLike;
|
|
228
|
+
declare function deserializeImageData<T extends SerializedImageData>(serialized: T): ImageData;
|
|
229
|
+
declare function deserializeNullableImageData<T extends SerializedImageData | null>(serialized: T): T extends null ? null : ImageData;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Packs RGBA into a 32-bit integer compatible with
|
|
233
|
+
* Little-Endian Uint32Array views on ImageData.
|
|
234
|
+
*/
|
|
235
|
+
declare function packColor(r: number, g: number, b: number, a: number): Color32;
|
|
236
|
+
declare function packRGBA({ r, g, b, a }: RGBA): Color32;
|
|
237
|
+
declare const unpackRed: (packed: Color32) => number;
|
|
238
|
+
declare const unpackGreen: (packed: Color32) => number;
|
|
239
|
+
declare const unpackBlue: (packed: Color32) => number;
|
|
240
|
+
declare const unpackAlpha: (packed: Color32) => number;
|
|
241
|
+
declare function unpackColor(packed: Color32): RGBA;
|
|
242
|
+
declare function unpackColorTo(packed: Color32, scratch?: RGBA): RGBA;
|
|
243
|
+
declare function colorDistance(a: Color32, b: Color32): number;
|
|
244
|
+
/**
|
|
245
|
+
* Linearly interpolates between two 32-bit colors using a floating-point weight.
|
|
246
|
+
* * This is the preferred method for UI animations or scenarios where high
|
|
247
|
+
* precision is required. It uses the standard `a + t * (b - a)` formula
|
|
248
|
+
* for each channel.
|
|
249
|
+
* @param a - The starting color as a 32-bit integer (AABBGGRR).
|
|
250
|
+
* @param b - The target color as a 32-bit integer (AABBGGRR).
|
|
251
|
+
* @param t - The interpolation factor between 0.0 and 1.0.
|
|
252
|
+
* @returns The interpolated 32-bit color.
|
|
253
|
+
*/
|
|
254
|
+
declare function lerpColor32(a: Color32, b: Color32, t: number): Color32;
|
|
255
|
+
/**
|
|
256
|
+
* Linearly interpolates between two 32-bit colors using integer fixed-point math.
|
|
257
|
+
* Highly optimized for image processing and real-time blitting. It processes
|
|
258
|
+
* channels in parallel using bitmasks (RB and GA pairs).
|
|
259
|
+
* @note Subject to a 1-bit drift (rounding down) due to fast bit-shift division.
|
|
260
|
+
* @param src - The source (foreground) color as a 32-bit integer.
|
|
261
|
+
* @param dst - The destination (background) color as a 32-bit integer.
|
|
262
|
+
* @param w - The blend weight as a byte value from 0 to 255. Where 0 is 100% dst and 255 is 100% src
|
|
263
|
+
* @returns The blended 32-bit color.
|
|
264
|
+
*/ declare function lerpColor32Fast(src: Color32, dst: Color32, w: number): Color32;
|
|
265
|
+
declare function color32ToHex(color: Color32): string;
|
|
266
|
+
/**
|
|
267
|
+
* Converts a 32-bit integer (0xAABBGGRR) to a CSS rgba() string.
|
|
268
|
+
* Example: 0xFF0000FF -> "rgba(255,0,0,1)"
|
|
269
|
+
*/
|
|
270
|
+
declare function color32ToCssRGBA(color: Color32): string;
|
|
176
271
|
|
|
177
|
-
export { type BlendImageDataOptions, COLOR_32_BLEND_MODES, base64DecodeArrayBuffer, base64EncodeArrayBuffer, blendImageData, color32ToCssRGBA, color32ToHex, colorBurnColor32, colorDistance, deserializeImageData, deserializeNullableImageData, deserializeRawImageData, differenceColor32, hardLightColor32, lerpColor32, lerpColor32Fast, linearDodgeColor32, makeImageDataColor32Adapter, multiplyColor32, overlayColor32, packColor, packRGBA, screenColor32, serializeImageData, serializeNullableImageData, sourceOverColor32, unpackAlpha, unpackBlue, unpackColor, unpackColorTo, unpackGreen, unpackRed };
|
|
272
|
+
export { type AlphaMask, type AnyMask, type ApplyMaskOptions, type Base64EncodedUInt8Array, type BinaryMask, type BlendColor32, type BlendImageDataOptions, COLOR_32_BLEND_MODES, type Color32, type ImageDataLike, MaskType, type RGBA, type Rect, type SerializedImageData, applyAlphaMask, applyBinaryMask, base64DecodeArrayBuffer, base64EncodeArrayBuffer, blendImageData, color32ToCssRGBA, color32ToHex, colorBurnColor32, colorDistance, copyImageData, copyImageDataLike, deserializeImageData, deserializeNullableImageData, deserializeRawImageData, differenceColor32, extractPixelData, hardLightColor32, lerpColor32, lerpColor32Fast, linearDodgeColor32, makeImageDataColor32Adapter, multiplyColor32, overlayColor32, packColor, packRGBA, screenColor32, serializeImageData, serializeNullableImageData, sourceOverColor32, unpackAlpha, unpackBlue, unpackColor, unpackColorTo, unpackGreen, unpackRed };
|
package/dist/index.prod.js
CHANGED
|
@@ -1,106 +1,3 @@
|
|
|
1
|
-
// src/color.ts
|
|
2
|
-
function packColor(r, g, b, a) {
|
|
3
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
4
|
-
}
|
|
5
|
-
function packRGBA({ r, g, b, a }) {
|
|
6
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
7
|
-
}
|
|
8
|
-
var unpackRed = (packed) => packed >>> 0 & 255;
|
|
9
|
-
var unpackGreen = (packed) => packed >>> 8 & 255;
|
|
10
|
-
var unpackBlue = (packed) => packed >>> 16 & 255;
|
|
11
|
-
var unpackAlpha = (packed) => packed >>> 24 & 255;
|
|
12
|
-
function unpackColor(packed) {
|
|
13
|
-
return {
|
|
14
|
-
r: packed >>> 0 & 255,
|
|
15
|
-
g: packed >>> 8 & 255,
|
|
16
|
-
b: packed >>> 16 & 255,
|
|
17
|
-
a: packed >>> 24 & 255
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
|
|
21
|
-
function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
|
|
22
|
-
scratch.r = packed >>> 0 & 255;
|
|
23
|
-
scratch.g = packed >>> 8 & 255;
|
|
24
|
-
scratch.b = packed >>> 16 & 255;
|
|
25
|
-
scratch.a = packed >>> 24 & 255;
|
|
26
|
-
return scratch;
|
|
27
|
-
}
|
|
28
|
-
function colorDistance(a, b) {
|
|
29
|
-
const dr = (a & 255) - (b & 255);
|
|
30
|
-
const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
|
|
31
|
-
const db = (a >>> 16 & 255) - (b >>> 16 & 255);
|
|
32
|
-
const da = (a >>> 24 & 255) - (b >>> 24 & 255);
|
|
33
|
-
return dr * dr + dg * dg + db * db + da * da;
|
|
34
|
-
}
|
|
35
|
-
function lerpColor32(a, b, t) {
|
|
36
|
-
const r = (a & 255) + t * ((b & 255) - (a & 255));
|
|
37
|
-
const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
|
|
38
|
-
const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
|
|
39
|
-
const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
|
|
40
|
-
return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
|
|
41
|
-
}
|
|
42
|
-
function lerpColor32Fast(src, dst, w) {
|
|
43
|
-
const invA = 255 - w;
|
|
44
|
-
const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
|
|
45
|
-
const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
|
|
46
|
-
return (rb | ga << 8) >>> 0;
|
|
47
|
-
}
|
|
48
|
-
function color32ToHex(color) {
|
|
49
|
-
const r = (color & 255).toString(16).padStart(2, "0");
|
|
50
|
-
const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
|
|
51
|
-
const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
|
|
52
|
-
const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
|
|
53
|
-
return `#${r}${g}${b}${a}`;
|
|
54
|
-
}
|
|
55
|
-
function color32ToCssRGBA(color) {
|
|
56
|
-
const r = color & 255;
|
|
57
|
-
const g = color >>> 8 & 255;
|
|
58
|
-
const b = color >>> 16 & 255;
|
|
59
|
-
const a = color >>> 24 & 255;
|
|
60
|
-
const alpha = Number((a / 255).toFixed(3));
|
|
61
|
-
return `rgba(${r},${g},${b},${alpha})`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// src/ImageData/serialization.ts
|
|
65
|
-
function base64EncodeArrayBuffer(buffer) {
|
|
66
|
-
const binary = String.fromCharCode(...new Uint8Array(buffer));
|
|
67
|
-
return btoa(binary);
|
|
68
|
-
}
|
|
69
|
-
function base64DecodeArrayBuffer(encoded) {
|
|
70
|
-
const binary = atob(encoded);
|
|
71
|
-
const bytes = new Uint8ClampedArray(binary.length);
|
|
72
|
-
for (let i = 0; i < binary.length; i++) {
|
|
73
|
-
bytes[i] = binary.charCodeAt(i);
|
|
74
|
-
}
|
|
75
|
-
return bytes;
|
|
76
|
-
}
|
|
77
|
-
function serializeImageData(imageData) {
|
|
78
|
-
return {
|
|
79
|
-
width: imageData.width,
|
|
80
|
-
height: imageData.height,
|
|
81
|
-
data: base64EncodeArrayBuffer(imageData.data.buffer)
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function serializeNullableImageData(imageData) {
|
|
85
|
-
if (!imageData) return null;
|
|
86
|
-
return serializeImageData(imageData);
|
|
87
|
-
}
|
|
88
|
-
function deserializeRawImageData(serialized) {
|
|
89
|
-
return {
|
|
90
|
-
width: serialized.width,
|
|
91
|
-
height: serialized.height,
|
|
92
|
-
data: base64DecodeArrayBuffer(serialized.data)
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
function deserializeImageData(serialized) {
|
|
96
|
-
const data = base64DecodeArrayBuffer(serialized.data);
|
|
97
|
-
return new ImageData(data, serialized.width, serialized.height);
|
|
98
|
-
}
|
|
99
|
-
function deserializeNullableImageData(serialized) {
|
|
100
|
-
if (!serialized) return null;
|
|
101
|
-
return deserializeImageData(serialized);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
1
|
// src/ImageData/blend-modes.ts
|
|
105
2
|
var sourceOverColor32 = (src, dst) => {
|
|
106
3
|
const a = src >>> 24 & 255;
|
|
@@ -237,6 +134,13 @@ var COLOR_32_BLEND_MODES = {
|
|
|
237
134
|
colorBurn: colorBurnColor32
|
|
238
135
|
};
|
|
239
136
|
|
|
137
|
+
// src/_types.ts
|
|
138
|
+
var MaskType = /* @__PURE__ */ ((MaskType2) => {
|
|
139
|
+
MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
|
|
140
|
+
MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
|
|
141
|
+
return MaskType2;
|
|
142
|
+
})(MaskType || {});
|
|
143
|
+
|
|
240
144
|
// src/ImageData/blit.ts
|
|
241
145
|
function blendImageData(dst, src, opts) {
|
|
242
146
|
let {
|
|
@@ -246,7 +150,6 @@ function blendImageData(dst, src, opts) {
|
|
|
246
150
|
sy = 0,
|
|
247
151
|
sw = src.width,
|
|
248
152
|
sh = src.height,
|
|
249
|
-
maskMode = "alpha",
|
|
250
153
|
opacity = 1,
|
|
251
154
|
alpha,
|
|
252
155
|
blendFn = sourceOverColor32,
|
|
@@ -282,7 +185,7 @@ function blendImageData(dst, src, opts) {
|
|
|
282
185
|
const dw = dst.width;
|
|
283
186
|
const sw_orig = src.width;
|
|
284
187
|
const gAlpha = alpha !== void 0 ? alpha | 0 : Math.round(opacity * 255);
|
|
285
|
-
const maskIsAlpha =
|
|
188
|
+
const maskIsAlpha = mask?.type === 0 /* ALPHA */;
|
|
286
189
|
for (let iy = 0; iy < actualH; iy++) {
|
|
287
190
|
const dRow = (iy + dy) * dw;
|
|
288
191
|
const sRow = (iy + sy) * sw_orig;
|
|
@@ -294,7 +197,7 @@ function blendImageData(dst, src, opts) {
|
|
|
294
197
|
if (sa === 0) continue;
|
|
295
198
|
let activeWeight = gAlpha;
|
|
296
199
|
if (mask) {
|
|
297
|
-
const m = mask[si];
|
|
200
|
+
const m = mask.data[si];
|
|
298
201
|
if (m === 0) continue;
|
|
299
202
|
activeWeight = maskIsAlpha ? m * activeWeight + 128 >> 8 : activeWeight;
|
|
300
203
|
}
|
|
@@ -308,6 +211,76 @@ function blendImageData(dst, src, opts) {
|
|
|
308
211
|
}
|
|
309
212
|
}
|
|
310
213
|
|
|
214
|
+
// src/ImageData/mask.ts
|
|
215
|
+
function applyBinaryMask(dst, mask, opts = {}) {
|
|
216
|
+
const { width: maskWidth, height: maskHeight } = mask;
|
|
217
|
+
const { dx = 0, dy = 0, sx = 0, sy = 0, sw = maskWidth, sh = maskHeight } = opts;
|
|
218
|
+
const x0 = Math.max(0, dx, dx + (0 - sx));
|
|
219
|
+
const y0 = Math.max(0, dy, dy + (0 - sy));
|
|
220
|
+
const x1 = Math.min(dst.width, dx + sw, dx + (maskWidth - sx));
|
|
221
|
+
const y1 = Math.min(dst.height, dy + sh, dy + (maskHeight - sy));
|
|
222
|
+
if (x1 <= x0 || y1 <= y0) return;
|
|
223
|
+
const { data: dstData, width: dstW } = dst;
|
|
224
|
+
for (let y = y0; y < y1; y++) {
|
|
225
|
+
const maskY = y - dy + sy;
|
|
226
|
+
const dstRowOffset = y * dstW * 4;
|
|
227
|
+
const maskRowOffset = maskY * maskWidth;
|
|
228
|
+
for (let x = x0; x < x1; x++) {
|
|
229
|
+
const maskX = x - dx + sx;
|
|
230
|
+
const mIdx = maskRowOffset + maskX;
|
|
231
|
+
if (mask.data[mIdx] === 0) {
|
|
232
|
+
const aIdx = dstRowOffset + x * 4 + 3;
|
|
233
|
+
dstData[aIdx] = 0;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return dst;
|
|
238
|
+
}
|
|
239
|
+
function applyAlphaMask(dst, mask, opts = {}) {
|
|
240
|
+
let { dx = 0, dy = 0, sx = 0, sy = 0, sw = mask.width, sh = mask.height } = opts;
|
|
241
|
+
if (dx < 0) {
|
|
242
|
+
sx -= dx;
|
|
243
|
+
sw += dx;
|
|
244
|
+
dx = 0;
|
|
245
|
+
}
|
|
246
|
+
if (dy < 0) {
|
|
247
|
+
sy -= dy;
|
|
248
|
+
sh += dy;
|
|
249
|
+
dy = 0;
|
|
250
|
+
}
|
|
251
|
+
if (sx < 0) {
|
|
252
|
+
dx -= sx;
|
|
253
|
+
sw += sx;
|
|
254
|
+
sx = 0;
|
|
255
|
+
}
|
|
256
|
+
if (sy < 0) {
|
|
257
|
+
dy -= sy;
|
|
258
|
+
sh += sy;
|
|
259
|
+
sy = 0;
|
|
260
|
+
}
|
|
261
|
+
const actualW = Math.min(sw, dst.width - dx, mask.width - sx);
|
|
262
|
+
const actualH = Math.min(sh, dst.height - dy, mask.height - sy);
|
|
263
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
264
|
+
const dData = dst.data;
|
|
265
|
+
const mData = mask.data;
|
|
266
|
+
const dW = dst.width;
|
|
267
|
+
const mW = mask.width;
|
|
268
|
+
for (let y = 0; y < actualH; y++) {
|
|
269
|
+
const dOffset = (dy + y) * dW + dx << 2;
|
|
270
|
+
const mOffset = (sy + y) * mW + sx;
|
|
271
|
+
for (let x = 0; x < actualW; x++) {
|
|
272
|
+
const mVal = mData[mOffset + x];
|
|
273
|
+
if (mVal === 255) continue;
|
|
274
|
+
const aIdx = dOffset + (x << 2) + 3;
|
|
275
|
+
if (mVal === 0) {
|
|
276
|
+
dData[aIdx] = 0;
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
dData[aIdx] = dData[aIdx] * mVal + 257 >> 8;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
311
284
|
// src/ImageData/read-write-pixels.ts
|
|
312
285
|
function makeImageDataColor32Adapter(imageData) {
|
|
313
286
|
const data32 = new Uint32Array(imageData.data.buffer);
|
|
@@ -330,8 +303,145 @@ function makeImageDataColor32Adapter(imageData) {
|
|
|
330
303
|
getPixel
|
|
331
304
|
};
|
|
332
305
|
}
|
|
306
|
+
function extractPixelData(imageData, _x, _y, _w, _h) {
|
|
307
|
+
const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
|
|
308
|
+
const { width: srcW, height: srcH, data: src } = imageData;
|
|
309
|
+
if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
|
|
310
|
+
const out = new Uint8ClampedArray(w * h * 4);
|
|
311
|
+
const x0 = Math.max(0, x);
|
|
312
|
+
const y0 = Math.max(0, y);
|
|
313
|
+
const x1 = Math.min(srcW, x + w);
|
|
314
|
+
const y1 = Math.min(srcH, y + h);
|
|
315
|
+
if (x1 <= x0 || y1 <= y0) return out;
|
|
316
|
+
for (let row = 0; row < y1 - y0; row++) {
|
|
317
|
+
const srcRow = y0 + row;
|
|
318
|
+
const srcStart = (srcRow * srcW + x0) * 4;
|
|
319
|
+
const rowLen = (x1 - x0) * 4;
|
|
320
|
+
const dstRow = y0 - y + row;
|
|
321
|
+
const dstCol = x0 - x;
|
|
322
|
+
const dstStart = (dstRow * w + dstCol) * 4;
|
|
323
|
+
out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
324
|
+
}
|
|
325
|
+
return out;
|
|
326
|
+
}
|
|
327
|
+
function copyImageData({ data, width, height }) {
|
|
328
|
+
return new ImageData(data.slice(), width, height);
|
|
329
|
+
}
|
|
330
|
+
function copyImageDataLike({ data, width, height }) {
|
|
331
|
+
return {
|
|
332
|
+
data: data.slice(),
|
|
333
|
+
width,
|
|
334
|
+
height
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/ImageData/serialization.ts
|
|
339
|
+
function base64EncodeArrayBuffer(buffer) {
|
|
340
|
+
const binary = String.fromCharCode(...new Uint8Array(buffer));
|
|
341
|
+
return btoa(binary);
|
|
342
|
+
}
|
|
343
|
+
function base64DecodeArrayBuffer(encoded) {
|
|
344
|
+
const binary = atob(encoded);
|
|
345
|
+
const bytes = new Uint8ClampedArray(binary.length);
|
|
346
|
+
for (let i = 0; i < binary.length; i++) {
|
|
347
|
+
bytes[i] = binary.charCodeAt(i);
|
|
348
|
+
}
|
|
349
|
+
return bytes;
|
|
350
|
+
}
|
|
351
|
+
function serializeImageData(imageData) {
|
|
352
|
+
return {
|
|
353
|
+
width: imageData.width,
|
|
354
|
+
height: imageData.height,
|
|
355
|
+
data: base64EncodeArrayBuffer(imageData.data.buffer)
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function serializeNullableImageData(imageData) {
|
|
359
|
+
if (!imageData) return null;
|
|
360
|
+
return serializeImageData(imageData);
|
|
361
|
+
}
|
|
362
|
+
function deserializeRawImageData(serialized) {
|
|
363
|
+
return {
|
|
364
|
+
width: serialized.width,
|
|
365
|
+
height: serialized.height,
|
|
366
|
+
data: base64DecodeArrayBuffer(serialized.data)
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
function deserializeImageData(serialized) {
|
|
370
|
+
const data = base64DecodeArrayBuffer(serialized.data);
|
|
371
|
+
return new ImageData(data, serialized.width, serialized.height);
|
|
372
|
+
}
|
|
373
|
+
function deserializeNullableImageData(serialized) {
|
|
374
|
+
if (!serialized) return null;
|
|
375
|
+
return deserializeImageData(serialized);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/color.ts
|
|
379
|
+
function packColor(r, g, b, a) {
|
|
380
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
381
|
+
}
|
|
382
|
+
function packRGBA({ r, g, b, a }) {
|
|
383
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
384
|
+
}
|
|
385
|
+
var unpackRed = (packed) => packed >>> 0 & 255;
|
|
386
|
+
var unpackGreen = (packed) => packed >>> 8 & 255;
|
|
387
|
+
var unpackBlue = (packed) => packed >>> 16 & 255;
|
|
388
|
+
var unpackAlpha = (packed) => packed >>> 24 & 255;
|
|
389
|
+
function unpackColor(packed) {
|
|
390
|
+
return {
|
|
391
|
+
r: packed >>> 0 & 255,
|
|
392
|
+
g: packed >>> 8 & 255,
|
|
393
|
+
b: packed >>> 16 & 255,
|
|
394
|
+
a: packed >>> 24 & 255
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
|
|
398
|
+
function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
|
|
399
|
+
scratch.r = packed >>> 0 & 255;
|
|
400
|
+
scratch.g = packed >>> 8 & 255;
|
|
401
|
+
scratch.b = packed >>> 16 & 255;
|
|
402
|
+
scratch.a = packed >>> 24 & 255;
|
|
403
|
+
return scratch;
|
|
404
|
+
}
|
|
405
|
+
function colorDistance(a, b) {
|
|
406
|
+
const dr = (a & 255) - (b & 255);
|
|
407
|
+
const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
|
|
408
|
+
const db = (a >>> 16 & 255) - (b >>> 16 & 255);
|
|
409
|
+
const da = (a >>> 24 & 255) - (b >>> 24 & 255);
|
|
410
|
+
return dr * dr + dg * dg + db * db + da * da;
|
|
411
|
+
}
|
|
412
|
+
function lerpColor32(a, b, t) {
|
|
413
|
+
const r = (a & 255) + t * ((b & 255) - (a & 255));
|
|
414
|
+
const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
|
|
415
|
+
const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
|
|
416
|
+
const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
|
|
417
|
+
return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
|
|
418
|
+
}
|
|
419
|
+
function lerpColor32Fast(src, dst, w) {
|
|
420
|
+
const invA = 255 - w;
|
|
421
|
+
const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
|
|
422
|
+
const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
|
|
423
|
+
return (rb | ga << 8) >>> 0;
|
|
424
|
+
}
|
|
425
|
+
function color32ToHex(color) {
|
|
426
|
+
const r = (color & 255).toString(16).padStart(2, "0");
|
|
427
|
+
const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
|
|
428
|
+
const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
|
|
429
|
+
const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
|
|
430
|
+
return `#${r}${g}${b}${a}`;
|
|
431
|
+
}
|
|
432
|
+
function color32ToCssRGBA(color) {
|
|
433
|
+
const r = color & 255;
|
|
434
|
+
const g = color >>> 8 & 255;
|
|
435
|
+
const b = color >>> 16 & 255;
|
|
436
|
+
const a = color >>> 24 & 255;
|
|
437
|
+
const alpha = Number((a / 255).toFixed(3));
|
|
438
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
439
|
+
}
|
|
333
440
|
export {
|
|
334
441
|
COLOR_32_BLEND_MODES,
|
|
442
|
+
MaskType,
|
|
443
|
+
applyAlphaMask,
|
|
444
|
+
applyBinaryMask,
|
|
335
445
|
base64DecodeArrayBuffer,
|
|
336
446
|
base64EncodeArrayBuffer,
|
|
337
447
|
blendImageData,
|
|
@@ -339,10 +449,13 @@ export {
|
|
|
339
449
|
color32ToHex,
|
|
340
450
|
colorBurnColor32,
|
|
341
451
|
colorDistance,
|
|
452
|
+
copyImageData,
|
|
453
|
+
copyImageDataLike,
|
|
342
454
|
deserializeImageData,
|
|
343
455
|
deserializeNullableImageData,
|
|
344
456
|
deserializeRawImageData,
|
|
345
457
|
differenceColor32,
|
|
458
|
+
extractPixelData,
|
|
346
459
|
hardLightColor32,
|
|
347
460
|
lerpColor32,
|
|
348
461
|
lerpColor32Fast,
|