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.
package/dist/index.dev.js CHANGED
@@ -1,4 +1,11 @@
1
- // src/ImageData/blend-modes.ts
1
+ // src/_types.ts
2
+ var MaskType = /* @__PURE__ */ ((MaskType2) => {
3
+ MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
4
+ MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
5
+ return MaskType2;
6
+ })(MaskType || {});
7
+
8
+ // src/blend-modes.ts
2
9
  var sourceOverColor32 = (src, dst) => {
3
10
  const a = src >>> 24 & 255;
4
11
  if (a === 255) return src;
@@ -134,176 +141,83 @@ var COLOR_32_BLEND_MODES = {
134
141
  colorBurn: colorBurnColor32
135
142
  };
136
143
 
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
-
144
- // src/ImageData/blit.ts
145
- function blendImageData(dst, src, opts) {
146
- let {
147
- dx = 0,
148
- dy = 0,
149
- sx = 0,
150
- sy = 0,
151
- sw = src.width,
152
- sh = src.height,
153
- opacity = 1,
154
- alpha,
155
- blendFn = sourceOverColor32,
156
- mask
157
- } = opts;
158
- if (sx < 0) {
159
- dx -= sx;
160
- sw += sx;
161
- sx = 0;
162
- }
163
- if (sy < 0) {
164
- dy -= sy;
165
- sh += sy;
166
- sy = 0;
167
- }
168
- sw = Math.min(sw, src.width - sx);
169
- sh = Math.min(sh, src.height - sy);
170
- if (dx < 0) {
171
- sx -= dx;
172
- sw += dx;
173
- dx = 0;
174
- }
175
- if (dy < 0) {
176
- sy -= dy;
177
- sh += dy;
178
- dy = 0;
179
- }
180
- const actualW = Math.min(sw, dst.width - dx);
181
- const actualH = Math.min(sh, dst.height - dy);
182
- if (actualW <= 0 || actualH <= 0) return;
183
- const dst32 = new Uint32Array(dst.data.buffer);
184
- const src32 = new Uint32Array(src.data.buffer);
185
- const dw = dst.width;
186
- const sw_orig = src.width;
187
- const gAlpha = alpha !== void 0 ? alpha | 0 : Math.round(opacity * 255);
188
- const maskIsAlpha = mask?.type === 0 /* ALPHA */;
189
- for (let iy = 0; iy < actualH; iy++) {
190
- const dRow = (iy + dy) * dw;
191
- const sRow = (iy + sy) * sw_orig;
192
- for (let ix = 0; ix < actualW; ix++) {
193
- const di = dRow + (ix + dx);
194
- const si = sRow + (ix + sx);
195
- let s = src32[si];
196
- let sa = s >>> 24 & 255;
197
- if (sa === 0) continue;
198
- let activeWeight = gAlpha;
199
- if (mask) {
200
- const m = mask.data[si];
201
- if (m === 0) continue;
202
- activeWeight = maskIsAlpha ? m * activeWeight + 128 >> 8 : activeWeight;
203
- }
204
- if (activeWeight < 255) {
205
- sa = sa * activeWeight + 128 >> 8;
206
- }
207
- if (sa === 0) continue;
208
- s = (s & 16777215 | sa << 24) >>> 0;
209
- dst32[di] = blendFn(s, dst32[di]);
210
- }
211
- }
144
+ // src/color.ts
145
+ function packColor(r, g, b, a) {
146
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
212
147
  }
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;
148
+ function packRGBA({ r, g, b, a }) {
149
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
238
150
  }
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
- }
151
+ var unpackRed = (packed) => packed >>> 0 & 255;
152
+ var unpackGreen = (packed) => packed >>> 8 & 255;
153
+ var unpackBlue = (packed) => packed >>> 16 & 255;
154
+ var unpackAlpha = (packed) => packed >>> 24 & 255;
155
+ function unpackColor(packed) {
156
+ return {
157
+ r: packed >>> 0 & 255,
158
+ g: packed >>> 8 & 255,
159
+ b: packed >>> 16 & 255,
160
+ a: packed >>> 24 & 255
161
+ };
162
+ }
163
+ var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
164
+ function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
165
+ scratch.r = packed >>> 0 & 255;
166
+ scratch.g = packed >>> 8 & 255;
167
+ scratch.b = packed >>> 16 & 255;
168
+ scratch.a = packed >>> 24 & 255;
169
+ return scratch;
170
+ }
171
+ function colorDistance(a, b) {
172
+ const dr = (a & 255) - (b & 255);
173
+ const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
174
+ const db = (a >>> 16 & 255) - (b >>> 16 & 255);
175
+ const da = (a >>> 24 & 255) - (b >>> 24 & 255);
176
+ return dr * dr + dg * dg + db * db + da * da;
177
+ }
178
+ function lerpColor32(a, b, t) {
179
+ const r = (a & 255) + t * ((b & 255) - (a & 255));
180
+ const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
181
+ const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
182
+ const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
183
+ return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
184
+ }
185
+ function lerpColor32Fast(src, dst, w) {
186
+ const invA = 255 - w;
187
+ const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
188
+ const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
189
+ return (rb | ga << 8) >>> 0;
190
+ }
191
+ function color32ToHex(color) {
192
+ const r = (color & 255).toString(16).padStart(2, "0");
193
+ const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
194
+ const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
195
+ const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
196
+ return `#${r}${g}${b}${a}`;
197
+ }
198
+ function color32ToCssRGBA(color) {
199
+ const r = color & 255;
200
+ const g = color >>> 8 & 255;
201
+ const b = color >>> 16 & 255;
202
+ const a = color >>> 24 & 255;
203
+ const alpha = Number((a / 255).toFixed(3));
204
+ return `rgba(${r},${g},${b},${alpha})`;
282
205
  }
283
206
 
284
- // src/ImageData/read-write-pixels.ts
285
- function makeImageDataColor32Adapter(imageData) {
286
- const data32 = new Uint32Array(imageData.data.buffer);
287
- function inBounds(x, y) {
288
- return x < 0 || x >= imageData.width || y < 0 || y >= imageData.height;
289
- }
290
- function setPixel(x, y, color) {
291
- if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) return;
292
- data32[y * imageData.width + x] = color;
293
- }
294
- function getPixel(x, y) {
295
- if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) return;
296
- return data32[y * imageData.width + x];
297
- }
207
+ // src/ImageData/copyImageData.ts
208
+ function copyImageData({ data, width, height }) {
209
+ return new ImageData(data.slice(), width, height);
210
+ }
211
+ function copyImageDataLike({ data, width, height }) {
298
212
  return {
299
- inBounds,
300
- imageData,
301
- data32,
302
- setPixel,
303
- getPixel
213
+ data: data.slice(),
214
+ width,
215
+ height
304
216
  };
305
217
  }
306
- function extractPixelData(imageData, _x, _y, _w, _h) {
218
+
219
+ // src/ImageData/extractImageData.ts
220
+ function extractImageData(imageData, _x, _y, _w, _h) {
307
221
  const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
308
222
  const { width: srcW, height: srcH, data: src } = imageData;
309
223
  if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
@@ -324,16 +238,6 @@ function extractPixelData(imageData, _x, _y, _w, _h) {
324
238
  }
325
239
  return out;
326
240
  }
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
241
 
338
242
  // src/ImageData/serialization.ts
339
243
  function base64EncodeArrayBuffer(buffer) {
@@ -375,76 +279,147 @@ function deserializeNullableImageData(serialized) {
375
279
  return deserializeImageData(serialized);
376
280
  }
377
281
 
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})`;
282
+ // src/PixelData/blendPixelData.ts
283
+ function blendPixelData(dst, src, opts) {
284
+ const {
285
+ x: targetX = 0,
286
+ y: targetY = 0,
287
+ sx: sourceX = 0,
288
+ sy: sourceY = 0,
289
+ w: width = src.width,
290
+ h: height = src.height,
291
+ alpha: globalAlpha = 255,
292
+ blendFn = sourceOverColor32,
293
+ mask,
294
+ maskType = 0 /* ALPHA */,
295
+ mw,
296
+ mx = 0,
297
+ my = 0,
298
+ invertMask = false
299
+ } = opts;
300
+ if (globalAlpha === 0) return;
301
+ let x = targetX;
302
+ let y = targetY;
303
+ let sx = sourceX;
304
+ let sy = sourceY;
305
+ let w = width;
306
+ let h = height;
307
+ if (sx < 0) {
308
+ x -= sx;
309
+ w += sx;
310
+ sx = 0;
311
+ }
312
+ if (sy < 0) {
313
+ y -= sy;
314
+ h += sy;
315
+ sy = 0;
316
+ }
317
+ w = Math.min(w, src.width - sx);
318
+ h = Math.min(h, src.height - sy);
319
+ if (x < 0) {
320
+ sx -= x;
321
+ w += x;
322
+ x = 0;
323
+ }
324
+ if (y < 0) {
325
+ sy -= y;
326
+ h += y;
327
+ y = 0;
328
+ }
329
+ const actualW = Math.min(w, dst.width - x);
330
+ const actualH = Math.min(h, dst.height - y);
331
+ if (actualW <= 0 || actualH <= 0) return;
332
+ const dst32 = dst.data32;
333
+ const src32 = src.data32;
334
+ const dw = dst.width;
335
+ const sw = src.width;
336
+ const mPitch = mw ?? width;
337
+ const isAlphaMask = maskType === 0 /* ALPHA */;
338
+ const dx = x - targetX;
339
+ const dy = y - targetY;
340
+ let dIdx = y * dw + x;
341
+ let sIdx = sy * sw + sx;
342
+ let mIdx = (my + dy) * mPitch + (mx + dx);
343
+ const dStride = dw - actualW;
344
+ const sStride = sw - actualW;
345
+ const mStride = mPitch - actualW;
346
+ for (let iy = 0; iy < actualH; iy++) {
347
+ for (let ix = 0; ix < actualW; ix++) {
348
+ const baseSrcColor = src32[sIdx];
349
+ const baseSrcAlpha = baseSrcColor >>> 24;
350
+ if (baseSrcAlpha === 0) {
351
+ dIdx++;
352
+ sIdx++;
353
+ mIdx++;
354
+ continue;
355
+ }
356
+ let weight = globalAlpha;
357
+ if (mask) {
358
+ const mVal = mask[mIdx];
359
+ if (isAlphaMask) {
360
+ const effectiveM = invertMask ? 255 - mVal : mVal;
361
+ if (effectiveM === 0) {
362
+ dIdx++;
363
+ sIdx++;
364
+ mIdx++;
365
+ continue;
366
+ }
367
+ if (globalAlpha === 255) {
368
+ weight = effectiveM;
369
+ } else if (effectiveM === 255) {
370
+ weight = globalAlpha;
371
+ } else {
372
+ weight = effectiveM * globalAlpha + 128 >> 8;
373
+ }
374
+ } else {
375
+ const isHit = invertMask ? mVal === 0 : mVal === 1;
376
+ if (!isHit) {
377
+ dIdx++;
378
+ sIdx++;
379
+ mIdx++;
380
+ continue;
381
+ }
382
+ weight = globalAlpha;
383
+ }
384
+ if (weight === 0) {
385
+ dIdx++;
386
+ sIdx++;
387
+ mIdx++;
388
+ continue;
389
+ }
390
+ }
391
+ let currentSrcAlpha = baseSrcAlpha;
392
+ let currentSrcColor = baseSrcColor;
393
+ if (weight < 255) {
394
+ if (baseSrcAlpha === 255) {
395
+ currentSrcAlpha = weight;
396
+ } else {
397
+ currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
398
+ }
399
+ if (currentSrcAlpha === 0) {
400
+ dIdx++;
401
+ sIdx++;
402
+ mIdx++;
403
+ continue;
404
+ }
405
+ currentSrcColor = (baseSrcColor & 16777215 | currentSrcAlpha << 24) >>> 0;
406
+ }
407
+ dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
408
+ dIdx++;
409
+ sIdx++;
410
+ mIdx++;
411
+ }
412
+ dIdx += dStride;
413
+ sIdx += sStride;
414
+ mIdx += mStride;
415
+ }
439
416
  }
440
417
  export {
441
418
  COLOR_32_BLEND_MODES,
442
419
  MaskType,
443
- applyAlphaMask,
444
- applyBinaryMask,
445
420
  base64DecodeArrayBuffer,
446
421
  base64EncodeArrayBuffer,
447
- blendImageData,
422
+ blendPixelData,
448
423
  color32ToCssRGBA,
449
424
  color32ToHex,
450
425
  colorBurnColor32,
@@ -455,12 +430,11 @@ export {
455
430
  deserializeNullableImageData,
456
431
  deserializeRawImageData,
457
432
  differenceColor32,
458
- extractPixelData,
433
+ extractImageData,
459
434
  hardLightColor32,
460
435
  lerpColor32,
461
436
  lerpColor32Fast,
462
437
  linearDodgeColor32,
463
- makeImageDataColor32Adapter,
464
438
  multiplyColor32,
465
439
  overlayColor32,
466
440
  packColor,