pixel-data-js 0.2.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.
@@ -22,11 +22,9 @@ var src_exports = {};
22
22
  __export(src_exports, {
23
23
  COLOR_32_BLEND_MODES: () => COLOR_32_BLEND_MODES,
24
24
  MaskType: () => MaskType,
25
- applyAlphaMask: () => applyAlphaMask,
26
- applyBinaryMask: () => applyBinaryMask,
27
25
  base64DecodeArrayBuffer: () => base64DecodeArrayBuffer,
28
26
  base64EncodeArrayBuffer: () => base64EncodeArrayBuffer,
29
- blendImageData: () => blendImageData,
27
+ blendPixelData: () => blendPixelData,
30
28
  color32ToCssRGBA: () => color32ToCssRGBA,
31
29
  color32ToHex: () => color32ToHex,
32
30
  colorBurnColor32: () => colorBurnColor32,
@@ -37,12 +35,11 @@ __export(src_exports, {
37
35
  deserializeNullableImageData: () => deserializeNullableImageData,
38
36
  deserializeRawImageData: () => deserializeRawImageData,
39
37
  differenceColor32: () => differenceColor32,
40
- extractPixelData: () => extractPixelData,
38
+ extractImageData: () => extractImageData,
41
39
  hardLightColor32: () => hardLightColor32,
42
40
  lerpColor32: () => lerpColor32,
43
41
  lerpColor32Fast: () => lerpColor32Fast,
44
42
  linearDodgeColor32: () => linearDodgeColor32,
45
- makeImageDataColor32Adapter: () => makeImageDataColor32Adapter,
46
43
  multiplyColor32: () => multiplyColor32,
47
44
  overlayColor32: () => overlayColor32,
48
45
  packColor: () => packColor,
@@ -60,7 +57,14 @@ __export(src_exports, {
60
57
  });
61
58
  module.exports = __toCommonJS(src_exports);
62
59
 
63
- // src/ImageData/blend-modes.ts
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 || {});
66
+
67
+ // src/blend-modes.ts
64
68
  var sourceOverColor32 = (src, dst) => {
65
69
  const a = src >>> 24 & 255;
66
70
  if (a === 255) return src;
@@ -196,176 +200,83 @@ var COLOR_32_BLEND_MODES = {
196
200
  colorBurn: colorBurnColor32
197
201
  };
198
202
 
199
- // src/_types.ts
200
- var MaskType = /* @__PURE__ */ ((MaskType2) => {
201
- MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
202
- MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
203
- return MaskType2;
204
- })(MaskType || {});
205
-
206
- // src/ImageData/blit.ts
207
- function blendImageData(dst, src, opts) {
208
- let {
209
- dx = 0,
210
- dy = 0,
211
- sx = 0,
212
- sy = 0,
213
- sw = src.width,
214
- sh = src.height,
215
- opacity = 1,
216
- alpha,
217
- blendFn = sourceOverColor32,
218
- mask
219
- } = opts;
220
- if (sx < 0) {
221
- dx -= sx;
222
- sw += sx;
223
- sx = 0;
224
- }
225
- if (sy < 0) {
226
- dy -= sy;
227
- sh += sy;
228
- sy = 0;
229
- }
230
- sw = Math.min(sw, src.width - sx);
231
- sh = Math.min(sh, src.height - sy);
232
- if (dx < 0) {
233
- sx -= dx;
234
- sw += dx;
235
- dx = 0;
236
- }
237
- if (dy < 0) {
238
- sy -= dy;
239
- sh += dy;
240
- dy = 0;
241
- }
242
- const actualW = Math.min(sw, dst.width - dx);
243
- const actualH = Math.min(sh, dst.height - dy);
244
- if (actualW <= 0 || actualH <= 0) return;
245
- const dst32 = new Uint32Array(dst.data.buffer);
246
- const src32 = new Uint32Array(src.data.buffer);
247
- const dw = dst.width;
248
- const sw_orig = src.width;
249
- const gAlpha = alpha !== void 0 ? alpha | 0 : Math.round(opacity * 255);
250
- const maskIsAlpha = mask?.type === 0 /* ALPHA */;
251
- for (let iy = 0; iy < actualH; iy++) {
252
- const dRow = (iy + dy) * dw;
253
- const sRow = (iy + sy) * sw_orig;
254
- for (let ix = 0; ix < actualW; ix++) {
255
- const di = dRow + (ix + dx);
256
- const si = sRow + (ix + sx);
257
- let s = src32[si];
258
- let sa = s >>> 24 & 255;
259
- if (sa === 0) continue;
260
- let activeWeight = gAlpha;
261
- if (mask) {
262
- const m = mask.data[si];
263
- if (m === 0) continue;
264
- activeWeight = maskIsAlpha ? m * activeWeight + 128 >> 8 : activeWeight;
265
- }
266
- if (activeWeight < 255) {
267
- sa = sa * activeWeight + 128 >> 8;
268
- }
269
- if (sa === 0) continue;
270
- s = (s & 16777215 | sa << 24) >>> 0;
271
- dst32[di] = blendFn(s, dst32[di]);
272
- }
273
- }
203
+ // src/color.ts
204
+ function packColor(r, g, b, a) {
205
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
274
206
  }
275
-
276
- // src/ImageData/mask.ts
277
- function applyBinaryMask(dst, mask, opts = {}) {
278
- const { width: maskWidth, height: maskHeight } = mask;
279
- const { dx = 0, dy = 0, sx = 0, sy = 0, sw = maskWidth, sh = maskHeight } = opts;
280
- const x0 = Math.max(0, dx, dx + (0 - sx));
281
- const y0 = Math.max(0, dy, dy + (0 - sy));
282
- const x1 = Math.min(dst.width, dx + sw, dx + (maskWidth - sx));
283
- const y1 = Math.min(dst.height, dy + sh, dy + (maskHeight - sy));
284
- if (x1 <= x0 || y1 <= y0) return;
285
- const { data: dstData, width: dstW } = dst;
286
- for (let y = y0; y < y1; y++) {
287
- const maskY = y - dy + sy;
288
- const dstRowOffset = y * dstW * 4;
289
- const maskRowOffset = maskY * maskWidth;
290
- for (let x = x0; x < x1; x++) {
291
- const maskX = x - dx + sx;
292
- const mIdx = maskRowOffset + maskX;
293
- if (mask.data[mIdx] === 0) {
294
- const aIdx = dstRowOffset + x * 4 + 3;
295
- dstData[aIdx] = 0;
296
- }
297
- }
298
- }
299
- return dst;
207
+ function packRGBA({ r, g, b, a }) {
208
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
300
209
  }
301
- function applyAlphaMask(dst, mask, opts = {}) {
302
- let { dx = 0, dy = 0, sx = 0, sy = 0, sw = mask.width, sh = mask.height } = opts;
303
- if (dx < 0) {
304
- sx -= dx;
305
- sw += dx;
306
- dx = 0;
307
- }
308
- if (dy < 0) {
309
- sy -= dy;
310
- sh += dy;
311
- dy = 0;
312
- }
313
- if (sx < 0) {
314
- dx -= sx;
315
- sw += sx;
316
- sx = 0;
317
- }
318
- if (sy < 0) {
319
- dy -= sy;
320
- sh += sy;
321
- sy = 0;
322
- }
323
- const actualW = Math.min(sw, dst.width - dx, mask.width - sx);
324
- const actualH = Math.min(sh, dst.height - dy, mask.height - sy);
325
- if (actualW <= 0 || actualH <= 0) return;
326
- const dData = dst.data;
327
- const mData = mask.data;
328
- const dW = dst.width;
329
- const mW = mask.width;
330
- for (let y = 0; y < actualH; y++) {
331
- const dOffset = (dy + y) * dW + dx << 2;
332
- const mOffset = (sy + y) * mW + sx;
333
- for (let x = 0; x < actualW; x++) {
334
- const mVal = mData[mOffset + x];
335
- if (mVal === 255) continue;
336
- const aIdx = dOffset + (x << 2) + 3;
337
- if (mVal === 0) {
338
- dData[aIdx] = 0;
339
- continue;
340
- }
341
- dData[aIdx] = dData[aIdx] * mVal + 257 >> 8;
342
- }
343
- }
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})`;
344
264
  }
345
265
 
346
- // src/ImageData/read-write-pixels.ts
347
- function makeImageDataColor32Adapter(imageData) {
348
- const data32 = new Uint32Array(imageData.data.buffer);
349
- function inBounds(x, y) {
350
- return x < 0 || x >= imageData.width || y < 0 || y >= imageData.height;
351
- }
352
- function setPixel(x, y, color) {
353
- if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) return;
354
- data32[y * imageData.width + x] = color;
355
- }
356
- function getPixel(x, y) {
357
- if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) return;
358
- return data32[y * imageData.width + x];
359
- }
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 }) {
360
271
  return {
361
- inBounds,
362
- imageData,
363
- data32,
364
- setPixel,
365
- getPixel
272
+ data: data.slice(),
273
+ width,
274
+ height
366
275
  };
367
276
  }
368
- function extractPixelData(imageData, _x, _y, _w, _h) {
277
+
278
+ // src/ImageData/extractImageData.ts
279
+ function extractImageData(imageData, _x, _y, _w, _h) {
369
280
  const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
370
281
  const { width: srcW, height: srcH, data: src } = imageData;
371
282
  if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
@@ -386,16 +297,6 @@ function extractPixelData(imageData, _x, _y, _w, _h) {
386
297
  }
387
298
  return out;
388
299
  }
389
- function copyImageData({ data, width, height }) {
390
- return new ImageData(data.slice(), width, height);
391
- }
392
- function copyImageDataLike({ data, width, height }) {
393
- return {
394
- data: data.slice(),
395
- width,
396
- height
397
- };
398
- }
399
300
 
400
301
  // src/ImageData/serialization.ts
401
302
  function base64EncodeArrayBuffer(buffer) {
@@ -437,77 +338,148 @@ function deserializeNullableImageData(serialized) {
437
338
  return deserializeImageData(serialized);
438
339
  }
439
340
 
440
- // src/color.ts
441
- function packColor(r, g, b, a) {
442
- return (a << 24 | b << 16 | g << 8 | r) >>> 0;
443
- }
444
- function packRGBA({ r, g, b, a }) {
445
- return (a << 24 | b << 16 | g << 8 | r) >>> 0;
446
- }
447
- var unpackRed = (packed) => packed >>> 0 & 255;
448
- var unpackGreen = (packed) => packed >>> 8 & 255;
449
- var unpackBlue = (packed) => packed >>> 16 & 255;
450
- var unpackAlpha = (packed) => packed >>> 24 & 255;
451
- function unpackColor(packed) {
452
- return {
453
- r: packed >>> 0 & 255,
454
- g: packed >>> 8 & 255,
455
- b: packed >>> 16 & 255,
456
- a: packed >>> 24 & 255
457
- };
458
- }
459
- var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
460
- function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
461
- scratch.r = packed >>> 0 & 255;
462
- scratch.g = packed >>> 8 & 255;
463
- scratch.b = packed >>> 16 & 255;
464
- scratch.a = packed >>> 24 & 255;
465
- return scratch;
466
- }
467
- function colorDistance(a, b) {
468
- const dr = (a & 255) - (b & 255);
469
- const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
470
- const db = (a >>> 16 & 255) - (b >>> 16 & 255);
471
- const da = (a >>> 24 & 255) - (b >>> 24 & 255);
472
- return dr * dr + dg * dg + db * db + da * da;
473
- }
474
- function lerpColor32(a, b, t) {
475
- const r = (a & 255) + t * ((b & 255) - (a & 255));
476
- const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
477
- const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
478
- const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
479
- return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
480
- }
481
- function lerpColor32Fast(src, dst, w) {
482
- const invA = 255 - w;
483
- const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
484
- const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
485
- return (rb | ga << 8) >>> 0;
486
- }
487
- function color32ToHex(color) {
488
- const r = (color & 255).toString(16).padStart(2, "0");
489
- const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
490
- const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
491
- const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
492
- return `#${r}${g}${b}${a}`;
493
- }
494
- function color32ToCssRGBA(color) {
495
- const r = color & 255;
496
- const g = color >>> 8 & 255;
497
- const b = color >>> 16 & 255;
498
- const a = color >>> 24 & 255;
499
- const alpha = Number((a / 255).toFixed(3));
500
- return `rgba(${r},${g},${b},${alpha})`;
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,
351
+ blendFn = sourceOverColor32,
352
+ mask,
353
+ maskType = 0 /* ALPHA */,
354
+ mw,
355
+ mx = 0,
356
+ my = 0,
357
+ invertMask = false
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;
366
+ if (sx < 0) {
367
+ x -= sx;
368
+ w += sx;
369
+ sx = 0;
370
+ }
371
+ if (sy < 0) {
372
+ y -= sy;
373
+ h += sy;
374
+ sy = 0;
375
+ }
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;
382
+ }
383
+ if (y < 0) {
384
+ sy -= y;
385
+ h += y;
386
+ y = 0;
387
+ }
388
+ const actualW = Math.min(w, dst.width - x);
389
+ const actualH = Math.min(h, dst.height - y);
390
+ if (actualW <= 0 || actualH <= 0) return;
391
+ const dst32 = dst.data32;
392
+ const src32 = src.data32;
393
+ const dw = dst.width;
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;
405
+ for (let iy = 0; iy < actualH; iy++) {
406
+ for (let ix = 0; ix < actualW; ix++) {
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;
416
+ if (mask) {
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
+ }
449
+ }
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;
465
+ }
466
+ dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
467
+ dIdx++;
468
+ sIdx++;
469
+ mIdx++;
470
+ }
471
+ dIdx += dStride;
472
+ sIdx += sStride;
473
+ mIdx += mStride;
474
+ }
501
475
  }
502
476
  // Annotate the CommonJS export names for ESM import in node:
503
477
  0 && (module.exports = {
504
478
  COLOR_32_BLEND_MODES,
505
479
  MaskType,
506
- applyAlphaMask,
507
- applyBinaryMask,
508
480
  base64DecodeArrayBuffer,
509
481
  base64EncodeArrayBuffer,
510
- blendImageData,
482
+ blendPixelData,
511
483
  color32ToCssRGBA,
512
484
  color32ToHex,
513
485
  colorBurnColor32,
@@ -518,12 +490,11 @@ function color32ToCssRGBA(color) {
518
490
  deserializeNullableImageData,
519
491
  deserializeRawImageData,
520
492
  differenceColor32,
521
- extractPixelData,
493
+ extractImageData,
522
494
  hardLightColor32,
523
495
  lerpColor32,
524
496
  lerpColor32Fast,
525
497
  linearDodgeColor32,
526
- makeImageDataColor32Adapter,
527
498
  multiplyColor32,
528
499
  overlayColor32,
529
500
  packColor,