pixel-data-js 0.1.0 → 0.3.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.
@@ -21,22 +21,25 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  COLOR_32_BLEND_MODES: () => COLOR_32_BLEND_MODES,
24
+ MaskType: () => MaskType,
24
25
  base64DecodeArrayBuffer: () => base64DecodeArrayBuffer,
25
26
  base64EncodeArrayBuffer: () => base64EncodeArrayBuffer,
26
- blendImageData: () => blendImageData,
27
+ blendPixelData: () => blendPixelData,
27
28
  color32ToCssRGBA: () => color32ToCssRGBA,
28
29
  color32ToHex: () => color32ToHex,
29
30
  colorBurnColor32: () => colorBurnColor32,
30
31
  colorDistance: () => colorDistance,
32
+ copyImageData: () => copyImageData,
33
+ copyImageDataLike: () => copyImageDataLike,
31
34
  deserializeImageData: () => deserializeImageData,
32
35
  deserializeNullableImageData: () => deserializeNullableImageData,
33
36
  deserializeRawImageData: () => deserializeRawImageData,
34
37
  differenceColor32: () => differenceColor32,
38
+ extractImageData: () => extractImageData,
35
39
  hardLightColor32: () => hardLightColor32,
36
40
  lerpColor32: () => lerpColor32,
37
41
  lerpColor32Fast: () => lerpColor32Fast,
38
42
  linearDodgeColor32: () => linearDodgeColor32,
39
- makeImageDataColor32Adapter: () => makeImageDataColor32Adapter,
40
43
  multiplyColor32: () => multiplyColor32,
41
44
  overlayColor32: () => overlayColor32,
42
45
  packColor: () => packColor,
@@ -54,110 +57,14 @@ __export(src_exports, {
54
57
  });
55
58
  module.exports = __toCommonJS(src_exports);
56
59
 
57
- // src/color.ts
58
- function packColor(r, g, b, a) {
59
- return (a << 24 | b << 16 | g << 8 | r) >>> 0;
60
- }
61
- function packRGBA({ r, g, b, a }) {
62
- return (a << 24 | b << 16 | g << 8 | r) >>> 0;
63
- }
64
- var unpackRed = (packed) => packed >>> 0 & 255;
65
- var unpackGreen = (packed) => packed >>> 8 & 255;
66
- var unpackBlue = (packed) => packed >>> 16 & 255;
67
- var unpackAlpha = (packed) => packed >>> 24 & 255;
68
- function unpackColor(packed) {
69
- return {
70
- r: packed >>> 0 & 255,
71
- g: packed >>> 8 & 255,
72
- b: packed >>> 16 & 255,
73
- a: packed >>> 24 & 255
74
- };
75
- }
76
- var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
77
- function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
78
- scratch.r = packed >>> 0 & 255;
79
- scratch.g = packed >>> 8 & 255;
80
- scratch.b = packed >>> 16 & 255;
81
- scratch.a = packed >>> 24 & 255;
82
- return scratch;
83
- }
84
- function colorDistance(a, b) {
85
- const dr = (a & 255) - (b & 255);
86
- const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
87
- const db = (a >>> 16 & 255) - (b >>> 16 & 255);
88
- const da = (a >>> 24 & 255) - (b >>> 24 & 255);
89
- return dr * dr + dg * dg + db * db + da * da;
90
- }
91
- function lerpColor32(a, b, t) {
92
- const r = (a & 255) + t * ((b & 255) - (a & 255));
93
- const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
94
- const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
95
- const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
96
- return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
97
- }
98
- function lerpColor32Fast(src, dst, w) {
99
- const invA = 255 - w;
100
- const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
101
- const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
102
- return (rb | ga << 8) >>> 0;
103
- }
104
- function color32ToHex(color) {
105
- const r = (color & 255).toString(16).padStart(2, "0");
106
- const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
107
- const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
108
- const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
109
- return `#${r}${g}${b}${a}`;
110
- }
111
- function color32ToCssRGBA(color) {
112
- const r = color & 255;
113
- const g = color >>> 8 & 255;
114
- const b = color >>> 16 & 255;
115
- const a = color >>> 24 & 255;
116
- const alpha = Number((a / 255).toFixed(3));
117
- return `rgba(${r},${g},${b},${alpha})`;
118
- }
60
+ // src/_types.ts
61
+ var MaskType = /* @__PURE__ */ ((MaskType2) => {
62
+ MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
63
+ MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
64
+ return MaskType2;
65
+ })(MaskType || {});
119
66
 
120
- // src/ImageData/serialization.ts
121
- function base64EncodeArrayBuffer(buffer) {
122
- const binary = String.fromCharCode(...new Uint8Array(buffer));
123
- return btoa(binary);
124
- }
125
- function base64DecodeArrayBuffer(encoded) {
126
- const binary = atob(encoded);
127
- const bytes = new Uint8ClampedArray(binary.length);
128
- for (let i = 0; i < binary.length; i++) {
129
- bytes[i] = binary.charCodeAt(i);
130
- }
131
- return bytes;
132
- }
133
- function serializeImageData(imageData) {
134
- return {
135
- width: imageData.width,
136
- height: imageData.height,
137
- data: base64EncodeArrayBuffer(imageData.data.buffer)
138
- };
139
- }
140
- function serializeNullableImageData(imageData) {
141
- if (!imageData) return null;
142
- return serializeImageData(imageData);
143
- }
144
- function deserializeRawImageData(serialized) {
145
- return {
146
- width: serialized.width,
147
- height: serialized.height,
148
- data: base64DecodeArrayBuffer(serialized.data)
149
- };
150
- }
151
- function deserializeImageData(serialized) {
152
- const data = base64DecodeArrayBuffer(serialized.data);
153
- return new ImageData(data, serialized.width, serialized.height);
154
- }
155
- function deserializeNullableImageData(serialized) {
156
- if (!serialized) return null;
157
- return deserializeImageData(serialized);
158
- }
159
-
160
- // src/ImageData/blend-modes.ts
67
+ // src/blend-modes.ts
161
68
  var sourceOverColor32 = (src, dst) => {
162
69
  const a = src >>> 24 & 255;
163
70
  if (a === 255) return src;
@@ -293,118 +200,301 @@ var COLOR_32_BLEND_MODES = {
293
200
  colorBurn: colorBurnColor32
294
201
  };
295
202
 
296
- // src/ImageData/blit.ts
297
- function blendImageData(dst, src, opts) {
298
- let {
299
- dx = 0,
300
- dy = 0,
301
- sx = 0,
302
- sy = 0,
303
- sw = src.width,
304
- sh = src.height,
305
- maskMode = "alpha",
306
- opacity = 1,
307
- alpha,
203
+ // src/color.ts
204
+ function packColor(r, g, b, a) {
205
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
206
+ }
207
+ function packRGBA({ r, g, b, a }) {
208
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
209
+ }
210
+ var unpackRed = (packed) => packed >>> 0 & 255;
211
+ var unpackGreen = (packed) => packed >>> 8 & 255;
212
+ var unpackBlue = (packed) => packed >>> 16 & 255;
213
+ var unpackAlpha = (packed) => packed >>> 24 & 255;
214
+ function unpackColor(packed) {
215
+ return {
216
+ r: packed >>> 0 & 255,
217
+ g: packed >>> 8 & 255,
218
+ b: packed >>> 16 & 255,
219
+ a: packed >>> 24 & 255
220
+ };
221
+ }
222
+ var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
223
+ function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
224
+ scratch.r = packed >>> 0 & 255;
225
+ scratch.g = packed >>> 8 & 255;
226
+ scratch.b = packed >>> 16 & 255;
227
+ scratch.a = packed >>> 24 & 255;
228
+ return scratch;
229
+ }
230
+ function colorDistance(a, b) {
231
+ const dr = (a & 255) - (b & 255);
232
+ const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
233
+ const db = (a >>> 16 & 255) - (b >>> 16 & 255);
234
+ const da = (a >>> 24 & 255) - (b >>> 24 & 255);
235
+ return dr * dr + dg * dg + db * db + da * da;
236
+ }
237
+ function lerpColor32(a, b, t) {
238
+ const r = (a & 255) + t * ((b & 255) - (a & 255));
239
+ const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
240
+ const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
241
+ const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
242
+ return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
243
+ }
244
+ function lerpColor32Fast(src, dst, w) {
245
+ const invA = 255 - w;
246
+ const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
247
+ const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
248
+ return (rb | ga << 8) >>> 0;
249
+ }
250
+ function color32ToHex(color) {
251
+ const r = (color & 255).toString(16).padStart(2, "0");
252
+ const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
253
+ const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
254
+ const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
255
+ return `#${r}${g}${b}${a}`;
256
+ }
257
+ function color32ToCssRGBA(color) {
258
+ const r = color & 255;
259
+ const g = color >>> 8 & 255;
260
+ const b = color >>> 16 & 255;
261
+ const a = color >>> 24 & 255;
262
+ const alpha = Number((a / 255).toFixed(3));
263
+ return `rgba(${r},${g},${b},${alpha})`;
264
+ }
265
+
266
+ // src/ImageData/copyImageData.ts
267
+ function copyImageData({ data, width, height }) {
268
+ return new ImageData(data.slice(), width, height);
269
+ }
270
+ function copyImageDataLike({ data, width, height }) {
271
+ return {
272
+ data: data.slice(),
273
+ width,
274
+ height
275
+ };
276
+ }
277
+
278
+ // src/ImageData/extractImageData.ts
279
+ function extractImageData(imageData, _x, _y, _w, _h) {
280
+ const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
281
+ const { width: srcW, height: srcH, data: src } = imageData;
282
+ if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
283
+ const out = new Uint8ClampedArray(w * h * 4);
284
+ const x0 = Math.max(0, x);
285
+ const y0 = Math.max(0, y);
286
+ const x1 = Math.min(srcW, x + w);
287
+ const y1 = Math.min(srcH, y + h);
288
+ if (x1 <= x0 || y1 <= y0) return out;
289
+ for (let row = 0; row < y1 - y0; row++) {
290
+ const srcRow = y0 + row;
291
+ const srcStart = (srcRow * srcW + x0) * 4;
292
+ const rowLen = (x1 - x0) * 4;
293
+ const dstRow = y0 - y + row;
294
+ const dstCol = x0 - x;
295
+ const dstStart = (dstRow * w + dstCol) * 4;
296
+ out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
297
+ }
298
+ return out;
299
+ }
300
+
301
+ // src/ImageData/serialization.ts
302
+ function base64EncodeArrayBuffer(buffer) {
303
+ const binary = String.fromCharCode(...new Uint8Array(buffer));
304
+ return btoa(binary);
305
+ }
306
+ function base64DecodeArrayBuffer(encoded) {
307
+ const binary = atob(encoded);
308
+ const bytes = new Uint8ClampedArray(binary.length);
309
+ for (let i = 0; i < binary.length; i++) {
310
+ bytes[i] = binary.charCodeAt(i);
311
+ }
312
+ return bytes;
313
+ }
314
+ function serializeImageData(imageData) {
315
+ return {
316
+ width: imageData.width,
317
+ height: imageData.height,
318
+ data: base64EncodeArrayBuffer(imageData.data.buffer)
319
+ };
320
+ }
321
+ function serializeNullableImageData(imageData) {
322
+ if (!imageData) return null;
323
+ return serializeImageData(imageData);
324
+ }
325
+ function deserializeRawImageData(serialized) {
326
+ return {
327
+ width: serialized.width,
328
+ height: serialized.height,
329
+ data: base64DecodeArrayBuffer(serialized.data)
330
+ };
331
+ }
332
+ function deserializeImageData(serialized) {
333
+ const data = base64DecodeArrayBuffer(serialized.data);
334
+ return new ImageData(data, serialized.width, serialized.height);
335
+ }
336
+ function deserializeNullableImageData(serialized) {
337
+ if (!serialized) return null;
338
+ return deserializeImageData(serialized);
339
+ }
340
+
341
+ // src/PixelData/blendPixelData.ts
342
+ function blendPixelData(dst, src, opts) {
343
+ const {
344
+ x: targetX = 0,
345
+ y: targetY = 0,
346
+ sx: sourceX = 0,
347
+ sy: sourceY = 0,
348
+ w: width = src.width,
349
+ h: height = src.height,
350
+ alpha: globalAlpha = 255,
308
351
  blendFn = sourceOverColor32,
309
- mask
352
+ mask,
353
+ maskType = 0 /* ALPHA */,
354
+ mw,
355
+ mx = 0,
356
+ my = 0,
357
+ invertMask = false
310
358
  } = opts;
359
+ if (globalAlpha === 0) return;
360
+ let x = targetX;
361
+ let y = targetY;
362
+ let sx = sourceX;
363
+ let sy = sourceY;
364
+ let w = width;
365
+ let h = height;
311
366
  if (sx < 0) {
312
- dx -= sx;
313
- sw += sx;
367
+ x -= sx;
368
+ w += sx;
314
369
  sx = 0;
315
370
  }
316
371
  if (sy < 0) {
317
- dy -= sy;
318
- sh += sy;
372
+ y -= sy;
373
+ h += sy;
319
374
  sy = 0;
320
375
  }
321
- sw = Math.min(sw, src.width - sx);
322
- sh = Math.min(sh, src.height - sy);
323
- if (dx < 0) {
324
- sx -= dx;
325
- sw += dx;
326
- dx = 0;
376
+ w = Math.min(w, src.width - sx);
377
+ h = Math.min(h, src.height - sy);
378
+ if (x < 0) {
379
+ sx -= x;
380
+ w += x;
381
+ x = 0;
327
382
  }
328
- if (dy < 0) {
329
- sy -= dy;
330
- sh += dy;
331
- dy = 0;
383
+ if (y < 0) {
384
+ sy -= y;
385
+ h += y;
386
+ y = 0;
332
387
  }
333
- const actualW = Math.min(sw, dst.width - dx);
334
- const actualH = Math.min(sh, dst.height - dy);
388
+ const actualW = Math.min(w, dst.width - x);
389
+ const actualH = Math.min(h, dst.height - y);
335
390
  if (actualW <= 0 || actualH <= 0) return;
336
- const dst32 = new Uint32Array(dst.data.buffer);
337
- const src32 = new Uint32Array(src.data.buffer);
391
+ const dst32 = dst.data32;
392
+ const src32 = src.data32;
338
393
  const dw = dst.width;
339
- const sw_orig = src.width;
340
- const gAlpha = alpha !== void 0 ? alpha | 0 : Math.round(opacity * 255);
341
- const maskIsAlpha = maskMode === "alpha";
394
+ const sw = src.width;
395
+ const mPitch = mw ?? width;
396
+ const isAlphaMask = maskType === 0 /* ALPHA */;
397
+ const dx = x - targetX;
398
+ const dy = y - targetY;
399
+ let dIdx = y * dw + x;
400
+ let sIdx = sy * sw + sx;
401
+ let mIdx = (my + dy) * mPitch + (mx + dx);
402
+ const dStride = dw - actualW;
403
+ const sStride = sw - actualW;
404
+ const mStride = mPitch - actualW;
342
405
  for (let iy = 0; iy < actualH; iy++) {
343
- const dRow = (iy + dy) * dw;
344
- const sRow = (iy + sy) * sw_orig;
345
406
  for (let ix = 0; ix < actualW; ix++) {
346
- const di = dRow + (ix + dx);
347
- const si = sRow + (ix + sx);
348
- let s = src32[si];
349
- let sa = s >>> 24 & 255;
350
- if (sa === 0) continue;
351
- let activeWeight = gAlpha;
407
+ const baseSrcColor = src32[sIdx];
408
+ const baseSrcAlpha = baseSrcColor >>> 24;
409
+ if (baseSrcAlpha === 0) {
410
+ dIdx++;
411
+ sIdx++;
412
+ mIdx++;
413
+ continue;
414
+ }
415
+ let weight = globalAlpha;
352
416
  if (mask) {
353
- const m = mask[si];
354
- if (m === 0) continue;
355
- activeWeight = maskIsAlpha ? m * activeWeight + 128 >> 8 : activeWeight;
417
+ const mVal = mask[mIdx];
418
+ if (isAlphaMask) {
419
+ const effectiveM = invertMask ? 255 - mVal : mVal;
420
+ if (effectiveM === 0) {
421
+ dIdx++;
422
+ sIdx++;
423
+ mIdx++;
424
+ continue;
425
+ }
426
+ if (globalAlpha === 255) {
427
+ weight = effectiveM;
428
+ } else if (effectiveM === 255) {
429
+ weight = globalAlpha;
430
+ } else {
431
+ weight = effectiveM * globalAlpha + 128 >> 8;
432
+ }
433
+ } else {
434
+ const isHit = invertMask ? mVal === 0 : mVal === 1;
435
+ if (!isHit) {
436
+ dIdx++;
437
+ sIdx++;
438
+ mIdx++;
439
+ continue;
440
+ }
441
+ weight = globalAlpha;
442
+ }
443
+ if (weight === 0) {
444
+ dIdx++;
445
+ sIdx++;
446
+ mIdx++;
447
+ continue;
448
+ }
356
449
  }
357
- if (activeWeight < 255) {
358
- sa = sa * activeWeight + 128 >> 8;
450
+ let currentSrcAlpha = baseSrcAlpha;
451
+ let currentSrcColor = baseSrcColor;
452
+ if (weight < 255) {
453
+ if (baseSrcAlpha === 255) {
454
+ currentSrcAlpha = weight;
455
+ } else {
456
+ currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
457
+ }
458
+ if (currentSrcAlpha === 0) {
459
+ dIdx++;
460
+ sIdx++;
461
+ mIdx++;
462
+ continue;
463
+ }
464
+ currentSrcColor = (baseSrcColor & 16777215 | currentSrcAlpha << 24) >>> 0;
359
465
  }
360
- if (sa === 0) continue;
361
- s = (s & 16777215 | sa << 24) >>> 0;
362
- dst32[di] = blendFn(s, dst32[di]);
466
+ dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
467
+ dIdx++;
468
+ sIdx++;
469
+ mIdx++;
363
470
  }
471
+ dIdx += dStride;
472
+ sIdx += sStride;
473
+ mIdx += mStride;
364
474
  }
365
475
  }
366
-
367
- // src/ImageData/read-write-pixels.ts
368
- function makeImageDataColor32Adapter(imageData) {
369
- const data32 = new Uint32Array(imageData.data.buffer);
370
- function inBounds(x, y) {
371
- return x < 0 || x >= imageData.width || y < 0 || y >= imageData.height;
372
- }
373
- function setPixel(x, y, color) {
374
- if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) return;
375
- data32[y * imageData.width + x] = color;
376
- }
377
- function getPixel(x, y) {
378
- if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) return;
379
- return data32[y * imageData.width + x];
380
- }
381
- return {
382
- inBounds,
383
- imageData,
384
- data32,
385
- setPixel,
386
- getPixel
387
- };
388
- }
389
476
  // Annotate the CommonJS export names for ESM import in node:
390
477
  0 && (module.exports = {
391
478
  COLOR_32_BLEND_MODES,
479
+ MaskType,
392
480
  base64DecodeArrayBuffer,
393
481
  base64EncodeArrayBuffer,
394
- blendImageData,
482
+ blendPixelData,
395
483
  color32ToCssRGBA,
396
484
  color32ToHex,
397
485
  colorBurnColor32,
398
486
  colorDistance,
487
+ copyImageData,
488
+ copyImageDataLike,
399
489
  deserializeImageData,
400
490
  deserializeNullableImageData,
401
491
  deserializeRawImageData,
402
492
  differenceColor32,
493
+ extractImageData,
403
494
  hardLightColor32,
404
495
  lerpColor32,
405
496
  lerpColor32Fast,
406
497
  linearDodgeColor32,
407
- makeImageDataColor32Adapter,
408
498
  multiplyColor32,
409
499
  overlayColor32,
410
500
  packColor,