@tsparticles/shape-image 3.0.3 → 3.1.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/browser/GifUtils/ByteStream.js +11 -8
- package/browser/GifUtils/Utils.js +17 -10
- package/browser/ImageDrawer.js +28 -22
- package/browser/ImagePreloader.js +1 -1
- package/browser/Utils.js +8 -6
- package/browser/index.js +9 -2
- package/cjs/GifUtils/ByteStream.js +11 -8
- package/cjs/GifUtils/Utils.js +17 -10
- package/cjs/ImageDrawer.js +27 -21
- package/cjs/ImagePreloader.js +1 -1
- package/cjs/Utils.js +8 -6
- package/cjs/index.js +9 -2
- package/esm/GifUtils/ByteStream.js +11 -8
- package/esm/GifUtils/Utils.js +17 -10
- package/esm/ImageDrawer.js +28 -22
- package/esm/ImagePreloader.js +1 -1
- package/esm/Utils.js +8 -6
- package/esm/index.js +9 -2
- package/package.json +2 -2
- package/report.html +2 -2
- package/tsparticles.shape.image.js +98 -50
- package/tsparticles.shape.image.min.js +1 -1
- package/tsparticles.shape.image.min.js.LICENSE.txt +1 -1
- package/types/ImageDrawer.d.ts +1 -1
- package/umd/GifUtils/ByteStream.js +11 -8
- package/umd/GifUtils/Utils.js +17 -10
- package/umd/ImageDrawer.js +27 -21
- package/umd/ImagePreloader.js +1 -1
- package/umd/Utils.js +8 -6
- package/umd/index.js +9 -2
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Demo / Generator : https://particles.js.org/
|
|
5
5
|
* GitHub : https://www.github.com/matteobruni/tsparticles
|
|
6
6
|
* How to use? : Check the GitHub README
|
|
7
|
-
* v3.0
|
|
7
|
+
* v3.1.0
|
|
8
8
|
*/
|
|
9
9
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
10
10
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
@@ -114,32 +114,39 @@ class ByteStream {
|
|
|
114
114
|
return this.data[this.pos++];
|
|
115
115
|
}
|
|
116
116
|
nextTwoBytes() {
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
const increment = 2,
|
|
118
|
+
previous = 1,
|
|
119
|
+
shift = 8;
|
|
120
|
+
this.pos += increment;
|
|
121
|
+
return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
|
|
119
122
|
}
|
|
120
123
|
readSubBlocks() {
|
|
121
124
|
let blockString = "",
|
|
122
125
|
size = 0;
|
|
126
|
+
const minCount = 0,
|
|
127
|
+
emptySize = 0;
|
|
123
128
|
do {
|
|
124
129
|
size = this.data[this.pos++];
|
|
125
|
-
for (let count = size; --count >=
|
|
126
|
-
} while (size !==
|
|
130
|
+
for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {}
|
|
131
|
+
} while (size !== emptySize);
|
|
127
132
|
return blockString;
|
|
128
133
|
}
|
|
129
134
|
readSubBlocksBin() {
|
|
130
135
|
let size = 0,
|
|
131
136
|
len = 0;
|
|
132
|
-
|
|
137
|
+
const emptySize = 0,
|
|
138
|
+
increment = 1;
|
|
139
|
+
for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
|
|
133
140
|
len += size;
|
|
134
141
|
}
|
|
135
142
|
const blockData = new Uint8Array(len);
|
|
136
|
-
for (let i = 0;
|
|
137
|
-
for (let count = size; --count >=
|
|
143
|
+
for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
|
|
144
|
+
for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {}
|
|
138
145
|
}
|
|
139
146
|
return blockData;
|
|
140
147
|
}
|
|
141
148
|
skipSubBlocks() {
|
|
142
|
-
for (; this.data[this.pos] !==
|
|
149
|
+
for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {}
|
|
143
150
|
this.pos++;
|
|
144
151
|
}
|
|
145
152
|
}
|
|
@@ -158,7 +165,7 @@ function parseColorTable(byteStream, count) {
|
|
|
158
165
|
}
|
|
159
166
|
return colors;
|
|
160
167
|
}
|
|
161
|
-
|
|
168
|
+
function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
|
|
162
169
|
switch (byteStream.nextByte()) {
|
|
163
170
|
case 249:
|
|
164
171
|
{
|
|
@@ -240,11 +247,19 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
240
247
|
g,
|
|
241
248
|
b
|
|
242
249
|
} = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
|
|
250
|
+
if (index !== getTransparencyIndex(null)) {
|
|
251
|
+
return {
|
|
252
|
+
r,
|
|
253
|
+
g,
|
|
254
|
+
b,
|
|
255
|
+
a: 255
|
|
256
|
+
};
|
|
257
|
+
}
|
|
243
258
|
return {
|
|
244
259
|
r,
|
|
245
260
|
g,
|
|
246
261
|
b,
|
|
247
|
-
a:
|
|
262
|
+
a: avgAlpha ? ~~((r + g + b) / 3) : 0
|
|
248
263
|
};
|
|
249
264
|
};
|
|
250
265
|
const image = (() => {
|
|
@@ -273,7 +288,10 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
273
288
|
if (interlacedFlag) {
|
|
274
289
|
for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
|
|
275
290
|
if (InterlaceOffsets[pass] < frame.height) {
|
|
276
|
-
|
|
291
|
+
let pixelPos = 0,
|
|
292
|
+
lineIndex = 0,
|
|
293
|
+
exit = false;
|
|
294
|
+
while (!exit) {
|
|
277
295
|
const last = code;
|
|
278
296
|
code = readBits(pos, size);
|
|
279
297
|
pos += size + 1;
|
|
@@ -289,13 +307,13 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
289
307
|
} else if (last !== clearCode) {
|
|
290
308
|
dic.push(dic[last].concat(dic[code][0]));
|
|
291
309
|
}
|
|
292
|
-
for (
|
|
310
|
+
for (const item of dic[code]) {
|
|
293
311
|
const {
|
|
294
312
|
r,
|
|
295
313
|
g,
|
|
296
314
|
b,
|
|
297
315
|
a
|
|
298
|
-
} = getColor(
|
|
316
|
+
} = getColor(item);
|
|
299
317
|
image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width + InterlaceSteps[pass] * lineIndex + pixelPos % (frame.width * 4));
|
|
300
318
|
pixelPos += 4;
|
|
301
319
|
}
|
|
@@ -306,7 +324,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
306
324
|
if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
|
|
307
325
|
lineIndex++;
|
|
308
326
|
if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
|
|
309
|
-
|
|
327
|
+
exit = true;
|
|
310
328
|
}
|
|
311
329
|
}
|
|
312
330
|
}
|
|
@@ -322,7 +340,13 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
322
340
|
frame.image = image;
|
|
323
341
|
frame.bitmap = await createImageBitmap(image);
|
|
324
342
|
} else {
|
|
325
|
-
|
|
343
|
+
let code = 0,
|
|
344
|
+
size = minCodeSize + 1,
|
|
345
|
+
pos = 0,
|
|
346
|
+
pixelPos = -4,
|
|
347
|
+
exit = false;
|
|
348
|
+
const dic = [[0]];
|
|
349
|
+
while (!exit) {
|
|
326
350
|
const last = code;
|
|
327
351
|
code = readBits(pos, size);
|
|
328
352
|
pos += size;
|
|
@@ -334,6 +358,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
334
358
|
}
|
|
335
359
|
} else {
|
|
336
360
|
if (code === clearCode + 1) {
|
|
361
|
+
exit = true;
|
|
337
362
|
break;
|
|
338
363
|
}
|
|
339
364
|
if (code >= dic.length) {
|
|
@@ -341,13 +366,13 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
341
366
|
} else if (last !== clearCode) {
|
|
342
367
|
dic.push(dic[last].concat(dic[code][0]));
|
|
343
368
|
}
|
|
344
|
-
for (
|
|
369
|
+
for (const item of dic[code]) {
|
|
345
370
|
const {
|
|
346
371
|
r,
|
|
347
372
|
g,
|
|
348
373
|
b,
|
|
349
374
|
a
|
|
350
|
-
} = getColor(
|
|
375
|
+
} = getColor(item);
|
|
351
376
|
image.data.set([r, g, b, a], pixelPos += 4);
|
|
352
377
|
}
|
|
353
378
|
if (dic.length >= 1 << size && size < 0xc) {
|
|
@@ -374,7 +399,7 @@ async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTranspare
|
|
|
374
399
|
await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);
|
|
375
400
|
break;
|
|
376
401
|
case 33:
|
|
377
|
-
|
|
402
|
+
parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
|
|
378
403
|
break;
|
|
379
404
|
default:
|
|
380
405
|
throw new EvalError("undefined block found");
|
|
@@ -515,6 +540,9 @@ async function decodeGIF(gifURL, progressCallback, avgAlpha) {
|
|
|
515
540
|
;// CONCATENATED MODULE: ./dist/browser/Utils.js
|
|
516
541
|
|
|
517
542
|
|
|
543
|
+
const stringStart = 0,
|
|
544
|
+
defaultLoopCount = 0,
|
|
545
|
+
defaultOpacity = 1;
|
|
518
546
|
const currentColorRegex = /(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;
|
|
519
547
|
function replaceColorSvg(imageShape, color, opacity) {
|
|
520
548
|
const {
|
|
@@ -528,7 +556,7 @@ function replaceColorSvg(imageShape, color, opacity) {
|
|
|
528
556
|
return svgData.replace(currentColorRegex, () => colorStyle);
|
|
529
557
|
}
|
|
530
558
|
const preFillIndex = svgData.indexOf(">");
|
|
531
|
-
return `${svgData.substring(
|
|
559
|
+
return `${svgData.substring(stringStart, preFillIndex)} fill="${colorStyle}"${svgData.substring(preFillIndex)}`;
|
|
532
560
|
}
|
|
533
561
|
async function loadImage(image) {
|
|
534
562
|
return new Promise(resolve => {
|
|
@@ -557,8 +585,8 @@ async function loadGifImage(image) {
|
|
|
557
585
|
image.loading = true;
|
|
558
586
|
try {
|
|
559
587
|
image.gifData = await decodeGIF(image.source);
|
|
560
|
-
image.gifLoopCount = getGIFLoopAmount(image.gifData) ??
|
|
561
|
-
if (image.gifLoopCount
|
|
588
|
+
image.gifLoopCount = getGIFLoopAmount(image.gifData) ?? defaultLoopCount;
|
|
589
|
+
if (!image.gifLoopCount) {
|
|
562
590
|
image.gifLoopCount = Infinity;
|
|
563
591
|
}
|
|
564
592
|
} catch {
|
|
@@ -582,7 +610,7 @@ async function downloadSvgImage(image) {
|
|
|
582
610
|
image.loading = false;
|
|
583
611
|
}
|
|
584
612
|
function replaceImageColor(image, imageData, color, particle) {
|
|
585
|
-
const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ??
|
|
613
|
+
const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity),
|
|
586
614
|
imageRes = {
|
|
587
615
|
color,
|
|
588
616
|
gif: imageData.gif,
|
|
@@ -608,7 +636,7 @@ function replaceImageColor(image, imageData, color, particle) {
|
|
|
608
636
|
resolve(imageRes);
|
|
609
637
|
domUrl.revokeObjectURL(url);
|
|
610
638
|
});
|
|
611
|
-
|
|
639
|
+
const errorHandler = async () => {
|
|
612
640
|
domUrl.revokeObjectURL(url);
|
|
613
641
|
const img2 = {
|
|
614
642
|
...image,
|
|
@@ -619,13 +647,27 @@ function replaceImageColor(image, imageData, color, particle) {
|
|
|
619
647
|
imageRes.loaded = true;
|
|
620
648
|
imageRes.element = img2.element;
|
|
621
649
|
resolve(imageRes);
|
|
622
|
-
}
|
|
650
|
+
};
|
|
651
|
+
img.addEventListener("error", () => void errorHandler());
|
|
623
652
|
img.src = url;
|
|
624
653
|
});
|
|
625
654
|
}
|
|
626
655
|
;// CONCATENATED MODULE: ./dist/browser/ImageDrawer.js
|
|
627
656
|
|
|
628
657
|
|
|
658
|
+
const origin = {
|
|
659
|
+
x: 0,
|
|
660
|
+
y: 0
|
|
661
|
+
},
|
|
662
|
+
ImageDrawer_defaultLoopCount = 0,
|
|
663
|
+
defaultFrame = 0,
|
|
664
|
+
half = 0.5,
|
|
665
|
+
initialTime = 0,
|
|
666
|
+
firstIndex = 0,
|
|
667
|
+
ImageDrawer_double = 2,
|
|
668
|
+
defaultAlpha = 1,
|
|
669
|
+
sides = 12,
|
|
670
|
+
defaultRatio = 1;
|
|
629
671
|
class ImageDrawer {
|
|
630
672
|
constructor(engine) {
|
|
631
673
|
this.loadImageShape = async imageShape => {
|
|
@@ -669,18 +711,18 @@ class ImageDrawer {
|
|
|
669
711
|
}
|
|
670
712
|
offscreenContext.imageSmoothingQuality = "low";
|
|
671
713
|
offscreenContext.imageSmoothingEnabled = false;
|
|
672
|
-
offscreenContext.clearRect(
|
|
714
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
673
715
|
if (particle.gifLoopCount === undefined) {
|
|
674
|
-
particle.gifLoopCount = image.gifLoopCount ??
|
|
716
|
+
particle.gifLoopCount = image.gifLoopCount ?? ImageDrawer_defaultLoopCount;
|
|
675
717
|
}
|
|
676
|
-
let frameIndex = particle.gifFrame ??
|
|
718
|
+
let frameIndex = particle.gifFrame ?? defaultFrame;
|
|
677
719
|
const pos = {
|
|
678
|
-
x: -image.gifData.width *
|
|
679
|
-
y: -image.gifData.height *
|
|
720
|
+
x: -image.gifData.width * half,
|
|
721
|
+
y: -image.gifData.height * half
|
|
680
722
|
},
|
|
681
723
|
frame = image.gifData.frames[frameIndex];
|
|
682
724
|
if (particle.gifTime === undefined) {
|
|
683
|
-
particle.gifTime =
|
|
725
|
+
particle.gifTime = initialTime;
|
|
684
726
|
}
|
|
685
727
|
if (!frame.bitmap) {
|
|
686
728
|
return;
|
|
@@ -694,7 +736,7 @@ class ImageDrawer {
|
|
|
694
736
|
case 0:
|
|
695
737
|
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
696
738
|
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
697
|
-
offscreenContext.clearRect(
|
|
739
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
698
740
|
break;
|
|
699
741
|
case 1:
|
|
700
742
|
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
@@ -703,20 +745,20 @@ class ImageDrawer {
|
|
|
703
745
|
case 2:
|
|
704
746
|
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
705
747
|
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
706
|
-
offscreenContext.clearRect(
|
|
707
|
-
if (image.gifData.globalColorTable.length
|
|
708
|
-
offscreenContext.putImageData(image.gifData.frames[
|
|
748
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
749
|
+
if (!image.gifData.globalColorTable.length) {
|
|
750
|
+
offscreenContext.putImageData(image.gifData.frames[firstIndex].image, pos.x + frame.left, pos.y + frame.top);
|
|
709
751
|
} else {
|
|
710
752
|
offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
|
|
711
753
|
}
|
|
712
754
|
break;
|
|
713
755
|
case 3:
|
|
714
756
|
{
|
|
715
|
-
const previousImageData = offscreenContext.getImageData(
|
|
757
|
+
const previousImageData = offscreenContext.getImageData(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
716
758
|
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
717
759
|
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
718
|
-
offscreenContext.clearRect(
|
|
719
|
-
offscreenContext.putImageData(previousImageData,
|
|
760
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
761
|
+
offscreenContext.putImageData(previousImageData, origin.x, origin.y);
|
|
720
762
|
}
|
|
721
763
|
break;
|
|
722
764
|
}
|
|
@@ -724,11 +766,11 @@ class ImageDrawer {
|
|
|
724
766
|
if (particle.gifTime > frame.delayTime) {
|
|
725
767
|
particle.gifTime -= frame.delayTime;
|
|
726
768
|
if (++frameIndex >= image.gifData.frames.length) {
|
|
727
|
-
if (--particle.gifLoopCount <=
|
|
769
|
+
if (--particle.gifLoopCount <= ImageDrawer_defaultLoopCount) {
|
|
728
770
|
return;
|
|
729
771
|
}
|
|
730
|
-
frameIndex =
|
|
731
|
-
offscreenContext.clearRect(
|
|
772
|
+
frameIndex = firstIndex;
|
|
773
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
732
774
|
}
|
|
733
775
|
particle.gifFrame = frameIndex;
|
|
734
776
|
}
|
|
@@ -739,13 +781,13 @@ class ImageDrawer {
|
|
|
739
781
|
x: -radius,
|
|
740
782
|
y: -radius
|
|
741
783
|
},
|
|
742
|
-
diameter = radius *
|
|
784
|
+
diameter = radius * ImageDrawer_double;
|
|
743
785
|
context.drawImage(element, pos.x, pos.y, diameter, diameter / ratio);
|
|
744
786
|
}
|
|
745
|
-
context.globalAlpha =
|
|
787
|
+
context.globalAlpha = defaultAlpha;
|
|
746
788
|
}
|
|
747
789
|
getSidesCount() {
|
|
748
|
-
return
|
|
790
|
+
return sides;
|
|
749
791
|
}
|
|
750
792
|
async init(container) {
|
|
751
793
|
const options = container.actualOptions;
|
|
@@ -769,7 +811,7 @@ class ImageDrawer {
|
|
|
769
811
|
}
|
|
770
812
|
const image = this._engine.images.find(t => t.name === imageData.name || t.source === imageData.src);
|
|
771
813
|
if (!image) {
|
|
772
|
-
this.loadImageShape(imageData).then(() => {
|
|
814
|
+
void this.loadImageShape(imageData).then(() => {
|
|
773
815
|
this.loadShape(particle);
|
|
774
816
|
});
|
|
775
817
|
}
|
|
@@ -798,7 +840,7 @@ class ImageDrawer {
|
|
|
798
840
|
});
|
|
799
841
|
return;
|
|
800
842
|
}
|
|
801
|
-
(async () => {
|
|
843
|
+
void (async () => {
|
|
802
844
|
let imageRes;
|
|
803
845
|
if (image.svgData && color) {
|
|
804
846
|
imageRes = await replaceImageColor(image, imageData, color, particle);
|
|
@@ -811,7 +853,7 @@ class ImageDrawer {
|
|
|
811
853
|
gifData: image.gifData,
|
|
812
854
|
gifLoopCount: image.gifLoopCount,
|
|
813
855
|
loaded: true,
|
|
814
|
-
ratio: imageData.width && imageData.height ? imageData.width / imageData.height : image.ratio ??
|
|
856
|
+
ratio: imageData.width && imageData.height ? imageData.width / imageData.height : image.ratio ?? defaultRatio,
|
|
815
857
|
replaceColor: replaceColor,
|
|
816
858
|
source: imageData.src
|
|
817
859
|
};
|
|
@@ -873,7 +915,7 @@ class ImagePreloaderPlugin {
|
|
|
873
915
|
return {};
|
|
874
916
|
}
|
|
875
917
|
loadOptions(options, source) {
|
|
876
|
-
if (!source
|
|
918
|
+
if (!source?.preload) {
|
|
877
919
|
return;
|
|
878
920
|
}
|
|
879
921
|
if (!options.preload) {
|
|
@@ -900,6 +942,7 @@ class ImagePreloaderPlugin {
|
|
|
900
942
|
|
|
901
943
|
|
|
902
944
|
|
|
945
|
+
const extLength = 3;
|
|
903
946
|
function addLoadImageToEngine(engine) {
|
|
904
947
|
if (engine.loadImage) {
|
|
905
948
|
return;
|
|
@@ -919,14 +962,19 @@ function addLoadImageToEngine(engine) {
|
|
|
919
962
|
gif: data.gif ?? false,
|
|
920
963
|
name: data.name ?? data.src,
|
|
921
964
|
source: data.src,
|
|
922
|
-
type: data.src.substring(data.src.length -
|
|
965
|
+
type: data.src.substring(data.src.length - extLength),
|
|
923
966
|
error: false,
|
|
924
967
|
loading: true,
|
|
925
968
|
replaceColor: data.replaceColor,
|
|
926
969
|
ratio: data.width && data.height ? data.width / data.height : undefined
|
|
927
970
|
};
|
|
928
971
|
engine.images.push(image);
|
|
929
|
-
|
|
972
|
+
let imageFunc;
|
|
973
|
+
if (data.gif) {
|
|
974
|
+
imageFunc = loadGifImage;
|
|
975
|
+
} else {
|
|
976
|
+
imageFunc = data.replaceColor ? downloadSvgImage : loadImage;
|
|
977
|
+
}
|
|
930
978
|
await imageFunc(image);
|
|
931
979
|
} catch {
|
|
932
980
|
throw new Error(`${engine_root_window_.errorPrefix} ${data.name ?? data.src} not found`);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! For license information please see tsparticles.shape.image.min.js.LICENSE.txt */
|
|
2
|
-
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],t);else{var a="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in a)("object"==typeof exports?exports:e)[o]=a[o]}}(this,(e=>(()=>{"use strict";var t={533:t=>{t.exports=e}},a={};function o(e){var i=a[e];if(void 0!==i)return i.exports;var r=a[e]={exports:{}};return t[e](r,r.exports,o),r.exports}o.d=(e,t)=>{for(var a in t)o.o(t,a)&&!o.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};return(()=>{o.r(i),o.d(i,{loadImageShape:()=>u});var e=o(533);const t=[0,4,2,1],a=[8,8,4,2];class r{constructor(e){this.pos=0,this.data=new Uint8ClampedArray(e)}getString(e){const t=this.data.slice(this.pos,this.pos+e);return this.pos+=t.length,t.reduce(((e,t)=>e+String.fromCharCode(t)),"")}nextByte(){return this.data[this.pos++]}nextTwoBytes(){return this.pos+=2,this.data[this.pos-2]+(this.data[this.pos-1]<<8)}readSubBlocks(){let e="",t=0;do{t=this.data[this.pos++];for(let a=t;--a>=0;e+=String.fromCharCode(this.data[this.pos++]));}while(0!==t);return e}readSubBlocksBin(){let e=0,t=0;for(let a=0;0!==(e=this.data[this.pos+a]);a+=e+1)t+=e;const a=new Uint8Array(t);for(let t=0;0!==(e=this.data[this.pos++]);)for(let o=e;--o>=0;a[t++]=this.data[this.pos++]);return a}skipSubBlocks(){for(;0!==this.data[this.pos];this.pos+=this.data[this.pos]+1);this.pos++}}function n(e,t){const a=[];for(let o=0;o<t;o++)a.push({r:e.data[e.pos],g:e.data[e.pos+1],b:e.data[e.pos+2]}),e.pos+=3;return a}async function s(e,o,i,r,s,l){switch(e.nextByte()){case 59:return!0;case 44:await async function(e,o,i,r,s,l){const c=o.frames[r(!0)];c.left=e.nextTwoBytes(),c.top=e.nextTwoBytes(),c.width=e.nextTwoBytes(),c.height=e.nextTwoBytes();const g=e.nextByte(),h=128==(128&g),d=64==(64&g);c.sortFlag=32==(32&g),c.reserved=(24&g)>>>3;const f=1<<1+(7&g);h&&(c.localColorTable=n(e,f));const p=e=>{const{r:t,g:a,b:r}=(h?c.localColorTable:o.globalColorTable)[e];return{r:t,g:a,b:r,a:e===s(null)?i?~~((t+a+r)/3):0:255}},m=(()=>{try{return new ImageData(c.width,c.height,{colorSpace:"srgb"})}catch(e){if(e instanceof DOMException&&"IndexSizeError"===e.name)return null;throw e}})();if(null==m)throw new EvalError("GIF frame size is to large");const u=e.nextByte(),w=e.readSubBlocksBin(),y=1<<u,b=(e,t)=>{const a=e>>>3,o=7&e;return(w[a]+(w[a+1]<<8)+(w[a+2]<<16)&(1<<t)-1<<o)>>>o};if(d){for(let i=0,n=u+1,s=0,g=[[0]],h=0;h<4;h++){if(t[h]<c.height)for(let e=0,o=0;;){const r=i;if(i=b(s,n),s+=n+1,i===y){n=u+1,g.length=y+2;for(let e=0;e<g.length;e++)g[e]=e<y?[e]:[]}else{i>=g.length?g.push(g[r].concat(g[r][0])):r!==y&&g.push(g[r].concat(g[i][0]));for(let r=0;r<g[i].length;r++){const{r:n,g:s,b:l,a:d}=p(g[i][r]);m.data.set([n,s,l,d],t[h]*c.width+a[h]*o+e%(4*c.width)),e+=4}g.length===1<<n&&n<12&&n++}if(e===4*c.width*(o+1)&&(o++,t[h]+a[h]*o>=c.height))break}l?.(e.pos/(e.data.length-1),r(!1)+1,m,{x:c.left,y:c.top},{width:o.width,height:o.height})}c.image=m,c.bitmap=await createImageBitmap(m)}else{for(let e=0,t=u+1,a=0,o=[[0]],i=-4;;){const r=e;if(e=b(a,t),a+=t,e===y){t=u+1,o.length=y+2;for(let e=0;e<o.length;e++)o[e]=e<y?[e]:[]}else{if(e===y+1)break;e>=o.length?o.push(o[r].concat(o[r][0])):r!==y&&o.push(o[r].concat(o[e][0]));for(let t=0;t<o[e].length;t++){const{r:a,g:r,b:n,a:s}=p(o[e][t]);m.data.set([a,r,n,s],i+=4)}o.length>=1<<t&&t<12&&t++}}c.image=m,c.bitmap=await createImageBitmap(m),l?.((e.pos+1)/e.data.length,r(!1)+1,c.image,{x:c.left,y:c.top},{width:o.width,height:o.height})}}(e,o,i,r,s,l);break;case 33:await async function(e,t,a,o){switch(e.nextByte()){case 249:{const i=t.frames[a(!1)];e.pos++;const r=e.nextByte();i.GCreserved=(224&r)>>>5,i.disposalMethod=(28&r)>>>2,i.userInputDelayFlag=2==(2&r);const n=1==(1&r);i.delayTime=10*e.nextTwoBytes();const s=e.nextByte();n&&o(s),e.pos++;break}case 255:{e.pos++;const a={identifier:e.getString(8),authenticationCode:e.getString(3),data:e.readSubBlocksBin()};t.applicationExtensions.push(a);break}case 254:t.comments.push([a(!1),e.readSubBlocks()]);break;case 1:if(0===t.globalColorTable.length)throw new EvalError("plain text extension without global color table");e.pos++,t.frames[a(!1)].plainTextData={left:e.nextTwoBytes(),top:e.nextTwoBytes(),width:e.nextTwoBytes(),height:e.nextTwoBytes(),charSize:{width:e.nextTwoBytes(),height:e.nextTwoBytes()},foregroundColor:e.nextByte(),backgroundColor:e.nextByte(),text:e.readSubBlocks()};break;default:e.skipSubBlocks()}}(e,o,r,s);break;default:throw new EvalError("undefined block found")}return!1}const l=/(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;async function c(t){return new Promise((a=>{t.loading=!0;const o=new Image;t.element=o,o.addEventListener("load",(()=>{t.loading=!1,a()})),o.addEventListener("error",(()=>{t.element=void 0,t.error=!0,t.loading=!1,(0,e.getLogger)().error(`${e.errorPrefix} loading image: ${t.source}`),a()})),o.src=t.source}))}async function g(e){if("gif"===e.type){e.loading=!0;try{e.gifData=await async function(e,t,a){a||(a=!1);const o=await fetch(e);if(!o.ok&&404===o.status)throw new EvalError("file not found");const i=await o.arrayBuffer(),l={width:0,height:0,totalTime:0,colorRes:0,pixelAspectRatio:0,frames:[],sortFlag:!1,globalColorTable:[],backgroundImage:new ImageData(1,1,{colorSpace:"srgb"}),comments:[],applicationExtensions:[]},c=new r(new Uint8ClampedArray(i));if("GIF89a"!==c.getString(6))throw new Error("not a supported GIF file");l.width=c.nextTwoBytes(),l.height=c.nextTwoBytes();const g=c.nextByte(),h=128==(128&g);l.colorRes=(112&g)>>>4,l.sortFlag=8==(8&g);const d=1<<1+(7&g),f=c.nextByte();l.pixelAspectRatio=c.nextByte(),0!==l.pixelAspectRatio&&(l.pixelAspectRatio=(l.pixelAspectRatio+15)/64),h&&(l.globalColorTable=n(c,d));const p=(()=>{try{return new ImageData(l.width,l.height,{colorSpace:"srgb"})}catch(e){if(e instanceof DOMException&&"IndexSizeError"===e.name)return null;throw e}})();if(null==p)throw new Error("GIF frame size is to large");const{r:m,g:u,b:w}=l.globalColorTable[f];p.data.set(h?[m,u,w,255]:[0,0,0,0]);for(let e=4;e<p.data.length;e*=2)p.data.copyWithin(e,0,e);l.backgroundImage=p;let y=-1,b=!0,x=-1;const C=e=>(e&&(b=!0),y),v=e=>(null!=e&&(x=e),x);try{do{b&&(l.frames.push({left:0,top:0,width:0,height:0,disposalMethod:0,image:new ImageData(1,1,{colorSpace:"srgb"}),plainTextData:null,userInputDelayFlag:!1,delayTime:0,sortFlag:!1,localColorTable:[],reserved:0,GCreserved:0}),y++,x=-1,b=!1)}while(!await s(c,l,a,C,v,t));l.frames.length--;for(const e of l.frames){if(e.userInputDelayFlag&&0===e.delayTime){l.totalTime=1/0;break}l.totalTime+=e.delayTime}return l}catch(e){if(e instanceof EvalError)throw new Error(`error while parsing frame ${y} "${e.message}"`);throw e}}(e.source),e.gifLoopCount=function(e){for(const t of e.applicationExtensions)if(t.identifier+t.authenticationCode==="NETSCAPE2.0")return t.data[1]+(t.data[2]<<8);return NaN}(e.gifData)??0,0===e.gifLoopCount&&(e.gifLoopCount=1/0)}catch{e.error=!0}e.loading=!1}else await c(e)}async function h(t){if("svg"!==t.type)return void await c(t);t.loading=!0;const a=await fetch(t.source);a.ok?t.svgData=await a.text():((0,e.getLogger)().error(`${e.errorPrefix} Image not found`),t.error=!0),t.loading=!1}function d(t,a,o,i){const r=function(t,a,o){const{svgData:i}=t;if(!i)return"";const r=(0,e.getStyleFromHsl)(a,o);if(i.includes("fill"))return i.replace(l,(()=>r));const n=i.indexOf(">");return`${i.substring(0,n)} fill="${r}"${i.substring(n)}`}(t,o,i.opacity?.value??1),n={color:o,gif:a.gif,data:{...t,svgData:r},loaded:!1,ratio:a.width/a.height,replaceColor:a.replaceColor,source:a.src};return new Promise((e=>{const a=new Blob([r],{type:"image/svg+xml"}),o=URL||window.URL||window.webkitURL||window,i=o.createObjectURL(a),s=new Image;s.addEventListener("load",(()=>{n.loaded=!0,n.element=s,e(n),o.revokeObjectURL(i)})),s.addEventListener("error",(async()=>{o.revokeObjectURL(i);const a={...t,error:!1,loading:!0};await c(a),n.loaded=!0,n.element=a.element,e(n)})),s.src=i}))}class f{constructor(t){this.loadImageShape=async t=>{if(!this._engine.loadImage)throw new Error(`${e.errorPrefix} image shape not initialized`);await this._engine.loadImage({gif:t.gif,name:t.name,replaceColor:t.replaceColor??!1,src:t.src})},this._engine=t}addImage(e){this._engine.images||(this._engine.images=[]),this._engine.images.push(e)}draw(e){const{context:t,radius:a,particle:o,opacity:i,delta:r}=e,n=o.image,s=n?.element;if(n){if(t.globalAlpha=i,n.gif&&n.gifData){const e=new OffscreenCanvas(n.gifData.width,n.gifData.height),i=e.getContext("2d");if(!i)throw new Error("could not create offscreen canvas context");i.imageSmoothingQuality="low",i.imageSmoothingEnabled=!1,i.clearRect(0,0,e.width,e.height),void 0===o.gifLoopCount&&(o.gifLoopCount=n.gifLoopCount??0);let s=o.gifFrame??0;const l={x:.5*-n.gifData.width,y:.5*-n.gifData.height},c=n.gifData.frames[s];if(void 0===o.gifTime&&(o.gifTime=0),!c.bitmap)return;switch(t.scale(a/n.gifData.width,a/n.gifData.height),c.disposalMethod){case 4:case 5:case 6:case 7:case 0:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(0,0,e.width,e.height);break;case 1:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y);break;case 2:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(0,0,e.width,e.height),0===n.gifData.globalColorTable.length?i.putImageData(n.gifData.frames[0].image,l.x+c.left,l.y+c.top):i.putImageData(n.gifData.backgroundImage,l.x,l.y);break;case 3:{const a=i.getImageData(0,0,e.width,e.height);i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(0,0,e.width,e.height),i.putImageData(a,0,0)}}if(o.gifTime+=r.value,o.gifTime>c.delayTime){if(o.gifTime-=c.delayTime,++s>=n.gifData.frames.length){if(--o.gifLoopCount<=0)return;s=0,i.clearRect(0,0,e.width,e.height)}o.gifFrame=s}t.scale(n.gifData.width/a,n.gifData.height/a)}else if(s){const e=n.ratio,o={x:-a,y:-a},i=2*a;t.drawImage(s,o.x,o.y,i,i/e)}t.globalAlpha=1}}getSidesCount(){return 12}async init(e){const t=e.actualOptions;if(t.preload&&this._engine.loadImage)for(const e of t.preload)await this._engine.loadImage(e)}loadShape(e){if("image"!==e.shape&&"images"!==e.shape)return;this._engine.images||(this._engine.images=[]);const t=e.shapeData;if(!t)return;this._engine.images.find((e=>e.name===t.name||e.source===t.src))||this.loadImageShape(t).then((()=>{this.loadShape(e)}))}particleInit(e,t){if("image"!==t.shape&&"images"!==t.shape)return;this._engine.images||(this._engine.images=[]);const a=this._engine.images,o=t.shapeData;if(!o)return;const i=t.getFillColor(),r=a.find((e=>e.name===o.name||e.source===o.src));if(!r)return;const n=o.replaceColor??r.replaceColor;r.loading?setTimeout((()=>{this.particleInit(e,t)})):(async()=>{let e;e=r.svgData&&i?await d(r,o,i,t):{color:i,data:r,element:r.element,gif:r.gif,gifData:r.gifData,gifLoopCount:r.gifLoopCount,loaded:!0,ratio:o.width&&o.height?o.width/o.height:r.ratio??1,replaceColor:n,source:o.src},e.ratio||(e.ratio=1);const a={image:e,fill:o.fill??t.shapeFill,close:o.close??t.shapeClose};t.image=a.image,t.shapeFill=a.fill,t.shapeClose=a.close})()}}class p{constructor(){this.src="",this.gif=!1}load(e){e&&(void 0!==e.gif&&(this.gif=e.gif),void 0!==e.height&&(this.height=e.height),void 0!==e.name&&(this.name=e.name),void 0!==e.replaceColor&&(this.replaceColor=e.replaceColor),void 0!==e.src&&(this.src=e.src),void 0!==e.width&&(this.width=e.width))}}class m{constructor(e){this.id="imagePreloader",this._engine=e}getPlugin(){return{}}loadOptions(e,t){if(!t||!t.preload)return;e.preload||(e.preload=[]);const a=e.preload;for(const e of t.preload){const t=a.find((t=>t.name===e.name||t.src===e.src));if(t)t.load(e);else{const t=new p;t.load(e),a.push(t)}}}needsPlugin(){return!0}}async function u(t,a=!0){!function(t){t.loadImage||(t.loadImage=async a=>{if(!a.name&&!a.src)throw new Error(`${e.errorPrefix} no image source provided`);if(t.images||(t.images=[]),!t.images.find((e=>e.name===a.name||e.source===a.src)))try{const e={gif:a.gif??!1,name:a.name??a.src,source:a.src,type:a.src.substring(a.src.length-3),error:!1,loading:!0,replaceColor:a.replaceColor,ratio:a.width&&a.height?a.width/a.height:void 0};t.images.push(e);const o=a.gif?g:a.replaceColor?h:c;await o(e)}catch{throw new Error(`${e.errorPrefix} ${a.name??a.src} not found`)}})}(t);const o=new m(t);await t.addPlugin(o,a),await t.addShape(["image","images"],new f(t),a)}})(),i})()));
|
|
2
|
+
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],t);else{var a="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in a)("object"==typeof exports?exports:e)[o]=a[o]}}(this,(e=>(()=>{"use strict";var t={533:t=>{t.exports=e}},a={};function o(e){var i=a[e];if(void 0!==i)return i.exports;var r=a[e]={exports:{}};return t[e](r,r.exports,o),r.exports}o.d=(e,t)=>{for(var a in t)o.o(t,a)&&!o.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};return(()=>{o.r(i),o.d(i,{loadImageShape:()=>C});var e=o(533);const t=[0,4,2,1],a=[8,8,4,2];class r{constructor(e){this.pos=0,this.data=new Uint8ClampedArray(e)}getString(e){const t=this.data.slice(this.pos,this.pos+e);return this.pos+=t.length,t.reduce(((e,t)=>e+String.fromCharCode(t)),"")}nextByte(){return this.data[this.pos++]}nextTwoBytes(){return this.pos+=2,this.data[this.pos-2]+(this.data[this.pos-1]<<8)}readSubBlocks(){let e="",t=0;do{t=this.data[this.pos++];for(let a=t;--a>=0;e+=String.fromCharCode(this.data[this.pos++]));}while(0!==t);return e}readSubBlocksBin(){let e=0,t=0;for(let a=0;0!==e;a+=e+1,e=this.data[this.pos+a])t+=e;const a=new Uint8Array(t);for(let t=0;0!==e;e=this.data[this.pos++])for(let o=e;--o>=0;a[t++]=this.data[this.pos++]);return a}skipSubBlocks(){for(const e=1,t=0;this.data[this.pos]!==t;this.pos+=this.data[this.pos]+e);this.pos++}}function n(e,t){const a=[];for(let o=0;o<t;o++)a.push({r:e.data[e.pos],g:e.data[e.pos+1],b:e.data[e.pos+2]}),e.pos+=3;return a}async function s(e,o,i,r,s,l){switch(e.nextByte()){case 59:return!0;case 44:await async function(e,o,i,r,s,l){const c=o.frames[r(!0)];c.left=e.nextTwoBytes(),c.top=e.nextTwoBytes(),c.width=e.nextTwoBytes(),c.height=e.nextTwoBytes();const g=e.nextByte(),h=128==(128&g),d=64==(64&g);c.sortFlag=32==(32&g),c.reserved=(24&g)>>>3;const f=1<<1+(7&g);h&&(c.localColorTable=n(e,f));const p=e=>{const{r:t,g:a,b:r}=(h?c.localColorTable:o.globalColorTable)[e];return e!==s(null)?{r:t,g:a,b:r,a:255}:{r:t,g:a,b:r,a:i?~~((t+a+r)/3):0}},m=(()=>{try{return new ImageData(c.width,c.height,{colorSpace:"srgb"})}catch(e){if(e instanceof DOMException&&"IndexSizeError"===e.name)return null;throw e}})();if(null==m)throw new EvalError("GIF frame size is to large");const u=e.nextByte(),w=e.readSubBlocksBin(),y=1<<u,b=(e,t)=>{const a=e>>>3,o=7&e;return(w[a]+(w[a+1]<<8)+(w[a+2]<<16)&(1<<t)-1<<o)>>>o};if(d){for(let i=0,n=u+1,s=0,g=[[0]],h=0;h<4;h++){if(t[h]<c.height){let e=0,o=0,r=!1;for(;!r;){const l=i;if(i=b(s,n),s+=n+1,i===y){n=u+1,g.length=y+2;for(let e=0;e<g.length;e++)g[e]=e<y?[e]:[]}else{i>=g.length?g.push(g[l].concat(g[l][0])):l!==y&&g.push(g[l].concat(g[i][0]));for(const r of g[i]){const{r:i,g:n,b:s,a:l}=p(r);m.data.set([i,n,s,l],t[h]*c.width+a[h]*o+e%(4*c.width)),e+=4}g.length===1<<n&&n<12&&n++}e===4*c.width*(o+1)&&(o++,t[h]+a[h]*o>=c.height&&(r=!0))}}l?.(e.pos/(e.data.length-1),r(!1)+1,m,{x:c.left,y:c.top},{width:o.width,height:o.height})}c.image=m,c.bitmap=await createImageBitmap(m)}else{let t=0,a=u+1,i=0,n=-4,s=!1;const g=[[0]];for(;!s;){const e=t;if(t=b(i,a),i+=a,t===y){a=u+1,g.length=y+2;for(let e=0;e<g.length;e++)g[e]=e<y?[e]:[]}else{if(t===y+1){s=!0;break}t>=g.length?g.push(g[e].concat(g[e][0])):e!==y&&g.push(g[e].concat(g[t][0]));for(const e of g[t]){const{r:t,g:a,b:o,a:i}=p(e);m.data.set([t,a,o,i],n+=4)}g.length>=1<<a&&a<12&&a++}}c.image=m,c.bitmap=await createImageBitmap(m),l?.((e.pos+1)/e.data.length,r(!1)+1,c.image,{x:c.left,y:c.top},{width:o.width,height:o.height})}}(e,o,i,r,s,l);break;case 33:!function(e,t,a,o){switch(e.nextByte()){case 249:{const i=t.frames[a(!1)];e.pos++;const r=e.nextByte();i.GCreserved=(224&r)>>>5,i.disposalMethod=(28&r)>>>2,i.userInputDelayFlag=2==(2&r);const n=1==(1&r);i.delayTime=10*e.nextTwoBytes();const s=e.nextByte();n&&o(s),e.pos++;break}case 255:{e.pos++;const a={identifier:e.getString(8),authenticationCode:e.getString(3),data:e.readSubBlocksBin()};t.applicationExtensions.push(a);break}case 254:t.comments.push([a(!1),e.readSubBlocks()]);break;case 1:if(0===t.globalColorTable.length)throw new EvalError("plain text extension without global color table");e.pos++,t.frames[a(!1)].plainTextData={left:e.nextTwoBytes(),top:e.nextTwoBytes(),width:e.nextTwoBytes(),height:e.nextTwoBytes(),charSize:{width:e.nextTwoBytes(),height:e.nextTwoBytes()},foregroundColor:e.nextByte(),backgroundColor:e.nextByte(),text:e.readSubBlocks()};break;default:e.skipSubBlocks()}}(e,o,r,s);break;default:throw new EvalError("undefined block found")}return!1}const l=0,c=0,g=/(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;async function h(t){return new Promise((a=>{t.loading=!0;const o=new Image;t.element=o,o.addEventListener("load",(()=>{t.loading=!1,a()})),o.addEventListener("error",(()=>{t.element=void 0,t.error=!0,t.loading=!1,(0,e.getLogger)().error(`${e.errorPrefix} loading image: ${t.source}`),a()})),o.src=t.source}))}async function d(e){if("gif"===e.type){e.loading=!0;try{e.gifData=await async function(e,t,a){a||(a=!1);const o=await fetch(e);if(!o.ok&&404===o.status)throw new EvalError("file not found");const i=await o.arrayBuffer(),l={width:0,height:0,totalTime:0,colorRes:0,pixelAspectRatio:0,frames:[],sortFlag:!1,globalColorTable:[],backgroundImage:new ImageData(1,1,{colorSpace:"srgb"}),comments:[],applicationExtensions:[]},c=new r(new Uint8ClampedArray(i));if("GIF89a"!==c.getString(6))throw new Error("not a supported GIF file");l.width=c.nextTwoBytes(),l.height=c.nextTwoBytes();const g=c.nextByte(),h=128==(128&g);l.colorRes=(112&g)>>>4,l.sortFlag=8==(8&g);const d=1<<1+(7&g),f=c.nextByte();l.pixelAspectRatio=c.nextByte(),0!==l.pixelAspectRatio&&(l.pixelAspectRatio=(l.pixelAspectRatio+15)/64),h&&(l.globalColorTable=n(c,d));const p=(()=>{try{return new ImageData(l.width,l.height,{colorSpace:"srgb"})}catch(e){if(e instanceof DOMException&&"IndexSizeError"===e.name)return null;throw e}})();if(null==p)throw new Error("GIF frame size is to large");const{r:m,g:u,b:w}=l.globalColorTable[f];p.data.set(h?[m,u,w,255]:[0,0,0,0]);for(let e=4;e<p.data.length;e*=2)p.data.copyWithin(e,0,e);l.backgroundImage=p;let y=-1,b=!0,x=-1;const C=e=>(e&&(b=!0),y),v=e=>(null!=e&&(x=e),x);try{do{b&&(l.frames.push({left:0,top:0,width:0,height:0,disposalMethod:0,image:new ImageData(1,1,{colorSpace:"srgb"}),plainTextData:null,userInputDelayFlag:!1,delayTime:0,sortFlag:!1,localColorTable:[],reserved:0,GCreserved:0}),y++,x=-1,b=!1)}while(!await s(c,l,a,C,v,t));l.frames.length--;for(const e of l.frames){if(e.userInputDelayFlag&&0===e.delayTime){l.totalTime=1/0;break}l.totalTime+=e.delayTime}return l}catch(e){if(e instanceof EvalError)throw new Error(`error while parsing frame ${y} "${e.message}"`);throw e}}(e.source),e.gifLoopCount=function(e){for(const t of e.applicationExtensions)if(t.identifier+t.authenticationCode==="NETSCAPE2.0")return t.data[1]+(t.data[2]<<8);return NaN}(e.gifData)??c,e.gifLoopCount||(e.gifLoopCount=1/0)}catch{e.error=!0}e.loading=!1}else await h(e)}async function f(t){if("svg"!==t.type)return void await h(t);t.loading=!0;const a=await fetch(t.source);a.ok?t.svgData=await a.text():((0,e.getLogger)().error(`${e.errorPrefix} Image not found`),t.error=!0),t.loading=!1}function p(t,a,o,i){const r=function(t,a,o){const{svgData:i}=t;if(!i)return"";const r=(0,e.getStyleFromHsl)(a,o);if(i.includes("fill"))return i.replace(g,(()=>r));const n=i.indexOf(">");return`${i.substring(l,n)} fill="${r}"${i.substring(n)}`}(t,o,i.opacity?.value??1),n={color:o,gif:a.gif,data:{...t,svgData:r},loaded:!1,ratio:a.width/a.height,replaceColor:a.replaceColor,source:a.src};return new Promise((e=>{const a=new Blob([r],{type:"image/svg+xml"}),o=URL||window.URL||window.webkitURL||window,i=o.createObjectURL(a),s=new Image;s.addEventListener("load",(()=>{n.loaded=!0,n.element=s,e(n),o.revokeObjectURL(i)}));s.addEventListener("error",(()=>{(async()=>{o.revokeObjectURL(i);const a={...t,error:!1,loading:!0};await h(a),n.loaded=!0,n.element=a.element,e(n)})()})),s.src=i}))}const m=0,u=0;class w{constructor(t){this.loadImageShape=async t=>{if(!this._engine.loadImage)throw new Error(`${e.errorPrefix} image shape not initialized`);await this._engine.loadImage({gif:t.gif,name:t.name,replaceColor:t.replaceColor??!1,src:t.src})},this._engine=t}addImage(e){this._engine.images||(this._engine.images=[]),this._engine.images.push(e)}draw(e){const{context:t,radius:a,particle:o,opacity:i,delta:r}=e,n=o.image,s=n?.element;if(n){if(t.globalAlpha=i,n.gif&&n.gifData){const e=new OffscreenCanvas(n.gifData.width,n.gifData.height),i=e.getContext("2d");if(!i)throw new Error("could not create offscreen canvas context");i.imageSmoothingQuality="low",i.imageSmoothingEnabled=!1,i.clearRect(m,u,e.width,e.height),void 0===o.gifLoopCount&&(o.gifLoopCount=n.gifLoopCount??0);let s=o.gifFrame??0;const l={x:.5*-n.gifData.width,y:.5*-n.gifData.height},c=n.gifData.frames[s];if(void 0===o.gifTime&&(o.gifTime=0),!c.bitmap)return;switch(t.scale(a/n.gifData.width,a/n.gifData.height),c.disposalMethod){case 4:case 5:case 6:case 7:case 0:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(m,u,e.width,e.height);break;case 1:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y);break;case 2:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(m,u,e.width,e.height),n.gifData.globalColorTable.length?i.putImageData(n.gifData.backgroundImage,l.x,l.y):i.putImageData(n.gifData.frames[0].image,l.x+c.left,l.y+c.top);break;case 3:{const a=i.getImageData(m,u,e.width,e.height);i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(m,u,e.width,e.height),i.putImageData(a,m,u)}}if(o.gifTime+=r.value,o.gifTime>c.delayTime){if(o.gifTime-=c.delayTime,++s>=n.gifData.frames.length){if(--o.gifLoopCount<=0)return;s=0,i.clearRect(m,u,e.width,e.height)}o.gifFrame=s}t.scale(n.gifData.width/a,n.gifData.height/a)}else if(s){const e=n.ratio,o={x:-a,y:-a},i=2*a;t.drawImage(s,o.x,o.y,i,i/e)}t.globalAlpha=1}}getSidesCount(){return 12}async init(e){const t=e.actualOptions;if(t.preload&&this._engine.loadImage)for(const e of t.preload)await this._engine.loadImage(e)}loadShape(e){if("image"!==e.shape&&"images"!==e.shape)return;this._engine.images||(this._engine.images=[]);const t=e.shapeData;if(!t)return;this._engine.images.find((e=>e.name===t.name||e.source===t.src))||this.loadImageShape(t).then((()=>{this.loadShape(e)}))}particleInit(e,t){if("image"!==t.shape&&"images"!==t.shape)return;this._engine.images||(this._engine.images=[]);const a=this._engine.images,o=t.shapeData;if(!o)return;const i=t.getFillColor(),r=a.find((e=>e.name===o.name||e.source===o.src));if(!r)return;const n=o.replaceColor??r.replaceColor;r.loading?setTimeout((()=>{this.particleInit(e,t)})):(async()=>{let e;e=r.svgData&&i?await p(r,o,i,t):{color:i,data:r,element:r.element,gif:r.gif,gifData:r.gifData,gifLoopCount:r.gifLoopCount,loaded:!0,ratio:o.width&&o.height?o.width/o.height:r.ratio??1,replaceColor:n,source:o.src},e.ratio||(e.ratio=1);const a={image:e,fill:o.fill??t.shapeFill,close:o.close??t.shapeClose};t.image=a.image,t.shapeFill=a.fill,t.shapeClose=a.close})()}}class y{constructor(){this.src="",this.gif=!1}load(e){e&&(void 0!==e.gif&&(this.gif=e.gif),void 0!==e.height&&(this.height=e.height),void 0!==e.name&&(this.name=e.name),void 0!==e.replaceColor&&(this.replaceColor=e.replaceColor),void 0!==e.src&&(this.src=e.src),void 0!==e.width&&(this.width=e.width))}}class b{constructor(e){this.id="imagePreloader",this._engine=e}getPlugin(){return{}}loadOptions(e,t){if(!t?.preload)return;e.preload||(e.preload=[]);const a=e.preload;for(const e of t.preload){const t=a.find((t=>t.name===e.name||t.src===e.src));if(t)t.load(e);else{const t=new y;t.load(e),a.push(t)}}}needsPlugin(){return!0}}const x=3;async function C(t,a=!0){!function(t){t.loadImage||(t.loadImage=async a=>{if(!a.name&&!a.src)throw new Error(`${e.errorPrefix} no image source provided`);if(t.images||(t.images=[]),!t.images.find((e=>e.name===a.name||e.source===a.src)))try{const e={gif:a.gif??!1,name:a.name??a.src,source:a.src,type:a.src.substring(a.src.length-x),error:!1,loading:!0,replaceColor:a.replaceColor,ratio:a.width&&a.height?a.width/a.height:void 0};let o;t.images.push(e),o=a.gif?d:a.replaceColor?f:h,await o(e)}catch{throw new Error(`${e.errorPrefix} ${a.name??a.src} not found`)}})}(t);const o=new b(t);await t.addPlugin(o,a),await t.addShape(["image","images"],new w(t),a)}})(),i})()));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
/*! tsParticles Image Shape v3.0
|
|
1
|
+
/*! tsParticles Image Shape v3.1.0 by Matteo Bruni */
|
package/types/ImageDrawer.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Container, type IShapeDrawData, type IShapeDrawer } from "@tsparticles/engine";
|
|
2
|
-
import type
|
|
2
|
+
import { type IImage, type ImageParticle } from "./Utils.js";
|
|
3
3
|
import type { ImageContainer, ImageEngine } from "./types.js";
|
|
4
4
|
export declare class ImageDrawer implements IShapeDrawer<ImageParticle> {
|
|
5
5
|
private readonly _engine;
|
|
@@ -24,32 +24,35 @@
|
|
|
24
24
|
return this.data[this.pos++];
|
|
25
25
|
}
|
|
26
26
|
nextTwoBytes() {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const increment = 2, previous = 1, shift = 8;
|
|
28
|
+
this.pos += increment;
|
|
29
|
+
return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
|
|
29
30
|
}
|
|
30
31
|
readSubBlocks() {
|
|
31
32
|
let blockString = "", size = 0;
|
|
33
|
+
const minCount = 0, emptySize = 0;
|
|
32
34
|
do {
|
|
33
35
|
size = this.data[this.pos++];
|
|
34
|
-
for (let count = size; --count >=
|
|
36
|
+
for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
|
|
35
37
|
}
|
|
36
|
-
} while (size !==
|
|
38
|
+
} while (size !== emptySize);
|
|
37
39
|
return blockString;
|
|
38
40
|
}
|
|
39
41
|
readSubBlocksBin() {
|
|
40
42
|
let size = 0, len = 0;
|
|
41
|
-
|
|
43
|
+
const emptySize = 0, increment = 1;
|
|
44
|
+
for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
|
|
42
45
|
len += size;
|
|
43
46
|
}
|
|
44
47
|
const blockData = new Uint8Array(len);
|
|
45
|
-
for (let i = 0;
|
|
46
|
-
for (let count = size; --count >=
|
|
48
|
+
for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
|
|
49
|
+
for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
return blockData;
|
|
50
53
|
}
|
|
51
54
|
skipSubBlocks() {
|
|
52
|
-
for (; this.data[this.pos] !==
|
|
55
|
+
for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {
|
|
53
56
|
}
|
|
54
57
|
this.pos++;
|
|
55
58
|
}
|
package/umd/GifUtils/Utils.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
}
|
|
25
25
|
return colors;
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
|
|
28
28
|
switch (byteStream.nextByte()) {
|
|
29
29
|
case 249: {
|
|
30
30
|
const frame = gif.frames[getFrameIndex(false)];
|
|
@@ -96,7 +96,10 @@
|
|
|
96
96
|
}
|
|
97
97
|
const getColor = (index) => {
|
|
98
98
|
const { r, g, b } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
|
|
99
|
-
|
|
99
|
+
if (index !== getTransparencyIndex(null)) {
|
|
100
|
+
return { r, g, b, a: 255 };
|
|
101
|
+
}
|
|
102
|
+
return { r, g, b, a: avgAlpha ? ~~((r + g + b) / 3) : 0 };
|
|
100
103
|
};
|
|
101
104
|
const image = (() => {
|
|
102
105
|
try {
|
|
@@ -122,7 +125,8 @@
|
|
|
122
125
|
if (interlacedFlag) {
|
|
123
126
|
for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
|
|
124
127
|
if (Constants_js_1.InterlaceOffsets[pass] < frame.height) {
|
|
125
|
-
|
|
128
|
+
let pixelPos = 0, lineIndex = 0, exit = false;
|
|
129
|
+
while (!exit) {
|
|
126
130
|
const last = code;
|
|
127
131
|
code = readBits(pos, size);
|
|
128
132
|
pos += size + 1;
|
|
@@ -140,8 +144,8 @@
|
|
|
140
144
|
else if (last !== clearCode) {
|
|
141
145
|
dic.push(dic[last].concat(dic[code][0]));
|
|
142
146
|
}
|
|
143
|
-
for (
|
|
144
|
-
const { r, g, b, a } = getColor(
|
|
147
|
+
for (const item of dic[code]) {
|
|
148
|
+
const { r, g, b, a } = getColor(item);
|
|
145
149
|
image.data.set([r, g, b, a], Constants_js_1.InterlaceOffsets[pass] * frame.width +
|
|
146
150
|
Constants_js_1.InterlaceSteps[pass] * lineIndex +
|
|
147
151
|
(pixelPos % (frame.width * 4)));
|
|
@@ -154,7 +158,7 @@
|
|
|
154
158
|
if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
|
|
155
159
|
lineIndex++;
|
|
156
160
|
if (Constants_js_1.InterlaceOffsets[pass] + Constants_js_1.InterlaceSteps[pass] * lineIndex >= frame.height) {
|
|
157
|
-
|
|
161
|
+
exit = true;
|
|
158
162
|
}
|
|
159
163
|
}
|
|
160
164
|
}
|
|
@@ -165,7 +169,9 @@
|
|
|
165
169
|
frame.bitmap = await createImageBitmap(image);
|
|
166
170
|
}
|
|
167
171
|
else {
|
|
168
|
-
|
|
172
|
+
let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4, exit = false;
|
|
173
|
+
const dic = [[0]];
|
|
174
|
+
while (!exit) {
|
|
169
175
|
const last = code;
|
|
170
176
|
code = readBits(pos, size);
|
|
171
177
|
pos += size;
|
|
@@ -178,6 +184,7 @@
|
|
|
178
184
|
}
|
|
179
185
|
else {
|
|
180
186
|
if (code === clearCode + 1) {
|
|
187
|
+
exit = true;
|
|
181
188
|
break;
|
|
182
189
|
}
|
|
183
190
|
if (code >= dic.length) {
|
|
@@ -186,8 +193,8 @@
|
|
|
186
193
|
else if (last !== clearCode) {
|
|
187
194
|
dic.push(dic[last].concat(dic[code][0]));
|
|
188
195
|
}
|
|
189
|
-
for (
|
|
190
|
-
const { r, g, b, a } = getColor(
|
|
196
|
+
for (const item of dic[code]) {
|
|
197
|
+
const { r, g, b, a } = getColor(item);
|
|
191
198
|
image.data.set([r, g, b, a], (pixelPos += 4));
|
|
192
199
|
}
|
|
193
200
|
if (dic.length >= 1 << size && size < 0xc) {
|
|
@@ -208,7 +215,7 @@
|
|
|
208
215
|
await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);
|
|
209
216
|
break;
|
|
210
217
|
case 33:
|
|
211
|
-
|
|
218
|
+
parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
|
|
212
219
|
break;
|
|
213
220
|
default:
|
|
214
221
|
throw new EvalError("undefined block found");
|