@loaders.gl/video 4.0.0-alpha.4 → 4.0.0-alpha.6
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/bundle.d.ts +2 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +2 -2
- package/dist/dist.min.js +2147 -0
- package/dist/es5/bundle.js +6 -0
- package/dist/es5/bundle.js.map +1 -0
- package/dist/es5/gif-builder.js +200 -0
- package/dist/es5/gif-builder.js.map +1 -0
- package/dist/es5/index.js +21 -0
- package/dist/es5/index.js.map +1 -0
- package/dist/es5/lib/gifshot/gifshot-loader.js +67 -0
- package/dist/es5/lib/gifshot/gifshot-loader.js.map +1 -0
- package/dist/es5/lib/gifshot/gifshot.js +1924 -0
- package/dist/es5/lib/gifshot/gifshot.js.map +1 -0
- package/dist/es5/lib/parsers/parse-video.js +31 -0
- package/dist/es5/lib/parsers/parse-video.js.map +1 -0
- package/dist/es5/lib/utils/assert.js +12 -0
- package/dist/es5/lib/utils/assert.js.map +1 -0
- package/dist/es5/video-loader.js +28 -0
- package/dist/es5/video-loader.js.map +1 -0
- package/dist/esm/bundle.js +4 -0
- package/dist/esm/bundle.js.map +1 -0
- package/dist/esm/gif-builder.js +106 -0
- package/dist/esm/gif-builder.js.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/{src → dist/esm}/lib/gifshot/gifshot-loader.js +4 -8
- package/dist/esm/lib/gifshot/gifshot-loader.js.map +1 -0
- package/dist/esm/lib/gifshot/gifshot.js +1915 -0
- package/dist/esm/lib/gifshot/gifshot.js.map +1 -0
- package/dist/esm/lib/parsers/parse-video.js +7 -0
- package/dist/esm/lib/parsers/parse-video.js.map +1 -0
- package/{src → dist/esm}/lib/utils/assert.js +1 -0
- package/dist/esm/lib/utils/assert.js.map +1 -0
- package/dist/esm/video-loader.js +19 -0
- package/dist/esm/video-loader.js.map +1 -0
- package/dist/gif-builder.d.ts +53 -0
- package/dist/gif-builder.d.ts.map +1 -0
- package/dist/gif-builder.js +136 -114
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -3
- package/dist/lib/gifshot/gifshot-loader.d.ts +2 -0
- package/dist/lib/gifshot/gifshot-loader.d.ts.map +1 -0
- package/dist/lib/gifshot/gifshot-loader.js +18 -15
- package/dist/lib/gifshot/gifshot.d.ts +72 -0
- package/dist/lib/gifshot/gifshot.d.ts.map +1 -0
- package/dist/lib/gifshot/gifshot.js +2439 -0
- package/dist/lib/parsers/parse-video.d.ts +2 -0
- package/dist/lib/parsers/parse-video.d.ts.map +1 -0
- package/dist/lib/parsers/parse-video.js +12 -6
- package/dist/lib/utils/assert.d.ts +2 -0
- package/dist/lib/utils/assert.d.ts.map +1 -0
- package/dist/lib/utils/assert.js +8 -5
- package/dist/video-loader.d.ts +17 -0
- package/dist/video-loader.d.ts.map +1 -0
- package/dist/video-loader.js +22 -14
- package/package.json +8 -8
- package/src/{gif-builder.js → gif-builder.ts} +6 -6
- package/src/lib/gifshot/gifshot.ts +2416 -0
- package/dist/bundle.js.map +0 -1
- package/dist/gif-builder.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/gifshot/gifshot-loader.js.map +0 -1
- package/dist/lib/parsers/parse-video.js.map +0 -1
- package/dist/lib/utils/assert.js.map +0 -1
- package/dist/lib/utils/globals.js +0 -16
- package/dist/lib/utils/globals.js.map +0 -1
- package/dist/libs/gifshot.js +0 -2826
- package/dist/video-loader.js.map +0 -1
- package/src/lib/utils/globals.js +0 -25
- package/src/libs/gifshot.js +0 -2826
|
@@ -0,0 +1,1915 @@
|
|
|
1
|
+
var utils = {
|
|
2
|
+
URL: globalThis.URL || globalThis.webkitURL || globalThis.mozURL || globalThis.msURL,
|
|
3
|
+
getUserMedia: function () {
|
|
4
|
+
if (!globalThis.navigator) return globalThis.navigator;
|
|
5
|
+
const getUserMedia = globalThis.navigator.getUserMedia || globalThis.navigator.webkitGetUserMedia || globalThis.navigator.mozGetUserMedia || globalThis.navigator.msGetUserMedia;
|
|
6
|
+
return getUserMedia ? getUserMedia.bind(globalThis.navigator) : getUserMedia;
|
|
7
|
+
}(),
|
|
8
|
+
requestAnimFrame: globalThis.requestAnimationFrame || globalThis.webkitRequestAnimationFrame || globalThis.mozRequestAnimationFrame || globalThis.oRequestAnimationFrame || globalThis.msRequestAnimationFrame,
|
|
9
|
+
requestTimeout: function requestTimeout(callback, delay) {
|
|
10
|
+
callback = callback || utils.noop;
|
|
11
|
+
delay = delay || 0;
|
|
12
|
+
if (!utils.requestAnimFrame) {
|
|
13
|
+
return setTimeout(callback, delay);
|
|
14
|
+
}
|
|
15
|
+
const start = new Date().getTime();
|
|
16
|
+
const handle = new Object();
|
|
17
|
+
const requestAnimFrame = utils.requestAnimFrame;
|
|
18
|
+
const loop = function loop() {
|
|
19
|
+
const current = new Date().getTime();
|
|
20
|
+
const delta = current - start;
|
|
21
|
+
delta >= delay ? callback.call() : handle.value = requestAnimFrame(loop);
|
|
22
|
+
};
|
|
23
|
+
handle.value = requestAnimFrame(loop);
|
|
24
|
+
return handle;
|
|
25
|
+
},
|
|
26
|
+
Blob: globalThis.Blob || globalThis.BlobBuilder || globalThis.WebKitBlobBuilder || globalThis.MozBlobBuilder || globalThis.MSBlobBuilder,
|
|
27
|
+
btoa: function () {
|
|
28
|
+
const btoa = globalThis.btoa || function (input) {
|
|
29
|
+
let output = '';
|
|
30
|
+
let i = 0;
|
|
31
|
+
const l = input.length;
|
|
32
|
+
const key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
33
|
+
let chr1 = void 0;
|
|
34
|
+
let chr2 = void 0;
|
|
35
|
+
let chr3 = void 0;
|
|
36
|
+
let enc1 = void 0;
|
|
37
|
+
let enc2 = void 0;
|
|
38
|
+
let enc3 = void 0;
|
|
39
|
+
let enc4 = void 0;
|
|
40
|
+
while (i < l) {
|
|
41
|
+
chr1 = input.charCodeAt(i++);
|
|
42
|
+
chr2 = input.charCodeAt(i++);
|
|
43
|
+
chr3 = input.charCodeAt(i++);
|
|
44
|
+
enc1 = chr1 >> 2;
|
|
45
|
+
enc2 = (chr1 & 3) << 4 | chr2 >> 4;
|
|
46
|
+
enc3 = (chr2 & 15) << 2 | chr3 >> 6;
|
|
47
|
+
enc4 = chr3 & 63;
|
|
48
|
+
if (isNaN(chr2)) {
|
|
49
|
+
enc3 = enc4 = 64;
|
|
50
|
+
} else if (isNaN(chr3)) {
|
|
51
|
+
enc4 = 64;
|
|
52
|
+
}
|
|
53
|
+
output = output + key.charAt(enc1) + key.charAt(enc2) + key.charAt(enc3) + key.charAt(enc4);
|
|
54
|
+
}
|
|
55
|
+
return output;
|
|
56
|
+
};
|
|
57
|
+
return btoa ? btoa.bind(globalThis) : utils.noop;
|
|
58
|
+
}(),
|
|
59
|
+
isObject: function isObject(obj) {
|
|
60
|
+
return obj && Object.prototype.toString.call(obj) === '[object Object]';
|
|
61
|
+
},
|
|
62
|
+
isEmptyObject: function isEmptyObject(obj) {
|
|
63
|
+
return utils.isObject(obj) && !Object.keys(obj).length;
|
|
64
|
+
},
|
|
65
|
+
isArray: function isArray(arr) {
|
|
66
|
+
return arr && Array.isArray(arr);
|
|
67
|
+
},
|
|
68
|
+
isFunction: function isFunction(func) {
|
|
69
|
+
return func && typeof func === 'function';
|
|
70
|
+
},
|
|
71
|
+
isElement: function isElement(elem) {
|
|
72
|
+
return elem && elem.nodeType === 1;
|
|
73
|
+
},
|
|
74
|
+
isString: function isString(value) {
|
|
75
|
+
return typeof value === 'string' || Object.prototype.toString.call(value) === '[object String]';
|
|
76
|
+
},
|
|
77
|
+
isSupported: {
|
|
78
|
+
canvas: function canvas() {
|
|
79
|
+
const el = document.createElement('canvas');
|
|
80
|
+
return el && el.getContext && el.getContext('2d');
|
|
81
|
+
},
|
|
82
|
+
webworkers: function webworkers() {
|
|
83
|
+
return globalThis.Worker;
|
|
84
|
+
},
|
|
85
|
+
blob: function blob() {
|
|
86
|
+
return utils.Blob;
|
|
87
|
+
},
|
|
88
|
+
Uint8Array: function Uint8Array() {
|
|
89
|
+
return globalThis.Uint8Array;
|
|
90
|
+
},
|
|
91
|
+
Uint32Array: function Uint32Array() {
|
|
92
|
+
return globalThis.Uint32Array;
|
|
93
|
+
},
|
|
94
|
+
videoCodecs: function () {
|
|
95
|
+
const testEl = document.createElement('video');
|
|
96
|
+
const supportObj = {
|
|
97
|
+
mp4: false,
|
|
98
|
+
h264: false,
|
|
99
|
+
ogv: false,
|
|
100
|
+
ogg: false,
|
|
101
|
+
webm: false
|
|
102
|
+
};
|
|
103
|
+
try {
|
|
104
|
+
if (testEl && testEl.canPlayType) {
|
|
105
|
+
supportObj.mp4 = testEl.canPlayType('video/mp4; codecs="mp4v.20.8"') !== '';
|
|
106
|
+
supportObj.h264 = (testEl.canPlayType('video/mp4; codecs="avc1.42E01E"') || testEl.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) !== '';
|
|
107
|
+
supportObj.ogv = testEl.canPlayType('video/ogg; codecs="theora"') !== '';
|
|
108
|
+
supportObj.ogg = testEl.canPlayType('video/ogg; codecs="theora"') !== '';
|
|
109
|
+
supportObj.webm = testEl.canPlayType('video/webm; codecs="vp8, vorbis"') !== -1;
|
|
110
|
+
}
|
|
111
|
+
} catch (e) {}
|
|
112
|
+
return supportObj;
|
|
113
|
+
}()
|
|
114
|
+
},
|
|
115
|
+
noop: function noop() {},
|
|
116
|
+
each: function each(collection, callback) {
|
|
117
|
+
let x = void 0;
|
|
118
|
+
let len = void 0;
|
|
119
|
+
if (utils.isArray(collection)) {
|
|
120
|
+
x = -1;
|
|
121
|
+
len = collection.length;
|
|
122
|
+
while (++x < len) {
|
|
123
|
+
if (callback(x, collection[x]) === false) {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} else if (utils.isObject(collection)) {
|
|
128
|
+
for (x in collection) {
|
|
129
|
+
if (collection.hasOwnProperty(x)) {
|
|
130
|
+
if (callback(x, collection[x]) === false) {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
normalizeOptions: function normalizeOptions(defaultOptions, userOptions) {
|
|
138
|
+
if (!utils.isObject(defaultOptions) || !utils.isObject(userOptions) || !Object.keys) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const newObj = {};
|
|
142
|
+
utils.each(defaultOptions, function (key, val) {
|
|
143
|
+
newObj[key] = defaultOptions[key];
|
|
144
|
+
});
|
|
145
|
+
utils.each(userOptions, function (key, val) {
|
|
146
|
+
const currentUserOption = userOptions[key];
|
|
147
|
+
if (!utils.isObject(currentUserOption)) {
|
|
148
|
+
newObj[key] = currentUserOption;
|
|
149
|
+
} else if (!defaultOptions[key]) {
|
|
150
|
+
newObj[key] = currentUserOption;
|
|
151
|
+
} else {
|
|
152
|
+
newObj[key] = utils.normalizeOptions(defaultOptions[key], currentUserOption);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
return newObj;
|
|
156
|
+
},
|
|
157
|
+
setCSSAttr: function setCSSAttr(elem, attr, val) {
|
|
158
|
+
if (!utils.isElement(elem)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (utils.isString(attr) && utils.isString(val)) {
|
|
162
|
+
elem.style[attr] = val;
|
|
163
|
+
} else if (utils.isObject(attr)) {
|
|
164
|
+
utils.each(attr, function (key, val) {
|
|
165
|
+
elem.style[key] = val;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
removeElement: function removeElement(node) {
|
|
170
|
+
if (!utils.isElement(node)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (node.parentNode) {
|
|
174
|
+
node.parentNode.removeChild(node);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
createWebWorker: function createWebWorker(content) {
|
|
178
|
+
if (!utils.isString(content)) {
|
|
179
|
+
return {};
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
const blob = new utils.Blob([content], {
|
|
183
|
+
type: 'text/javascript'
|
|
184
|
+
});
|
|
185
|
+
const objectUrl = utils.URL.createObjectURL(blob);
|
|
186
|
+
const worker = new Worker(objectUrl);
|
|
187
|
+
return {
|
|
188
|
+
objectUrl,
|
|
189
|
+
worker
|
|
190
|
+
};
|
|
191
|
+
} catch (e) {
|
|
192
|
+
return "".concat(e);
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
getExtension: function getExtension(src) {
|
|
196
|
+
return src.substr(src.lastIndexOf('.') + 1, src.length);
|
|
197
|
+
},
|
|
198
|
+
getFontSize: function getFontSize() {
|
|
199
|
+
const options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
200
|
+
if (!document.body || options.resizeFont === false) {
|
|
201
|
+
return options.fontSize;
|
|
202
|
+
}
|
|
203
|
+
const text = options.text;
|
|
204
|
+
const containerWidth = options.gifWidth;
|
|
205
|
+
let fontSize = parseInt(options.fontSize, 10);
|
|
206
|
+
const minFontSize = parseInt(options.minFontSize, 10);
|
|
207
|
+
const div = document.createElement('div');
|
|
208
|
+
const span = document.createElement('span');
|
|
209
|
+
div.setAttribute('width', containerWidth);
|
|
210
|
+
div.appendChild(span);
|
|
211
|
+
span.innerHTML = text;
|
|
212
|
+
span.style.fontSize = "".concat(fontSize, "px");
|
|
213
|
+
span.style.textIndent = '-9999px';
|
|
214
|
+
span.style.visibility = 'hidden';
|
|
215
|
+
document.body.appendChild(span);
|
|
216
|
+
while (span.offsetWidth > containerWidth && fontSize >= minFontSize) {
|
|
217
|
+
span.style.fontSize = "".concat(--fontSize, "px");
|
|
218
|
+
}
|
|
219
|
+
document.body.removeChild(span);
|
|
220
|
+
return "".concat(fontSize, "px");
|
|
221
|
+
},
|
|
222
|
+
webWorkerError: false
|
|
223
|
+
};
|
|
224
|
+
const utils$2 = Object.freeze({
|
|
225
|
+
default: utils
|
|
226
|
+
});
|
|
227
|
+
var error = {
|
|
228
|
+
validate: function validate(skipObj) {
|
|
229
|
+
skipObj = utils.isObject(skipObj) ? skipObj : {};
|
|
230
|
+
let errorObj = {};
|
|
231
|
+
utils.each(error.validators, function (indece, currentValidator) {
|
|
232
|
+
const errorCode = currentValidator.errorCode;
|
|
233
|
+
if (!skipObj[errorCode] && !currentValidator.condition) {
|
|
234
|
+
errorObj = currentValidator;
|
|
235
|
+
errorObj.error = true;
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
delete errorObj.condition;
|
|
240
|
+
return errorObj;
|
|
241
|
+
},
|
|
242
|
+
isValid: function isValid(skipObj) {
|
|
243
|
+
const errorObj = error.validate(skipObj);
|
|
244
|
+
const isValid = errorObj.error !== true;
|
|
245
|
+
return isValid;
|
|
246
|
+
},
|
|
247
|
+
validators: [{
|
|
248
|
+
condition: utils.isFunction(utils.getUserMedia),
|
|
249
|
+
errorCode: 'getUserMedia',
|
|
250
|
+
errorMsg: 'The getUserMedia API is not supported in your browser'
|
|
251
|
+
}, {
|
|
252
|
+
condition: utils.isSupported.canvas(),
|
|
253
|
+
errorCode: 'canvas',
|
|
254
|
+
errorMsg: 'Canvas elements are not supported in your browser'
|
|
255
|
+
}, {
|
|
256
|
+
condition: utils.isSupported.webworkers(),
|
|
257
|
+
errorCode: 'webworkers',
|
|
258
|
+
errorMsg: 'The Web Workers API is not supported in your browser'
|
|
259
|
+
}, {
|
|
260
|
+
condition: utils.isFunction(utils.URL),
|
|
261
|
+
errorCode: 'globalThis.URL',
|
|
262
|
+
errorMsg: 'The globalThis.URL API is not supported in your browser'
|
|
263
|
+
}, {
|
|
264
|
+
condition: utils.isSupported.blob(),
|
|
265
|
+
errorCode: 'globalThis.Blob',
|
|
266
|
+
errorMsg: 'The globalThis.Blob File API is not supported in your browser'
|
|
267
|
+
}, {
|
|
268
|
+
condition: utils.isSupported.Uint8Array(),
|
|
269
|
+
errorCode: 'globalThis.Uint8Array',
|
|
270
|
+
errorMsg: 'The globalThis.Uint8Array function constructor is not supported in your browser'
|
|
271
|
+
}, {
|
|
272
|
+
condition: utils.isSupported.Uint32Array(),
|
|
273
|
+
errorCode: 'globalThis.Uint32Array',
|
|
274
|
+
errorMsg: 'The globalThis.Uint32Array function constructor is not supported in your browser'
|
|
275
|
+
}],
|
|
276
|
+
messages: {
|
|
277
|
+
videoCodecs: {
|
|
278
|
+
errorCode: 'videocodec',
|
|
279
|
+
errorMsg: 'The video codec you are trying to use is not supported in your browser'
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
const error$2 = Object.freeze({
|
|
284
|
+
default: error
|
|
285
|
+
});
|
|
286
|
+
const noop = function noop() {};
|
|
287
|
+
const defaultOptions = {
|
|
288
|
+
sampleInterval: 10,
|
|
289
|
+
numWorkers: 2,
|
|
290
|
+
filter: '',
|
|
291
|
+
gifWidth: 200,
|
|
292
|
+
gifHeight: 200,
|
|
293
|
+
interval: 0.1,
|
|
294
|
+
numFrames: 10,
|
|
295
|
+
frameDuration: 1,
|
|
296
|
+
keepCameraOn: false,
|
|
297
|
+
images: [],
|
|
298
|
+
video: null,
|
|
299
|
+
webcamVideoElement: null,
|
|
300
|
+
cameraStream: null,
|
|
301
|
+
text: '',
|
|
302
|
+
fontWeight: 'normal',
|
|
303
|
+
fontSize: '16px',
|
|
304
|
+
minFontSize: '10px',
|
|
305
|
+
resizeFont: false,
|
|
306
|
+
fontFamily: 'sans-serif',
|
|
307
|
+
fontColor: '#ffffff',
|
|
308
|
+
textAlign: 'center',
|
|
309
|
+
textBaseline: 'bottom',
|
|
310
|
+
textXCoordinate: null,
|
|
311
|
+
textYCoordinate: null,
|
|
312
|
+
progressCallback: noop,
|
|
313
|
+
completeCallback: noop,
|
|
314
|
+
saveRenderingContexts: false,
|
|
315
|
+
savedRenderingContexts: [],
|
|
316
|
+
crossOrigin: 'Anonymous'
|
|
317
|
+
};
|
|
318
|
+
const defaultOptions$2 = Object.freeze({
|
|
319
|
+
default: defaultOptions
|
|
320
|
+
});
|
|
321
|
+
function isSupported() {
|
|
322
|
+
return error.isValid();
|
|
323
|
+
}
|
|
324
|
+
function isWebCamGIFSupported() {
|
|
325
|
+
return error.isValid();
|
|
326
|
+
}
|
|
327
|
+
function isSupported$1() {
|
|
328
|
+
const options = {
|
|
329
|
+
getUserMedia: true
|
|
330
|
+
};
|
|
331
|
+
return error.isValid(options);
|
|
332
|
+
}
|
|
333
|
+
function isExistingVideoGIFSupported(codecs) {
|
|
334
|
+
let hasValidCodec = false;
|
|
335
|
+
if (utils.isArray(codecs) && codecs.length) {
|
|
336
|
+
utils.each(codecs, function (indece, currentCodec) {
|
|
337
|
+
if (utils.isSupported.videoCodecs[currentCodec]) {
|
|
338
|
+
hasValidCodec = true;
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
if (!hasValidCodec) {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
} else if (utils.isString(codecs) && codecs.length) {
|
|
345
|
+
if (!utils.isSupported.videoCodecs[codecs]) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return error.isValid({
|
|
350
|
+
getUserMedia: true
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
function NeuQuant() {
|
|
354
|
+
const netsize = 256;
|
|
355
|
+
const prime1 = 499;
|
|
356
|
+
const prime2 = 491;
|
|
357
|
+
const prime3 = 487;
|
|
358
|
+
const prime4 = 503;
|
|
359
|
+
const minpicturebytes = 3 * prime4;
|
|
360
|
+
const maxnetpos = netsize - 1;
|
|
361
|
+
const netbiasshift = 4;
|
|
362
|
+
const ncycles = 100;
|
|
363
|
+
const intbiasshift = 16;
|
|
364
|
+
const intbias = 1 << intbiasshift;
|
|
365
|
+
const gammashift = 10;
|
|
366
|
+
const gamma = 1 << gammashift;
|
|
367
|
+
const betashift = 10;
|
|
368
|
+
const beta = intbias >> betashift;
|
|
369
|
+
const betagamma = intbias << gammashift - betashift;
|
|
370
|
+
const initrad = netsize >> 3;
|
|
371
|
+
const radiusbiasshift = 6;
|
|
372
|
+
const radiusbias = 1 << radiusbiasshift;
|
|
373
|
+
const initradius = initrad * radiusbias;
|
|
374
|
+
const radiusdec = 30;
|
|
375
|
+
const alphabiasshift = 10;
|
|
376
|
+
const initalpha = 1 << alphabiasshift;
|
|
377
|
+
let alphadec;
|
|
378
|
+
const radbiasshift = 8;
|
|
379
|
+
const radbias = 1 << radbiasshift;
|
|
380
|
+
const alpharadbshift = alphabiasshift + radbiasshift;
|
|
381
|
+
const alpharadbias = 1 << alpharadbshift;
|
|
382
|
+
let thepicture;
|
|
383
|
+
let lengthcount;
|
|
384
|
+
let samplefac;
|
|
385
|
+
let network;
|
|
386
|
+
const netindex = [];
|
|
387
|
+
const bias = [];
|
|
388
|
+
const freq = [];
|
|
389
|
+
const radpower = [];
|
|
390
|
+
function NeuQuantConstructor(thepic, len, sample) {
|
|
391
|
+
let i;
|
|
392
|
+
let p;
|
|
393
|
+
thepicture = thepic;
|
|
394
|
+
lengthcount = len;
|
|
395
|
+
samplefac = sample;
|
|
396
|
+
network = new Array(netsize);
|
|
397
|
+
for (i = 0; i < netsize; i++) {
|
|
398
|
+
network[i] = new Array(4);
|
|
399
|
+
p = network[i];
|
|
400
|
+
p[0] = p[1] = p[2] = (i << netbiasshift + 8) / netsize | 0;
|
|
401
|
+
freq[i] = intbias / netsize | 0;
|
|
402
|
+
bias[i] = 0;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function colorMap() {
|
|
406
|
+
const map = [];
|
|
407
|
+
const index = new Array(netsize);
|
|
408
|
+
for (let i = 0; i < netsize; i++) {
|
|
409
|
+
index[network[i][3]] = i;
|
|
410
|
+
}
|
|
411
|
+
let k = 0;
|
|
412
|
+
for (let l = 0; l < netsize; l++) {
|
|
413
|
+
const j = index[l];
|
|
414
|
+
map[k++] = network[j][0];
|
|
415
|
+
map[k++] = network[j][1];
|
|
416
|
+
map[k++] = network[j][2];
|
|
417
|
+
}
|
|
418
|
+
return map;
|
|
419
|
+
}
|
|
420
|
+
function inxbuild() {
|
|
421
|
+
let i;
|
|
422
|
+
let j;
|
|
423
|
+
let smallpos;
|
|
424
|
+
let smallval;
|
|
425
|
+
let p;
|
|
426
|
+
let q;
|
|
427
|
+
let previouscol;
|
|
428
|
+
let startpos;
|
|
429
|
+
previouscol = 0;
|
|
430
|
+
startpos = 0;
|
|
431
|
+
for (i = 0; i < netsize; i++) {
|
|
432
|
+
p = network[i];
|
|
433
|
+
smallpos = i;
|
|
434
|
+
smallval = p[1];
|
|
435
|
+
for (j = i + 1; j < netsize; j++) {
|
|
436
|
+
q = network[j];
|
|
437
|
+
if (q[1] < smallval) {
|
|
438
|
+
smallpos = j;
|
|
439
|
+
smallval = q[1];
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
q = network[smallpos];
|
|
443
|
+
if (i != smallpos) {
|
|
444
|
+
j = q[0];
|
|
445
|
+
q[0] = p[0];
|
|
446
|
+
p[0] = j;
|
|
447
|
+
j = q[1];
|
|
448
|
+
q[1] = p[1];
|
|
449
|
+
p[1] = j;
|
|
450
|
+
j = q[2];
|
|
451
|
+
q[2] = p[2];
|
|
452
|
+
p[2] = j;
|
|
453
|
+
j = q[3];
|
|
454
|
+
q[3] = p[3];
|
|
455
|
+
p[3] = j;
|
|
456
|
+
}
|
|
457
|
+
if (smallval != previouscol) {
|
|
458
|
+
netindex[previouscol] = startpos + i >> 1;
|
|
459
|
+
for (j = previouscol + 1; j < smallval; j++) {
|
|
460
|
+
netindex[j] = i;
|
|
461
|
+
}
|
|
462
|
+
previouscol = smallval;
|
|
463
|
+
startpos = i;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
netindex[previouscol] = startpos + maxnetpos >> 1;
|
|
467
|
+
for (j = previouscol + 1; j < 256; j++) {
|
|
468
|
+
netindex[j] = maxnetpos;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
function learn() {
|
|
472
|
+
let i;
|
|
473
|
+
let j;
|
|
474
|
+
let b;
|
|
475
|
+
let g;
|
|
476
|
+
let r;
|
|
477
|
+
let radius;
|
|
478
|
+
let rad;
|
|
479
|
+
let alpha;
|
|
480
|
+
let step;
|
|
481
|
+
let delta;
|
|
482
|
+
let samplepixels;
|
|
483
|
+
let p;
|
|
484
|
+
let pix;
|
|
485
|
+
let lim;
|
|
486
|
+
if (lengthcount < minpicturebytes) {
|
|
487
|
+
samplefac = 1;
|
|
488
|
+
}
|
|
489
|
+
alphadec = 30 + (samplefac - 1) / 3;
|
|
490
|
+
p = thepicture;
|
|
491
|
+
pix = 0;
|
|
492
|
+
lim = lengthcount;
|
|
493
|
+
samplepixels = lengthcount / (3 * samplefac);
|
|
494
|
+
delta = samplepixels / ncycles | 0;
|
|
495
|
+
alpha = initalpha;
|
|
496
|
+
radius = initradius;
|
|
497
|
+
rad = radius >> radiusbiasshift;
|
|
498
|
+
if (rad <= 1) {
|
|
499
|
+
rad = 0;
|
|
500
|
+
}
|
|
501
|
+
for (i = 0; i < rad; i++) {
|
|
502
|
+
radpower[i] = alpha * ((rad * rad - i * i) * radbias / (rad * rad));
|
|
503
|
+
}
|
|
504
|
+
if (lengthcount < minpicturebytes) {
|
|
505
|
+
step = 3;
|
|
506
|
+
} else if (lengthcount % prime1 !== 0) {
|
|
507
|
+
step = 3 * prime1;
|
|
508
|
+
} else if (lengthcount % prime2 !== 0) {
|
|
509
|
+
step = 3 * prime2;
|
|
510
|
+
} else if (lengthcount % prime3 !== 0) {
|
|
511
|
+
step = 3 * prime3;
|
|
512
|
+
} else {
|
|
513
|
+
step = 3 * prime4;
|
|
514
|
+
}
|
|
515
|
+
i = 0;
|
|
516
|
+
while (i < samplepixels) {
|
|
517
|
+
b = (p[pix + 0] & 0xff) << netbiasshift;
|
|
518
|
+
g = (p[pix + 1] & 0xff) << netbiasshift;
|
|
519
|
+
r = (p[pix + 2] & 0xff) << netbiasshift;
|
|
520
|
+
j = contest(b, g, r);
|
|
521
|
+
altersingle(alpha, j, b, g, r);
|
|
522
|
+
if (rad !== 0) {
|
|
523
|
+
alterneigh(rad, j, b, g, r);
|
|
524
|
+
}
|
|
525
|
+
pix += step;
|
|
526
|
+
if (pix >= lim) {
|
|
527
|
+
pix -= lengthcount;
|
|
528
|
+
}
|
|
529
|
+
i++;
|
|
530
|
+
if (delta === 0) {
|
|
531
|
+
delta = 1;
|
|
532
|
+
}
|
|
533
|
+
if (i % delta === 0) {
|
|
534
|
+
alpha -= alpha / alphadec;
|
|
535
|
+
radius -= radius / radiusdec;
|
|
536
|
+
rad = radius >> radiusbiasshift;
|
|
537
|
+
if (rad <= 1) {
|
|
538
|
+
rad = 0;
|
|
539
|
+
}
|
|
540
|
+
for (j = 0; j < rad; j++) {
|
|
541
|
+
radpower[j] = alpha * ((rad * rad - j * j) * radbias / (rad * rad));
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function map(b, g, r) {
|
|
547
|
+
let i;
|
|
548
|
+
let j;
|
|
549
|
+
let dist;
|
|
550
|
+
let a;
|
|
551
|
+
let bestd;
|
|
552
|
+
let p;
|
|
553
|
+
let best;
|
|
554
|
+
bestd = 1000;
|
|
555
|
+
best = -1;
|
|
556
|
+
i = netindex[g];
|
|
557
|
+
j = i - 1;
|
|
558
|
+
while (i < netsize || j >= 0) {
|
|
559
|
+
if (i < netsize) {
|
|
560
|
+
p = network[i];
|
|
561
|
+
dist = p[1] - g;
|
|
562
|
+
if (dist >= bestd) {
|
|
563
|
+
i = netsize;
|
|
564
|
+
} else {
|
|
565
|
+
i++;
|
|
566
|
+
if (dist < 0) {
|
|
567
|
+
dist = -dist;
|
|
568
|
+
}
|
|
569
|
+
a = p[0] - b;
|
|
570
|
+
if (a < 0) {
|
|
571
|
+
a = -a;
|
|
572
|
+
}
|
|
573
|
+
dist += a;
|
|
574
|
+
if (dist < bestd) {
|
|
575
|
+
a = p[2] - r;
|
|
576
|
+
if (a < 0) {
|
|
577
|
+
a = -a;
|
|
578
|
+
}
|
|
579
|
+
dist += a;
|
|
580
|
+
if (dist < bestd) {
|
|
581
|
+
bestd = dist;
|
|
582
|
+
best = p[3];
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (j >= 0) {
|
|
588
|
+
p = network[j];
|
|
589
|
+
dist = g - p[1];
|
|
590
|
+
if (dist >= bestd) {
|
|
591
|
+
j = -1;
|
|
592
|
+
} else {
|
|
593
|
+
j--;
|
|
594
|
+
if (dist < 0) {
|
|
595
|
+
dist = -dist;
|
|
596
|
+
}
|
|
597
|
+
a = p[0] - b;
|
|
598
|
+
if (a < 0) {
|
|
599
|
+
a = -a;
|
|
600
|
+
}
|
|
601
|
+
dist += a;
|
|
602
|
+
if (dist < bestd) {
|
|
603
|
+
a = p[2] - r;
|
|
604
|
+
if (a < 0) {
|
|
605
|
+
a = -a;
|
|
606
|
+
}
|
|
607
|
+
dist += a;
|
|
608
|
+
if (dist < bestd) {
|
|
609
|
+
bestd = dist;
|
|
610
|
+
best = p[3];
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return best;
|
|
617
|
+
}
|
|
618
|
+
function process() {
|
|
619
|
+
learn();
|
|
620
|
+
unbiasnet();
|
|
621
|
+
inxbuild();
|
|
622
|
+
return colorMap();
|
|
623
|
+
}
|
|
624
|
+
function unbiasnet() {
|
|
625
|
+
let i;
|
|
626
|
+
let j;
|
|
627
|
+
for (i = 0; i < netsize; i++) {
|
|
628
|
+
network[i][0] >>= netbiasshift;
|
|
629
|
+
network[i][1] >>= netbiasshift;
|
|
630
|
+
network[i][2] >>= netbiasshift;
|
|
631
|
+
network[i][3] = i;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function alterneigh(rad, i, b, g, r) {
|
|
635
|
+
let j;
|
|
636
|
+
let k;
|
|
637
|
+
let lo;
|
|
638
|
+
let hi;
|
|
639
|
+
let a;
|
|
640
|
+
let m;
|
|
641
|
+
let p;
|
|
642
|
+
lo = i - rad;
|
|
643
|
+
if (lo < -1) {
|
|
644
|
+
lo = -1;
|
|
645
|
+
}
|
|
646
|
+
hi = i + rad;
|
|
647
|
+
if (hi > netsize) {
|
|
648
|
+
hi = netsize;
|
|
649
|
+
}
|
|
650
|
+
j = i + 1;
|
|
651
|
+
k = i - 1;
|
|
652
|
+
m = 1;
|
|
653
|
+
while (j < hi || k > lo) {
|
|
654
|
+
a = radpower[m++];
|
|
655
|
+
if (j < hi) {
|
|
656
|
+
p = network[j++];
|
|
657
|
+
try {
|
|
658
|
+
p[0] -= a * (p[0] - b) / alpharadbias | 0;
|
|
659
|
+
p[1] -= a * (p[1] - g) / alpharadbias | 0;
|
|
660
|
+
p[2] -= a * (p[2] - r) / alpharadbias | 0;
|
|
661
|
+
} catch (e) {}
|
|
662
|
+
}
|
|
663
|
+
if (k > lo) {
|
|
664
|
+
p = network[k--];
|
|
665
|
+
try {
|
|
666
|
+
p[0] -= a * (p[0] - b) / alpharadbias | 0;
|
|
667
|
+
p[1] -= a * (p[1] - g) / alpharadbias | 0;
|
|
668
|
+
p[2] -= a * (p[2] - r) / alpharadbias | 0;
|
|
669
|
+
} catch (e) {}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
function altersingle(alpha, i, b, g, r) {
|
|
674
|
+
const n = network[i];
|
|
675
|
+
const alphaMult = alpha / initalpha;
|
|
676
|
+
n[0] -= alphaMult * (n[0] - b) | 0;
|
|
677
|
+
n[1] -= alphaMult * (n[1] - g) | 0;
|
|
678
|
+
n[2] -= alphaMult * (n[2] - r) | 0;
|
|
679
|
+
}
|
|
680
|
+
function contest(b, g, r) {
|
|
681
|
+
let i;
|
|
682
|
+
let dist;
|
|
683
|
+
let a;
|
|
684
|
+
let biasdist;
|
|
685
|
+
let betafreq;
|
|
686
|
+
let bestpos;
|
|
687
|
+
let bestbiaspos;
|
|
688
|
+
let bestd;
|
|
689
|
+
let bestbiasd;
|
|
690
|
+
let n;
|
|
691
|
+
bestd = ~(1 << 31);
|
|
692
|
+
bestbiasd = bestd;
|
|
693
|
+
bestpos = -1;
|
|
694
|
+
bestbiaspos = bestpos;
|
|
695
|
+
for (i = 0; i < netsize; i++) {
|
|
696
|
+
n = network[i];
|
|
697
|
+
dist = n[0] - b;
|
|
698
|
+
if (dist < 0) {
|
|
699
|
+
dist = -dist;
|
|
700
|
+
}
|
|
701
|
+
a = n[1] - g;
|
|
702
|
+
if (a < 0) {
|
|
703
|
+
a = -a;
|
|
704
|
+
}
|
|
705
|
+
dist += a;
|
|
706
|
+
a = n[2] - r;
|
|
707
|
+
if (a < 0) {
|
|
708
|
+
a = -a;
|
|
709
|
+
}
|
|
710
|
+
dist += a;
|
|
711
|
+
if (dist < bestd) {
|
|
712
|
+
bestd = dist;
|
|
713
|
+
bestpos = i;
|
|
714
|
+
}
|
|
715
|
+
biasdist = dist - (bias[i] >> intbiasshift - netbiasshift);
|
|
716
|
+
if (biasdist < bestbiasd) {
|
|
717
|
+
bestbiasd = biasdist;
|
|
718
|
+
bestbiaspos = i;
|
|
719
|
+
}
|
|
720
|
+
betafreq = freq[i] >> betashift;
|
|
721
|
+
freq[i] -= betafreq;
|
|
722
|
+
bias[i] += betafreq << gammashift;
|
|
723
|
+
}
|
|
724
|
+
freq[bestpos] += beta;
|
|
725
|
+
bias[bestpos] -= betagamma;
|
|
726
|
+
return bestbiaspos;
|
|
727
|
+
}
|
|
728
|
+
NeuQuantConstructor.apply(this, arguments);
|
|
729
|
+
const exports = {};
|
|
730
|
+
exports.map = map;
|
|
731
|
+
exports.process = process;
|
|
732
|
+
return exports;
|
|
733
|
+
}
|
|
734
|
+
function workerCode() {
|
|
735
|
+
const self = this;
|
|
736
|
+
try {
|
|
737
|
+
globalThis.onmessage = function (ev) {
|
|
738
|
+
const data = ev.data || {};
|
|
739
|
+
let response;
|
|
740
|
+
if (data.gifshot) {
|
|
741
|
+
response = workerMethods.run(data);
|
|
742
|
+
postMessage(response);
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
} catch (e) {}
|
|
746
|
+
var workerMethods = {
|
|
747
|
+
dataToRGB: function dataToRGB(data, width, height) {
|
|
748
|
+
const length = width * height * 4;
|
|
749
|
+
let i = 0;
|
|
750
|
+
const rgb = [];
|
|
751
|
+
while (i < length) {
|
|
752
|
+
rgb.push(data[i++]);
|
|
753
|
+
rgb.push(data[i++]);
|
|
754
|
+
rgb.push(data[i++]);
|
|
755
|
+
i++;
|
|
756
|
+
}
|
|
757
|
+
return rgb;
|
|
758
|
+
},
|
|
759
|
+
componentizedPaletteToArray: function componentizedPaletteToArray(paletteRGB) {
|
|
760
|
+
paletteRGB = paletteRGB || [];
|
|
761
|
+
const paletteArray = [];
|
|
762
|
+
for (let i = 0; i < paletteRGB.length; i += 3) {
|
|
763
|
+
const r = paletteRGB[i];
|
|
764
|
+
const g = paletteRGB[i + 1];
|
|
765
|
+
const b = paletteRGB[i + 2];
|
|
766
|
+
paletteArray.push(r << 16 | g << 8 | b);
|
|
767
|
+
}
|
|
768
|
+
return paletteArray;
|
|
769
|
+
},
|
|
770
|
+
processFrameWithQuantizer: function processFrameWithQuantizer(imageData, width, height, sampleInterval) {
|
|
771
|
+
const rgbComponents = this.dataToRGB(imageData, width, height);
|
|
772
|
+
const nq = new NeuQuant(rgbComponents, rgbComponents.length, sampleInterval);
|
|
773
|
+
const paletteRGB = nq.process();
|
|
774
|
+
const paletteArray = new Uint32Array(this.componentizedPaletteToArray(paletteRGB));
|
|
775
|
+
const numberPixels = width * height;
|
|
776
|
+
const indexedPixels = new Uint8Array(numberPixels);
|
|
777
|
+
let k = 0;
|
|
778
|
+
for (let i = 0; i < numberPixels; i++) {
|
|
779
|
+
const r = rgbComponents[k++];
|
|
780
|
+
const g = rgbComponents[k++];
|
|
781
|
+
const b = rgbComponents[k++];
|
|
782
|
+
indexedPixels[i] = nq.map(r, g, b);
|
|
783
|
+
}
|
|
784
|
+
return {
|
|
785
|
+
pixels: indexedPixels,
|
|
786
|
+
palette: paletteArray
|
|
787
|
+
};
|
|
788
|
+
},
|
|
789
|
+
run: function run(frame) {
|
|
790
|
+
frame = frame || {};
|
|
791
|
+
const _frame = frame;
|
|
792
|
+
const height = _frame.height;
|
|
793
|
+
const palette = _frame.palette;
|
|
794
|
+
const sampleInterval = _frame.sampleInterval;
|
|
795
|
+
const width = _frame.width;
|
|
796
|
+
const imageData = frame.data;
|
|
797
|
+
return this.processFrameWithQuantizer(imageData, width, height, sampleInterval);
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
return workerMethods;
|
|
801
|
+
}
|
|
802
|
+
function gifWriter(buf, width, height, gopts) {
|
|
803
|
+
let p = 0;
|
|
804
|
+
gopts = gopts === undefined ? {} : gopts;
|
|
805
|
+
const loop_count = gopts.loop === undefined ? null : gopts.loop;
|
|
806
|
+
const global_palette = gopts.palette === undefined ? null : gopts.palette;
|
|
807
|
+
if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw 'Width/Height invalid.';
|
|
808
|
+
function check_palette_and_num_colors(palette) {
|
|
809
|
+
const num_colors = palette.length;
|
|
810
|
+
if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) throw 'Invalid code/color length, must be power of 2 and 2 .. 256.';
|
|
811
|
+
return num_colors;
|
|
812
|
+
}
|
|
813
|
+
buf[p++] = 0x47;
|
|
814
|
+
buf[p++] = 0x49;
|
|
815
|
+
buf[p++] = 0x46;
|
|
816
|
+
buf[p++] = 0x38;
|
|
817
|
+
buf[p++] = 0x39;
|
|
818
|
+
buf[p++] = 0x61;
|
|
819
|
+
const gp_num_colors_pow2 = 0;
|
|
820
|
+
const background = 0;
|
|
821
|
+
buf[p++] = width & 0xff;
|
|
822
|
+
buf[p++] = width >> 8 & 0xff;
|
|
823
|
+
buf[p++] = height & 0xff;
|
|
824
|
+
buf[p++] = height >> 8 & 0xff;
|
|
825
|
+
buf[p++] = (global_palette !== null ? 0x80 : 0) | gp_num_colors_pow2;
|
|
826
|
+
buf[p++] = background;
|
|
827
|
+
buf[p++] = 0;
|
|
828
|
+
if (loop_count !== null) {
|
|
829
|
+
if (loop_count < 0 || loop_count > 65535) throw 'Loop count invalid.';
|
|
830
|
+
buf[p++] = 0x21;
|
|
831
|
+
buf[p++] = 0xff;
|
|
832
|
+
buf[p++] = 0x0b;
|
|
833
|
+
buf[p++] = 0x4e;
|
|
834
|
+
buf[p++] = 0x45;
|
|
835
|
+
buf[p++] = 0x54;
|
|
836
|
+
buf[p++] = 0x53;
|
|
837
|
+
buf[p++] = 0x43;
|
|
838
|
+
buf[p++] = 0x41;
|
|
839
|
+
buf[p++] = 0x50;
|
|
840
|
+
buf[p++] = 0x45;
|
|
841
|
+
buf[p++] = 0x32;
|
|
842
|
+
buf[p++] = 0x2e;
|
|
843
|
+
buf[p++] = 0x30;
|
|
844
|
+
buf[p++] = 0x03;
|
|
845
|
+
buf[p++] = 0x01;
|
|
846
|
+
buf[p++] = loop_count & 0xff;
|
|
847
|
+
buf[p++] = loop_count >> 8 & 0xff;
|
|
848
|
+
buf[p++] = 0x00;
|
|
849
|
+
}
|
|
850
|
+
let ended = false;
|
|
851
|
+
this.addFrame = function (x, y, w, h, indexed_pixels, opts) {
|
|
852
|
+
if (ended === true) {
|
|
853
|
+
--p;
|
|
854
|
+
ended = false;
|
|
855
|
+
}
|
|
856
|
+
opts = opts === undefined ? {} : opts;
|
|
857
|
+
if (x < 0 || y < 0 || x > 65535 || y > 65535) throw 'x/y invalid.';
|
|
858
|
+
if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw 'Width/Height invalid.';
|
|
859
|
+
if (indexed_pixels.length < w * h) throw 'Not enough pixels for the frame size.';
|
|
860
|
+
let using_local_palette = true;
|
|
861
|
+
let palette = opts.palette;
|
|
862
|
+
if (palette === undefined || palette === null) {
|
|
863
|
+
using_local_palette = false;
|
|
864
|
+
palette = global_palette;
|
|
865
|
+
}
|
|
866
|
+
if (palette === undefined || palette === null) throw 'Must supply either a local or global palette.';
|
|
867
|
+
let num_colors = check_palette_and_num_colors(palette);
|
|
868
|
+
let min_code_size = 0;
|
|
869
|
+
while (num_colors >>= 1) {
|
|
870
|
+
++min_code_size;
|
|
871
|
+
}
|
|
872
|
+
num_colors = 1 << min_code_size;
|
|
873
|
+
const delay = opts.delay === undefined ? 0 : opts.delay;
|
|
874
|
+
const disposal = opts.disposal === undefined ? 0 : opts.disposal;
|
|
875
|
+
if (disposal < 0 || disposal > 3) throw 'Disposal out of range.';
|
|
876
|
+
let use_transparency = false;
|
|
877
|
+
let transparent_index = 0;
|
|
878
|
+
if (opts.transparent !== undefined && opts.transparent !== null) {
|
|
879
|
+
use_transparency = true;
|
|
880
|
+
transparent_index = opts.transparent;
|
|
881
|
+
if (transparent_index < 0 || transparent_index >= num_colors) throw 'Transparent color index.';
|
|
882
|
+
}
|
|
883
|
+
if (disposal !== 0 || use_transparency || delay !== 0) {
|
|
884
|
+
buf[p++] = 0x21;
|
|
885
|
+
buf[p++] = 0xf9;
|
|
886
|
+
buf[p++] = 4;
|
|
887
|
+
buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0);
|
|
888
|
+
buf[p++] = delay & 0xff;
|
|
889
|
+
buf[p++] = delay >> 8 & 0xff;
|
|
890
|
+
buf[p++] = transparent_index;
|
|
891
|
+
buf[p++] = 0;
|
|
892
|
+
}
|
|
893
|
+
buf[p++] = 0x2c;
|
|
894
|
+
buf[p++] = x & 0xff;
|
|
895
|
+
buf[p++] = x >> 8 & 0xff;
|
|
896
|
+
buf[p++] = y & 0xff;
|
|
897
|
+
buf[p++] = y >> 8 & 0xff;
|
|
898
|
+
buf[p++] = w & 0xff;
|
|
899
|
+
buf[p++] = w >> 8 & 0xff;
|
|
900
|
+
buf[p++] = h & 0xff;
|
|
901
|
+
buf[p++] = h >> 8 & 0xff;
|
|
902
|
+
buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0;
|
|
903
|
+
if (using_local_palette === true) {
|
|
904
|
+
for (let i = 0, il = palette.length; i < il; ++i) {
|
|
905
|
+
const rgb = palette[i];
|
|
906
|
+
buf[p++] = rgb >> 16 & 0xff;
|
|
907
|
+
buf[p++] = rgb >> 8 & 0xff;
|
|
908
|
+
buf[p++] = rgb & 0xff;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels);
|
|
912
|
+
};
|
|
913
|
+
this.end = function () {
|
|
914
|
+
if (ended === false) {
|
|
915
|
+
buf[p++] = 0x3b;
|
|
916
|
+
ended = true;
|
|
917
|
+
}
|
|
918
|
+
return p;
|
|
919
|
+
};
|
|
920
|
+
function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) {
|
|
921
|
+
buf[p++] = min_code_size;
|
|
922
|
+
let cur_subblock = p++;
|
|
923
|
+
const clear_code = 1 << min_code_size;
|
|
924
|
+
const code_mask = clear_code - 1;
|
|
925
|
+
const eoi_code = clear_code + 1;
|
|
926
|
+
let next_code = eoi_code + 1;
|
|
927
|
+
let cur_code_size = min_code_size + 1;
|
|
928
|
+
let cur_shift = 0;
|
|
929
|
+
let cur = 0;
|
|
930
|
+
function emit_bytes_to_buffer(bit_block_size) {
|
|
931
|
+
while (cur_shift >= bit_block_size) {
|
|
932
|
+
buf[p++] = cur & 0xff;
|
|
933
|
+
cur >>= 8;
|
|
934
|
+
cur_shift -= 8;
|
|
935
|
+
if (p === cur_subblock + 256) {
|
|
936
|
+
buf[cur_subblock] = 255;
|
|
937
|
+
cur_subblock = p++;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
function emit_code(c) {
|
|
942
|
+
cur |= c << cur_shift;
|
|
943
|
+
cur_shift += cur_code_size;
|
|
944
|
+
emit_bytes_to_buffer(8);
|
|
945
|
+
}
|
|
946
|
+
let ib_code = index_stream[0] & code_mask;
|
|
947
|
+
let code_table = {};
|
|
948
|
+
emit_code(clear_code);
|
|
949
|
+
for (let i = 1, il = index_stream.length; i < il; ++i) {
|
|
950
|
+
const k = index_stream[i] & code_mask;
|
|
951
|
+
const cur_key = ib_code << 8 | k;
|
|
952
|
+
const cur_code = code_table[cur_key];
|
|
953
|
+
if (cur_code === undefined) {
|
|
954
|
+
cur |= ib_code << cur_shift;
|
|
955
|
+
cur_shift += cur_code_size;
|
|
956
|
+
while (cur_shift >= 8) {
|
|
957
|
+
buf[p++] = cur & 0xff;
|
|
958
|
+
cur >>= 8;
|
|
959
|
+
cur_shift -= 8;
|
|
960
|
+
if (p === cur_subblock + 256) {
|
|
961
|
+
buf[cur_subblock] = 255;
|
|
962
|
+
cur_subblock = p++;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
if (next_code === 4096) {
|
|
966
|
+
emit_code(clear_code);
|
|
967
|
+
next_code = eoi_code + 1;
|
|
968
|
+
cur_code_size = min_code_size + 1;
|
|
969
|
+
code_table = {};
|
|
970
|
+
} else {
|
|
971
|
+
if (next_code >= 1 << cur_code_size) ++cur_code_size;
|
|
972
|
+
code_table[cur_key] = next_code++;
|
|
973
|
+
}
|
|
974
|
+
ib_code = k;
|
|
975
|
+
} else {
|
|
976
|
+
ib_code = cur_code;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
emit_code(ib_code);
|
|
980
|
+
emit_code(eoi_code);
|
|
981
|
+
emit_bytes_to_buffer(1);
|
|
982
|
+
if (cur_subblock + 1 === p) {
|
|
983
|
+
buf[cur_subblock] = 0;
|
|
984
|
+
} else {
|
|
985
|
+
buf[cur_subblock] = p - cur_subblock - 1;
|
|
986
|
+
buf[p++] = 0;
|
|
987
|
+
}
|
|
988
|
+
return p;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
const noop$2 = function noop() {};
|
|
992
|
+
const AnimatedGIF = function AnimatedGIF(options) {
|
|
993
|
+
this.canvas = null;
|
|
994
|
+
this.ctx = null;
|
|
995
|
+
this.repeat = 0;
|
|
996
|
+
this.frames = [];
|
|
997
|
+
this.numRenderedFrames = 0;
|
|
998
|
+
this.onRenderCompleteCallback = noop$2;
|
|
999
|
+
this.onRenderProgressCallback = noop$2;
|
|
1000
|
+
this.workers = [];
|
|
1001
|
+
this.availableWorkers = [];
|
|
1002
|
+
this.generatingGIF = false;
|
|
1003
|
+
this.options = options;
|
|
1004
|
+
this.initializeWebWorkers(options);
|
|
1005
|
+
};
|
|
1006
|
+
AnimatedGIF.prototype = {
|
|
1007
|
+
workerMethods: workerCode(),
|
|
1008
|
+
initializeWebWorkers: function initializeWebWorkers(options) {
|
|
1009
|
+
const self = this;
|
|
1010
|
+
const processFrameWorkerCode = "".concat(NeuQuant.toString(), "(").concat(workerCode.toString(), "());");
|
|
1011
|
+
let webWorkerObj = void 0;
|
|
1012
|
+
let objectUrl = void 0;
|
|
1013
|
+
let webWorker = void 0;
|
|
1014
|
+
let numWorkers = void 0;
|
|
1015
|
+
let x = -1;
|
|
1016
|
+
let workerError = '';
|
|
1017
|
+
numWorkers = options.numWorkers;
|
|
1018
|
+
while (++x < numWorkers) {
|
|
1019
|
+
webWorkerObj = utils.createWebWorker(processFrameWorkerCode);
|
|
1020
|
+
if (utils.isObject(webWorkerObj)) {
|
|
1021
|
+
objectUrl = webWorkerObj.objectUrl;
|
|
1022
|
+
webWorker = webWorkerObj.worker;
|
|
1023
|
+
self.workers.push({
|
|
1024
|
+
worker: webWorker,
|
|
1025
|
+
objectUrl
|
|
1026
|
+
});
|
|
1027
|
+
self.availableWorkers.push(webWorker);
|
|
1028
|
+
} else {
|
|
1029
|
+
workerError = webWorkerObj;
|
|
1030
|
+
utils.webWorkerError = Boolean(webWorkerObj);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
this.workerError = workerError;
|
|
1034
|
+
this.canvas = document.createElement('canvas');
|
|
1035
|
+
this.canvas.width = options.gifWidth;
|
|
1036
|
+
this.canvas.height = options.gifHeight;
|
|
1037
|
+
this.ctx = this.canvas.getContext('2d');
|
|
1038
|
+
this.frames = [];
|
|
1039
|
+
},
|
|
1040
|
+
getWorker: function getWorker() {
|
|
1041
|
+
return this.availableWorkers.pop();
|
|
1042
|
+
},
|
|
1043
|
+
freeWorker: function freeWorker(worker) {
|
|
1044
|
+
this.availableWorkers.push(worker);
|
|
1045
|
+
},
|
|
1046
|
+
byteMap: function () {
|
|
1047
|
+
const byteMap = [];
|
|
1048
|
+
for (let i = 0; i < 256; i++) {
|
|
1049
|
+
byteMap[i] = String.fromCharCode(i);
|
|
1050
|
+
}
|
|
1051
|
+
return byteMap;
|
|
1052
|
+
}(),
|
|
1053
|
+
bufferToString: function bufferToString(buffer) {
|
|
1054
|
+
const numberValues = buffer.length;
|
|
1055
|
+
let str = '';
|
|
1056
|
+
let x = -1;
|
|
1057
|
+
while (++x < numberValues) {
|
|
1058
|
+
str += this.byteMap[buffer[x]];
|
|
1059
|
+
}
|
|
1060
|
+
return str;
|
|
1061
|
+
},
|
|
1062
|
+
onFrameFinished: function onFrameFinished(progressCallback) {
|
|
1063
|
+
const self = this;
|
|
1064
|
+
const frames = self.frames;
|
|
1065
|
+
const options = self.options;
|
|
1066
|
+
const hasExistingImages = Boolean((options.images || []).length);
|
|
1067
|
+
const allDone = frames.every(function (frame) {
|
|
1068
|
+
return !frame.beingProcessed && frame.done;
|
|
1069
|
+
});
|
|
1070
|
+
self.numRenderedFrames++;
|
|
1071
|
+
if (hasExistingImages) {
|
|
1072
|
+
progressCallback(self.numRenderedFrames / frames.length);
|
|
1073
|
+
}
|
|
1074
|
+
self.onRenderProgressCallback(self.numRenderedFrames * 0.75 / frames.length);
|
|
1075
|
+
if (allDone) {
|
|
1076
|
+
if (!self.generatingGIF) {
|
|
1077
|
+
self.generateGIF(frames, self.onRenderCompleteCallback);
|
|
1078
|
+
}
|
|
1079
|
+
} else {
|
|
1080
|
+
utils.requestTimeout(function () {
|
|
1081
|
+
self.processNextFrame();
|
|
1082
|
+
}, 1);
|
|
1083
|
+
}
|
|
1084
|
+
},
|
|
1085
|
+
processFrame: function processFrame(position) {
|
|
1086
|
+
const AnimatedGifContext = this;
|
|
1087
|
+
const options = this.options;
|
|
1088
|
+
const _options = this.options;
|
|
1089
|
+
const progressCallback = _options.progressCallback;
|
|
1090
|
+
const sampleInterval = _options.sampleInterval;
|
|
1091
|
+
const frames = this.frames;
|
|
1092
|
+
let frame = void 0;
|
|
1093
|
+
let worker = void 0;
|
|
1094
|
+
const done = function done() {
|
|
1095
|
+
const ev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1096
|
+
const data = ev.data;
|
|
1097
|
+
delete frame.data;
|
|
1098
|
+
frame.pixels = Array.prototype.slice.call(data.pixels);
|
|
1099
|
+
frame.palette = Array.prototype.slice.call(data.palette);
|
|
1100
|
+
frame.done = true;
|
|
1101
|
+
frame.beingProcessed = false;
|
|
1102
|
+
AnimatedGifContext.freeWorker(worker);
|
|
1103
|
+
AnimatedGifContext.onFrameFinished(progressCallback);
|
|
1104
|
+
};
|
|
1105
|
+
frame = frames[position];
|
|
1106
|
+
if (frame.beingProcessed || frame.done) {
|
|
1107
|
+
this.onFrameFinished();
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
frame.sampleInterval = sampleInterval;
|
|
1111
|
+
frame.beingProcessed = true;
|
|
1112
|
+
frame.gifshot = true;
|
|
1113
|
+
worker = this.getWorker();
|
|
1114
|
+
if (worker) {
|
|
1115
|
+
worker.onmessage = done;
|
|
1116
|
+
worker.postMessage(frame);
|
|
1117
|
+
} else {
|
|
1118
|
+
done({
|
|
1119
|
+
data: AnimatedGifContext.workerMethods.run(frame)
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
},
|
|
1123
|
+
startRendering: function startRendering(completeCallback) {
|
|
1124
|
+
this.onRenderCompleteCallback = completeCallback;
|
|
1125
|
+
for (let i = 0; i < this.options.numWorkers && i < this.frames.length; i++) {
|
|
1126
|
+
this.processFrame(i);
|
|
1127
|
+
}
|
|
1128
|
+
},
|
|
1129
|
+
processNextFrame: function processNextFrame() {
|
|
1130
|
+
let position = -1;
|
|
1131
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
1132
|
+
const frame = this.frames[i];
|
|
1133
|
+
if (!frame.done && !frame.beingProcessed) {
|
|
1134
|
+
position = i;
|
|
1135
|
+
break;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
if (position >= 0) {
|
|
1139
|
+
this.processFrame(position);
|
|
1140
|
+
}
|
|
1141
|
+
},
|
|
1142
|
+
generateGIF: function generateGIF(frames, callback) {
|
|
1143
|
+
const buffer = [];
|
|
1144
|
+
const gifOptions = {
|
|
1145
|
+
loop: this.repeat
|
|
1146
|
+
};
|
|
1147
|
+
const options = this.options;
|
|
1148
|
+
const interval = options.interval;
|
|
1149
|
+
const frameDuration = options.frameDuration;
|
|
1150
|
+
const existingImages = options.images;
|
|
1151
|
+
const hasExistingImages = Boolean(existingImages.length);
|
|
1152
|
+
const height = options.gifHeight;
|
|
1153
|
+
const width = options.gifWidth;
|
|
1154
|
+
const gifWriter$$1 = new gifWriter(buffer, width, height, gifOptions);
|
|
1155
|
+
const onRenderProgressCallback = this.onRenderProgressCallback;
|
|
1156
|
+
const delay = hasExistingImages ? interval * 100 : 0;
|
|
1157
|
+
let bufferToString = void 0;
|
|
1158
|
+
let gif = void 0;
|
|
1159
|
+
this.generatingGIF = true;
|
|
1160
|
+
utils.each(frames, function (iterator, frame) {
|
|
1161
|
+
const framePalette = frame.palette;
|
|
1162
|
+
onRenderProgressCallback(0.75 + 0.25 * frame.position * 1.0 / frames.length);
|
|
1163
|
+
for (let i = 0; i < frameDuration; i++) {
|
|
1164
|
+
gifWriter$$1.addFrame(0, 0, width, height, frame.pixels, {
|
|
1165
|
+
palette: framePalette,
|
|
1166
|
+
delay
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
gifWriter$$1.end();
|
|
1171
|
+
onRenderProgressCallback(1.0);
|
|
1172
|
+
this.frames = [];
|
|
1173
|
+
this.generatingGIF = false;
|
|
1174
|
+
if (utils.isFunction(callback)) {
|
|
1175
|
+
bufferToString = this.bufferToString(buffer);
|
|
1176
|
+
gif = "data:image/gif;base64,".concat(utils.btoa(bufferToString));
|
|
1177
|
+
callback(gif);
|
|
1178
|
+
}
|
|
1179
|
+
},
|
|
1180
|
+
setRepeat: function setRepeat(r) {
|
|
1181
|
+
this.repeat = r;
|
|
1182
|
+
},
|
|
1183
|
+
addFrame: function addFrame(element, gifshotOptions) {
|
|
1184
|
+
gifshotOptions = utils.isObject(gifshotOptions) ? gifshotOptions : {};
|
|
1185
|
+
const self = this;
|
|
1186
|
+
const ctx = self.ctx;
|
|
1187
|
+
const options = self.options;
|
|
1188
|
+
const width = options.gifWidth;
|
|
1189
|
+
const height = options.gifHeight;
|
|
1190
|
+
const fontSize = utils.getFontSize(gifshotOptions);
|
|
1191
|
+
const _gifshotOptions = gifshotOptions;
|
|
1192
|
+
const filter = _gifshotOptions.filter;
|
|
1193
|
+
const fontColor = _gifshotOptions.fontColor;
|
|
1194
|
+
const fontFamily = _gifshotOptions.fontFamily;
|
|
1195
|
+
const fontWeight = _gifshotOptions.fontWeight;
|
|
1196
|
+
const gifHeight = _gifshotOptions.gifHeight;
|
|
1197
|
+
const gifWidth = _gifshotOptions.gifWidth;
|
|
1198
|
+
const text = _gifshotOptions.text;
|
|
1199
|
+
const textAlign = _gifshotOptions.textAlign;
|
|
1200
|
+
const textBaseline = _gifshotOptions.textBaseline;
|
|
1201
|
+
const textXCoordinate = gifshotOptions.textXCoordinate ? gifshotOptions.textXCoordinate : textAlign === 'left' ? 1 : textAlign === 'right' ? width : width / 2;
|
|
1202
|
+
const textYCoordinate = gifshotOptions.textYCoordinate ? gifshotOptions.textYCoordinate : textBaseline === 'top' ? 1 : textBaseline === 'center' ? height / 2 : height;
|
|
1203
|
+
const font = "".concat(fontWeight, " ").concat(fontSize, " ").concat(fontFamily);
|
|
1204
|
+
let imageData = void 0;
|
|
1205
|
+
try {
|
|
1206
|
+
ctx.filter = filter;
|
|
1207
|
+
ctx.drawImage(element, 0, 0, width, height);
|
|
1208
|
+
if (text) {
|
|
1209
|
+
ctx.font = font;
|
|
1210
|
+
ctx.fillStyle = fontColor;
|
|
1211
|
+
ctx.textAlign = textAlign;
|
|
1212
|
+
ctx.textBaseline = textBaseline;
|
|
1213
|
+
ctx.fillText(text, textXCoordinate, textYCoordinate);
|
|
1214
|
+
}
|
|
1215
|
+
imageData = ctx.getImageData(0, 0, width, height);
|
|
1216
|
+
self.addFrameImageData(imageData);
|
|
1217
|
+
} catch (e) {
|
|
1218
|
+
return "".concat(e);
|
|
1219
|
+
}
|
|
1220
|
+
},
|
|
1221
|
+
addFrameImageData: function addFrameImageData() {
|
|
1222
|
+
const imageData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1223
|
+
const frames = this.frames;
|
|
1224
|
+
const imageDataArray = imageData.data;
|
|
1225
|
+
this.frames.push({
|
|
1226
|
+
data: imageDataArray,
|
|
1227
|
+
width: imageData.width,
|
|
1228
|
+
height: imageData.height,
|
|
1229
|
+
palette: null,
|
|
1230
|
+
dithering: null,
|
|
1231
|
+
done: false,
|
|
1232
|
+
beingProcessed: false,
|
|
1233
|
+
position: frames.length
|
|
1234
|
+
});
|
|
1235
|
+
},
|
|
1236
|
+
onRenderProgress: function onRenderProgress(callback) {
|
|
1237
|
+
this.onRenderProgressCallback = callback;
|
|
1238
|
+
},
|
|
1239
|
+
isRendering: function isRendering() {
|
|
1240
|
+
return this.generatingGIF;
|
|
1241
|
+
},
|
|
1242
|
+
getBase64GIF: function getBase64GIF(completeCallback) {
|
|
1243
|
+
const self = this;
|
|
1244
|
+
const onRenderComplete = function onRenderComplete(gif) {
|
|
1245
|
+
self.destroyWorkers();
|
|
1246
|
+
utils.requestTimeout(function () {
|
|
1247
|
+
completeCallback(gif);
|
|
1248
|
+
}, 0);
|
|
1249
|
+
};
|
|
1250
|
+
self.startRendering(onRenderComplete);
|
|
1251
|
+
},
|
|
1252
|
+
destroyWorkers: function destroyWorkers() {
|
|
1253
|
+
if (this.workerError) {
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
const workers = this.workers;
|
|
1257
|
+
utils.each(workers, function (iterator, workerObj) {
|
|
1258
|
+
const worker = workerObj.worker;
|
|
1259
|
+
const objectUrl = workerObj.objectUrl;
|
|
1260
|
+
worker.terminate();
|
|
1261
|
+
utils.URL.revokeObjectURL(objectUrl);
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
function getBase64GIF(animatedGifInstance, callback) {
|
|
1266
|
+
animatedGifInstance.getBase64GIF(function (image) {
|
|
1267
|
+
callback({
|
|
1268
|
+
error: false,
|
|
1269
|
+
errorCode: '',
|
|
1270
|
+
errorMsg: '',
|
|
1271
|
+
image
|
|
1272
|
+
});
|
|
1273
|
+
});
|
|
1274
|
+
}
|
|
1275
|
+
function existingImages() {
|
|
1276
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1277
|
+
const self = this;
|
|
1278
|
+
const callback = obj.callback;
|
|
1279
|
+
const images = obj.images;
|
|
1280
|
+
const options = obj.options;
|
|
1281
|
+
let imagesLength = obj.imagesLength;
|
|
1282
|
+
const skipObj = {
|
|
1283
|
+
getUserMedia: true,
|
|
1284
|
+
'globalThis.URL': true
|
|
1285
|
+
};
|
|
1286
|
+
const errorObj = error.validate(skipObj);
|
|
1287
|
+
const loadedImages = [];
|
|
1288
|
+
let loadedImagesLength = 0;
|
|
1289
|
+
let tempImage = void 0;
|
|
1290
|
+
let ag = void 0;
|
|
1291
|
+
if (errorObj.error) {
|
|
1292
|
+
return callback(errorObj);
|
|
1293
|
+
}
|
|
1294
|
+
ag = new AnimatedGIF(options);
|
|
1295
|
+
utils.each(images, function (index, image) {
|
|
1296
|
+
const currentImage = image;
|
|
1297
|
+
if (utils.isElement(currentImage)) {
|
|
1298
|
+
if (options.crossOrigin) {
|
|
1299
|
+
currentImage.crossOrigin = options.crossOrigin;
|
|
1300
|
+
}
|
|
1301
|
+
loadedImages[index] = currentImage;
|
|
1302
|
+
loadedImagesLength += 1;
|
|
1303
|
+
if (loadedImagesLength === imagesLength) {
|
|
1304
|
+
addLoadedImagesToGif();
|
|
1305
|
+
}
|
|
1306
|
+
} else if (utils.isString(currentImage)) {
|
|
1307
|
+
tempImage = new Image();
|
|
1308
|
+
if (options.crossOrigin) {
|
|
1309
|
+
tempImage.crossOrigin = options.crossOrigin;
|
|
1310
|
+
}
|
|
1311
|
+
(function (tempImage) {
|
|
1312
|
+
if (image.text) {
|
|
1313
|
+
tempImage.text = image.text;
|
|
1314
|
+
}
|
|
1315
|
+
tempImage.onerror = function (e) {
|
|
1316
|
+
let obj = void 0;
|
|
1317
|
+
--imagesLength;
|
|
1318
|
+
if (imagesLength === 0) {
|
|
1319
|
+
obj = {};
|
|
1320
|
+
obj.error = 'None of the requested images was capable of being retrieved';
|
|
1321
|
+
return callback(obj);
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
tempImage.onload = function (e) {
|
|
1325
|
+
if (image.text) {
|
|
1326
|
+
loadedImages[index] = {
|
|
1327
|
+
img: tempImage,
|
|
1328
|
+
text: tempImage.text
|
|
1329
|
+
};
|
|
1330
|
+
} else {
|
|
1331
|
+
loadedImages[index] = tempImage;
|
|
1332
|
+
}
|
|
1333
|
+
loadedImagesLength += 1;
|
|
1334
|
+
if (loadedImagesLength === imagesLength) {
|
|
1335
|
+
addLoadedImagesToGif();
|
|
1336
|
+
}
|
|
1337
|
+
utils.removeElement(tempImage);
|
|
1338
|
+
};
|
|
1339
|
+
tempImage.src = currentImage;
|
|
1340
|
+
})(tempImage);
|
|
1341
|
+
utils.setCSSAttr(tempImage, {
|
|
1342
|
+
position: 'fixed',
|
|
1343
|
+
opacity: '0'
|
|
1344
|
+
});
|
|
1345
|
+
document.body.appendChild(tempImage);
|
|
1346
|
+
}
|
|
1347
|
+
});
|
|
1348
|
+
function addLoadedImagesToGif() {
|
|
1349
|
+
utils.each(loadedImages, function (index, loadedImage) {
|
|
1350
|
+
if (loadedImage) {
|
|
1351
|
+
if (loadedImage.text) {
|
|
1352
|
+
ag.addFrame(loadedImage.img, options, loadedImage.text);
|
|
1353
|
+
} else {
|
|
1354
|
+
ag.addFrame(loadedImage, options);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
});
|
|
1358
|
+
getBase64GIF(ag, callback);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
const noop$3 = function noop() {};
|
|
1362
|
+
const screenShot = {
|
|
1363
|
+
getGIF: function getGIF() {
|
|
1364
|
+
const options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1365
|
+
let callback = arguments[1];
|
|
1366
|
+
callback = utils.isFunction(callback) ? callback : noop$3;
|
|
1367
|
+
const canvas = document.createElement('canvas');
|
|
1368
|
+
let context = void 0;
|
|
1369
|
+
const existingImages = options.images;
|
|
1370
|
+
const hasExistingImages = Boolean(existingImages.length);
|
|
1371
|
+
const cameraStream = options.cameraStream;
|
|
1372
|
+
const crop = options.crop;
|
|
1373
|
+
const filter = options.filter;
|
|
1374
|
+
const fontColor = options.fontColor;
|
|
1375
|
+
const fontFamily = options.fontFamily;
|
|
1376
|
+
const fontWeight = options.fontWeight;
|
|
1377
|
+
const keepCameraOn = options.keepCameraOn;
|
|
1378
|
+
const numWorkers = options.numWorkers;
|
|
1379
|
+
const progressCallback = options.progressCallback;
|
|
1380
|
+
const saveRenderingContexts = options.saveRenderingContexts;
|
|
1381
|
+
const savedRenderingContexts = options.savedRenderingContexts;
|
|
1382
|
+
const text = options.text;
|
|
1383
|
+
const textAlign = options.textAlign;
|
|
1384
|
+
const textBaseline = options.textBaseline;
|
|
1385
|
+
const videoElement = options.videoElement;
|
|
1386
|
+
const videoHeight = options.videoHeight;
|
|
1387
|
+
const videoWidth = options.videoWidth;
|
|
1388
|
+
const webcamVideoElement = options.webcamVideoElement;
|
|
1389
|
+
const gifWidth = Number(options.gifWidth);
|
|
1390
|
+
const gifHeight = Number(options.gifHeight);
|
|
1391
|
+
let interval = Number(options.interval);
|
|
1392
|
+
const sampleInterval = Number(options.sampleInterval);
|
|
1393
|
+
const waitBetweenFrames = hasExistingImages ? 0 : interval * 1000;
|
|
1394
|
+
const renderingContextsToSave = [];
|
|
1395
|
+
let numFrames = savedRenderingContexts.length ? savedRenderingContexts.length : options.numFrames;
|
|
1396
|
+
let pendingFrames = numFrames;
|
|
1397
|
+
const ag = new AnimatedGIF(options);
|
|
1398
|
+
const fontSize = utils.getFontSize(options);
|
|
1399
|
+
const textXCoordinate = options.textXCoordinate ? options.textXCoordinate : textAlign === 'left' ? 1 : textAlign === 'right' ? gifWidth : gifWidth / 2;
|
|
1400
|
+
const textYCoordinate = options.textYCoordinate ? options.textYCoordinate : textBaseline === 'top' ? 1 : textBaseline === 'center' ? gifHeight / 2 : gifHeight;
|
|
1401
|
+
const font = "".concat(fontWeight, " ").concat(fontSize, " ").concat(fontFamily);
|
|
1402
|
+
let sourceX = crop ? Math.floor(crop.scaledWidth / 2) : 0;
|
|
1403
|
+
let sourceWidth = crop ? videoWidth - crop.scaledWidth : 0;
|
|
1404
|
+
let sourceY = crop ? Math.floor(crop.scaledHeight / 2) : 0;
|
|
1405
|
+
let sourceHeight = crop ? videoHeight - crop.scaledHeight : 0;
|
|
1406
|
+
const captureFrames = function captureSingleFrame() {
|
|
1407
|
+
const framesLeft = pendingFrames - 1;
|
|
1408
|
+
if (savedRenderingContexts.length) {
|
|
1409
|
+
context.putImageData(savedRenderingContexts[numFrames - pendingFrames], 0, 0);
|
|
1410
|
+
finishCapture();
|
|
1411
|
+
} else {
|
|
1412
|
+
drawVideo();
|
|
1413
|
+
}
|
|
1414
|
+
function drawVideo() {
|
|
1415
|
+
try {
|
|
1416
|
+
if (sourceWidth > videoWidth) {
|
|
1417
|
+
sourceWidth = videoWidth;
|
|
1418
|
+
}
|
|
1419
|
+
if (sourceHeight > videoHeight) {
|
|
1420
|
+
sourceHeight = videoHeight;
|
|
1421
|
+
}
|
|
1422
|
+
if (sourceX < 0) {
|
|
1423
|
+
sourceX = 0;
|
|
1424
|
+
}
|
|
1425
|
+
if (sourceY < 0) {
|
|
1426
|
+
sourceY = 0;
|
|
1427
|
+
}
|
|
1428
|
+
context.filter = filter;
|
|
1429
|
+
context.drawImage(videoElement, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, gifWidth, gifHeight);
|
|
1430
|
+
finishCapture();
|
|
1431
|
+
} catch (e) {
|
|
1432
|
+
if (e.name === 'NS_ERROR_NOT_AVAILABLE') {
|
|
1433
|
+
utils.requestTimeout(drawVideo, 100);
|
|
1434
|
+
} else {
|
|
1435
|
+
throw e;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
function finishCapture() {
|
|
1440
|
+
let imageData = void 0;
|
|
1441
|
+
if (saveRenderingContexts) {
|
|
1442
|
+
renderingContextsToSave.push(context.getImageData(0, 0, gifWidth, gifHeight));
|
|
1443
|
+
}
|
|
1444
|
+
if (text) {
|
|
1445
|
+
context.font = font;
|
|
1446
|
+
context.fillStyle = fontColor;
|
|
1447
|
+
context.textAlign = textAlign;
|
|
1448
|
+
context.textBaseline = textBaseline;
|
|
1449
|
+
context.fillText(text, textXCoordinate, textYCoordinate);
|
|
1450
|
+
}
|
|
1451
|
+
imageData = context.getImageData(0, 0, gifWidth, gifHeight);
|
|
1452
|
+
ag.addFrameImageData(imageData);
|
|
1453
|
+
pendingFrames = framesLeft;
|
|
1454
|
+
progressCallback((numFrames - pendingFrames) / numFrames);
|
|
1455
|
+
if (framesLeft > 0) {
|
|
1456
|
+
utils.requestTimeout(captureSingleFrame, waitBetweenFrames);
|
|
1457
|
+
}
|
|
1458
|
+
if (!pendingFrames) {
|
|
1459
|
+
ag.getBase64GIF(function (image) {
|
|
1460
|
+
callback({
|
|
1461
|
+
error: false,
|
|
1462
|
+
errorCode: '',
|
|
1463
|
+
errorMsg: '',
|
|
1464
|
+
image,
|
|
1465
|
+
cameraStream,
|
|
1466
|
+
videoElement,
|
|
1467
|
+
webcamVideoElement,
|
|
1468
|
+
savedRenderingContexts: renderingContextsToSave,
|
|
1469
|
+
keepCameraOn
|
|
1470
|
+
});
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
};
|
|
1475
|
+
numFrames = numFrames !== undefined ? numFrames : 10;
|
|
1476
|
+
interval = interval !== undefined ? interval : 0.1;
|
|
1477
|
+
canvas.width = gifWidth;
|
|
1478
|
+
canvas.height = gifHeight;
|
|
1479
|
+
context = canvas.getContext('2d');
|
|
1480
|
+
(function capture() {
|
|
1481
|
+
if (!savedRenderingContexts.length && videoElement.currentTime === 0) {
|
|
1482
|
+
utils.requestTimeout(capture, 100);
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
captureFrames();
|
|
1486
|
+
})();
|
|
1487
|
+
},
|
|
1488
|
+
getCropDimensions: function getCropDimensions() {
|
|
1489
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1490
|
+
const width = obj.videoWidth;
|
|
1491
|
+
const height = obj.videoHeight;
|
|
1492
|
+
const gifWidth = obj.gifWidth;
|
|
1493
|
+
const gifHeight = obj.gifHeight;
|
|
1494
|
+
const result = {
|
|
1495
|
+
width: 0,
|
|
1496
|
+
height: 0,
|
|
1497
|
+
scaledWidth: 0,
|
|
1498
|
+
scaledHeight: 0
|
|
1499
|
+
};
|
|
1500
|
+
if (width > height) {
|
|
1501
|
+
result.width = Math.round(width * (gifHeight / height)) - gifWidth;
|
|
1502
|
+
result.scaledWidth = Math.round(result.width * (height / gifHeight));
|
|
1503
|
+
} else {
|
|
1504
|
+
result.height = Math.round(height * (gifWidth / width)) - gifHeight;
|
|
1505
|
+
result.scaledHeight = Math.round(result.height * (width / gifWidth));
|
|
1506
|
+
}
|
|
1507
|
+
return result;
|
|
1508
|
+
}
|
|
1509
|
+
};
|
|
1510
|
+
var videoStream = {
|
|
1511
|
+
loadedData: false,
|
|
1512
|
+
defaultVideoDimensions: {
|
|
1513
|
+
width: 640,
|
|
1514
|
+
height: 480
|
|
1515
|
+
},
|
|
1516
|
+
findVideoSize: function findVideoSizeMethod(obj) {
|
|
1517
|
+
findVideoSizeMethod.attempts = findVideoSizeMethod.attempts || 0;
|
|
1518
|
+
const cameraStream = obj.cameraStream;
|
|
1519
|
+
const completedCallback = obj.completedCallback;
|
|
1520
|
+
const videoElement = obj.videoElement;
|
|
1521
|
+
if (!videoElement) {
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
if (videoElement.videoWidth > 0 && videoElement.videoHeight > 0) {
|
|
1525
|
+
videoElement.removeEventListener('loadeddata', videoStream.findVideoSize);
|
|
1526
|
+
completedCallback({
|
|
1527
|
+
videoElement,
|
|
1528
|
+
cameraStream,
|
|
1529
|
+
videoWidth: videoElement.videoWidth,
|
|
1530
|
+
videoHeight: videoElement.videoHeight
|
|
1531
|
+
});
|
|
1532
|
+
} else if (findVideoSizeMethod.attempts < 10) {
|
|
1533
|
+
findVideoSizeMethod.attempts += 1;
|
|
1534
|
+
utils.requestTimeout(function () {
|
|
1535
|
+
videoStream.findVideoSize(obj);
|
|
1536
|
+
}, 400);
|
|
1537
|
+
} else {
|
|
1538
|
+
completedCallback({
|
|
1539
|
+
videoElement,
|
|
1540
|
+
cameraStream,
|
|
1541
|
+
videoWidth: videoStream.defaultVideoDimensions.width,
|
|
1542
|
+
videoHeight: videoStream.defaultVideoDimensions.height
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
},
|
|
1546
|
+
onStreamingTimeout: function onStreamingTimeout(callback) {
|
|
1547
|
+
if (utils.isFunction(callback)) {
|
|
1548
|
+
callback({
|
|
1549
|
+
error: true,
|
|
1550
|
+
errorCode: 'getUserMedia',
|
|
1551
|
+
errorMsg: 'There was an issue with the getUserMedia API - Timed out while trying to start streaming',
|
|
1552
|
+
image: null,
|
|
1553
|
+
cameraStream: {}
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
},
|
|
1557
|
+
stream: function stream(obj) {
|
|
1558
|
+
const existingVideo = utils.isArray(obj.existingVideo) ? obj.existingVideo[0] : obj.existingVideo;
|
|
1559
|
+
const cameraStream = obj.cameraStream;
|
|
1560
|
+
const completedCallback = obj.completedCallback;
|
|
1561
|
+
const streamedCallback = obj.streamedCallback;
|
|
1562
|
+
const videoElement = obj.videoElement;
|
|
1563
|
+
if (utils.isFunction(streamedCallback)) {
|
|
1564
|
+
streamedCallback();
|
|
1565
|
+
}
|
|
1566
|
+
if (existingVideo) {
|
|
1567
|
+
if (utils.isString(existingVideo)) {
|
|
1568
|
+
videoElement.src = existingVideo;
|
|
1569
|
+
videoElement.innerHTML = "<source src=\"".concat(existingVideo, "\" type=\"video/").concat(utils.getExtension(existingVideo), "\" />");
|
|
1570
|
+
} else if (existingVideo instanceof Blob) {
|
|
1571
|
+
try {
|
|
1572
|
+
videoElement.src = utils.URL.createObjectURL(existingVideo);
|
|
1573
|
+
} catch (e) {}
|
|
1574
|
+
videoElement.innerHTML = "<source src=\"".concat(existingVideo, "\" type=\"").concat(existingVideo.type, "\" />");
|
|
1575
|
+
}
|
|
1576
|
+
} else if (videoElement.mozSrcObject) {
|
|
1577
|
+
videoElement.mozSrcObject = cameraStream;
|
|
1578
|
+
} else if (utils.URL) {
|
|
1579
|
+
try {
|
|
1580
|
+
videoElement.srcObject = cameraStream;
|
|
1581
|
+
videoElement.src = utils.URL.createObjectURL(cameraStream);
|
|
1582
|
+
} catch (e) {
|
|
1583
|
+
videoElement.srcObject = cameraStream;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
videoElement.play();
|
|
1587
|
+
utils.requestTimeout(function checkLoadedData() {
|
|
1588
|
+
checkLoadedData.count = checkLoadedData.count || 0;
|
|
1589
|
+
if (videoStream.loadedData === true) {
|
|
1590
|
+
videoStream.findVideoSize({
|
|
1591
|
+
videoElement,
|
|
1592
|
+
cameraStream,
|
|
1593
|
+
completedCallback
|
|
1594
|
+
});
|
|
1595
|
+
videoStream.loadedData = false;
|
|
1596
|
+
} else {
|
|
1597
|
+
checkLoadedData.count += 1;
|
|
1598
|
+
if (checkLoadedData.count > 10) {
|
|
1599
|
+
videoStream.findVideoSize({
|
|
1600
|
+
videoElement,
|
|
1601
|
+
cameraStream,
|
|
1602
|
+
completedCallback
|
|
1603
|
+
});
|
|
1604
|
+
} else {
|
|
1605
|
+
checkLoadedData();
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
}, 0);
|
|
1609
|
+
},
|
|
1610
|
+
startStreaming: function startStreaming(obj) {
|
|
1611
|
+
const errorCallback = utils.isFunction(obj.error) ? obj.error : utils.noop;
|
|
1612
|
+
const streamedCallback = utils.isFunction(obj.streamed) ? obj.streamed : utils.noop;
|
|
1613
|
+
const completedCallback = utils.isFunction(obj.completed) ? obj.completed : utils.noop;
|
|
1614
|
+
const crossOrigin = obj.crossOrigin;
|
|
1615
|
+
const existingVideo = obj.existingVideo;
|
|
1616
|
+
const lastCameraStream = obj.lastCameraStream;
|
|
1617
|
+
const options = obj.options;
|
|
1618
|
+
const webcamVideoElement = obj.webcamVideoElement;
|
|
1619
|
+
const videoElement = utils.isElement(existingVideo) ? existingVideo : webcamVideoElement ? webcamVideoElement : document.createElement('video');
|
|
1620
|
+
const cameraStream = void 0;
|
|
1621
|
+
if (crossOrigin) {
|
|
1622
|
+
videoElement.crossOrigin = options.crossOrigin;
|
|
1623
|
+
}
|
|
1624
|
+
videoElement.autoplay = true;
|
|
1625
|
+
videoElement.loop = true;
|
|
1626
|
+
videoElement.muted = true;
|
|
1627
|
+
videoElement.addEventListener('loadeddata', function (event) {
|
|
1628
|
+
videoStream.loadedData = true;
|
|
1629
|
+
if (options.offset) {
|
|
1630
|
+
videoElement.currentTime = options.offset;
|
|
1631
|
+
}
|
|
1632
|
+
});
|
|
1633
|
+
if (existingVideo) {
|
|
1634
|
+
videoStream.stream({
|
|
1635
|
+
videoElement,
|
|
1636
|
+
existingVideo,
|
|
1637
|
+
completedCallback
|
|
1638
|
+
});
|
|
1639
|
+
} else if (lastCameraStream) {
|
|
1640
|
+
videoStream.stream({
|
|
1641
|
+
videoElement,
|
|
1642
|
+
cameraStream: lastCameraStream,
|
|
1643
|
+
streamedCallback,
|
|
1644
|
+
completedCallback
|
|
1645
|
+
});
|
|
1646
|
+
} else {
|
|
1647
|
+
utils.getUserMedia({
|
|
1648
|
+
video: true
|
|
1649
|
+
}, function (stream) {
|
|
1650
|
+
videoStream.stream({
|
|
1651
|
+
videoElement,
|
|
1652
|
+
cameraStream: stream,
|
|
1653
|
+
streamedCallback,
|
|
1654
|
+
completedCallback
|
|
1655
|
+
});
|
|
1656
|
+
}, errorCallback);
|
|
1657
|
+
}
|
|
1658
|
+
},
|
|
1659
|
+
startVideoStreaming: function startVideoStreaming(callback) {
|
|
1660
|
+
const options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1661
|
+
const timeoutLength = options.timeout !== undefined ? options.timeout : 0;
|
|
1662
|
+
const originalCallback = options.callback;
|
|
1663
|
+
const webcamVideoElement = options.webcamVideoElement;
|
|
1664
|
+
let noGetUserMediaSupportTimeout = void 0;
|
|
1665
|
+
if (timeoutLength > 0) {
|
|
1666
|
+
noGetUserMediaSupportTimeout = utils.requestTimeout(function () {
|
|
1667
|
+
videoStream.onStreamingTimeout(originalCallback);
|
|
1668
|
+
}, 10000);
|
|
1669
|
+
}
|
|
1670
|
+
videoStream.startStreaming({
|
|
1671
|
+
error: function error() {
|
|
1672
|
+
originalCallback({
|
|
1673
|
+
error: true,
|
|
1674
|
+
errorCode: 'getUserMedia',
|
|
1675
|
+
errorMsg: 'There was an issue with the getUserMedia API - the user probably denied permission',
|
|
1676
|
+
image: null,
|
|
1677
|
+
cameraStream: {}
|
|
1678
|
+
});
|
|
1679
|
+
},
|
|
1680
|
+
streamed: function streamed() {
|
|
1681
|
+
clearTimeout(noGetUserMediaSupportTimeout);
|
|
1682
|
+
},
|
|
1683
|
+
completed: function completed() {
|
|
1684
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1685
|
+
const cameraStream = obj.cameraStream;
|
|
1686
|
+
const videoElement = obj.videoElement;
|
|
1687
|
+
const videoHeight = obj.videoHeight;
|
|
1688
|
+
const videoWidth = obj.videoWidth;
|
|
1689
|
+
callback({
|
|
1690
|
+
cameraStream,
|
|
1691
|
+
videoElement,
|
|
1692
|
+
videoHeight,
|
|
1693
|
+
videoWidth
|
|
1694
|
+
});
|
|
1695
|
+
},
|
|
1696
|
+
lastCameraStream: options.lastCameraStream,
|
|
1697
|
+
webcamVideoElement,
|
|
1698
|
+
crossOrigin: options.crossOrigin,
|
|
1699
|
+
options
|
|
1700
|
+
});
|
|
1701
|
+
},
|
|
1702
|
+
stopVideoStreaming: function stopVideoStreaming(obj) {
|
|
1703
|
+
obj = utils.isObject(obj) ? obj : {};
|
|
1704
|
+
const _obj = obj;
|
|
1705
|
+
const keepCameraOn = _obj.keepCameraOn;
|
|
1706
|
+
const videoElement = _obj.videoElement;
|
|
1707
|
+
const webcamVideoElement = _obj.webcamVideoElement;
|
|
1708
|
+
const cameraStream = obj.cameraStream || {};
|
|
1709
|
+
const cameraStreamTracks = cameraStream.getTracks ? cameraStream.getTracks() || [] : [];
|
|
1710
|
+
const hasCameraStreamTracks = Boolean(cameraStreamTracks.length);
|
|
1711
|
+
const firstCameraStreamTrack = cameraStreamTracks[0];
|
|
1712
|
+
if (!keepCameraOn && hasCameraStreamTracks) {
|
|
1713
|
+
if (utils.isFunction(firstCameraStreamTrack.stop)) {
|
|
1714
|
+
firstCameraStreamTrack.stop();
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
if (utils.isElement(videoElement) && !webcamVideoElement) {
|
|
1718
|
+
videoElement.pause();
|
|
1719
|
+
if (utils.isFunction(utils.URL.revokeObjectURL) && !utils.webWorkerError) {
|
|
1720
|
+
if (videoElement.src) {
|
|
1721
|
+
utils.URL.revokeObjectURL(videoElement.src);
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
utils.removeElement(videoElement);
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
};
|
|
1728
|
+
function stopVideoStreaming(options) {
|
|
1729
|
+
options = utils.isObject(options) ? options : {};
|
|
1730
|
+
videoStream.stopVideoStreaming(options);
|
|
1731
|
+
}
|
|
1732
|
+
function createAndGetGIF(obj, callback) {
|
|
1733
|
+
const options = obj.options || {};
|
|
1734
|
+
const images = options.images;
|
|
1735
|
+
const video = options.video;
|
|
1736
|
+
const gifWidth = Number(options.gifWidth);
|
|
1737
|
+
const gifHeight = Number(options.gifHeight);
|
|
1738
|
+
const numFrames = Number(options.numFrames);
|
|
1739
|
+
const cameraStream = obj.cameraStream;
|
|
1740
|
+
const videoElement = obj.videoElement;
|
|
1741
|
+
const videoWidth = obj.videoWidth;
|
|
1742
|
+
const videoHeight = obj.videoHeight;
|
|
1743
|
+
const cropDimensions = screenShot.getCropDimensions({
|
|
1744
|
+
videoWidth,
|
|
1745
|
+
videoHeight,
|
|
1746
|
+
gifHeight,
|
|
1747
|
+
gifWidth
|
|
1748
|
+
});
|
|
1749
|
+
const completeCallback = callback;
|
|
1750
|
+
options.crop = cropDimensions;
|
|
1751
|
+
options.videoElement = videoElement;
|
|
1752
|
+
options.videoWidth = videoWidth;
|
|
1753
|
+
options.videoHeight = videoHeight;
|
|
1754
|
+
options.cameraStream = cameraStream;
|
|
1755
|
+
if (!utils.isElement(videoElement)) {
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
videoElement.width = gifWidth + cropDimensions.width;
|
|
1759
|
+
videoElement.height = gifHeight + cropDimensions.height;
|
|
1760
|
+
if (!options.webcamVideoElement) {
|
|
1761
|
+
utils.setCSSAttr(videoElement, {
|
|
1762
|
+
position: 'fixed',
|
|
1763
|
+
opacity: '0'
|
|
1764
|
+
});
|
|
1765
|
+
document.body.appendChild(videoElement);
|
|
1766
|
+
}
|
|
1767
|
+
videoElement.play();
|
|
1768
|
+
screenShot.getGIF(options, function (obj) {
|
|
1769
|
+
if ((!images || !images.length) && (!video || !video.length)) {
|
|
1770
|
+
stopVideoStreaming(obj);
|
|
1771
|
+
}
|
|
1772
|
+
completeCallback(obj);
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1775
|
+
function existingVideo() {
|
|
1776
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1777
|
+
const callback = obj.callback;
|
|
1778
|
+
let existingVideo = obj.existingVideo;
|
|
1779
|
+
const options = obj.options;
|
|
1780
|
+
const skipObj = {
|
|
1781
|
+
getUserMedia: true,
|
|
1782
|
+
'globalThis.URL': true
|
|
1783
|
+
};
|
|
1784
|
+
const errorObj = error.validate(skipObj);
|
|
1785
|
+
const loadedImages = 0;
|
|
1786
|
+
let videoType = void 0;
|
|
1787
|
+
let videoSrc = void 0;
|
|
1788
|
+
const tempImage = void 0;
|
|
1789
|
+
const ag = void 0;
|
|
1790
|
+
if (errorObj.error) {
|
|
1791
|
+
return callback(errorObj);
|
|
1792
|
+
}
|
|
1793
|
+
if (utils.isElement(existingVideo) && existingVideo.src) {
|
|
1794
|
+
videoSrc = existingVideo.src;
|
|
1795
|
+
videoType = utils.getExtension(videoSrc);
|
|
1796
|
+
if (!utils.isSupported.videoCodecs[videoType]) {
|
|
1797
|
+
return callback(error.messages.videoCodecs);
|
|
1798
|
+
}
|
|
1799
|
+
} else if (utils.isArray(existingVideo)) {
|
|
1800
|
+
utils.each(existingVideo, function (iterator, videoSrc) {
|
|
1801
|
+
if (videoSrc instanceof Blob) {
|
|
1802
|
+
videoType = videoSrc.type.substr(videoSrc.type.lastIndexOf('/') + 1, videoSrc.length);
|
|
1803
|
+
} else {
|
|
1804
|
+
videoType = videoSrc.substr(videoSrc.lastIndexOf('.') + 1, videoSrc.length);
|
|
1805
|
+
}
|
|
1806
|
+
if (utils.isSupported.videoCodecs[videoType]) {
|
|
1807
|
+
existingVideo = videoSrc;
|
|
1808
|
+
return false;
|
|
1809
|
+
}
|
|
1810
|
+
});
|
|
1811
|
+
}
|
|
1812
|
+
videoStream.startStreaming({
|
|
1813
|
+
completed: function completed(obj) {
|
|
1814
|
+
obj.options = options || {};
|
|
1815
|
+
createAndGetGIF(obj, callback);
|
|
1816
|
+
},
|
|
1817
|
+
existingVideo,
|
|
1818
|
+
crossOrigin: options.crossOrigin,
|
|
1819
|
+
options
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
function existingWebcam() {
|
|
1823
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1824
|
+
const callback = obj.callback;
|
|
1825
|
+
const lastCameraStream = obj.lastCameraStream;
|
|
1826
|
+
const options = obj.options;
|
|
1827
|
+
const webcamVideoElement = obj.webcamVideoElement;
|
|
1828
|
+
if (!isWebCamGIFSupported()) {
|
|
1829
|
+
return callback(error.validate());
|
|
1830
|
+
}
|
|
1831
|
+
if (options.savedRenderingContexts.length) {
|
|
1832
|
+
screenShot.getGIF(options, function (obj) {
|
|
1833
|
+
callback(obj);
|
|
1834
|
+
});
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
videoStream.startVideoStreaming(function () {
|
|
1838
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1839
|
+
obj.options = options || {};
|
|
1840
|
+
createAndGetGIF(obj, callback);
|
|
1841
|
+
}, {
|
|
1842
|
+
lastCameraStream,
|
|
1843
|
+
callback,
|
|
1844
|
+
webcamVideoElement,
|
|
1845
|
+
crossOrigin: options.crossOrigin
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1848
|
+
function createGIF(userOptions, callback) {
|
|
1849
|
+
callback = utils.isFunction(userOptions) ? userOptions : callback;
|
|
1850
|
+
userOptions = utils.isObject(userOptions) ? userOptions : {};
|
|
1851
|
+
if (!utils.isFunction(callback)) {
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
let options = utils.normalizeOptions(defaultOptions, userOptions) || {};
|
|
1855
|
+
const lastCameraStream = userOptions.cameraStream;
|
|
1856
|
+
const images = options.images;
|
|
1857
|
+
const imagesLength = images ? images.length : 0;
|
|
1858
|
+
const video = options.video;
|
|
1859
|
+
const webcamVideoElement = options.webcamVideoElement;
|
|
1860
|
+
options = utils.normalizeOptions(options, {
|
|
1861
|
+
gifWidth: Math.floor(options.gifWidth),
|
|
1862
|
+
gifHeight: Math.floor(options.gifHeight)
|
|
1863
|
+
});
|
|
1864
|
+
if (imagesLength) {
|
|
1865
|
+
existingImages({
|
|
1866
|
+
images,
|
|
1867
|
+
imagesLength,
|
|
1868
|
+
callback,
|
|
1869
|
+
options
|
|
1870
|
+
});
|
|
1871
|
+
} else if (video) {
|
|
1872
|
+
existingVideo({
|
|
1873
|
+
existingVideo: video,
|
|
1874
|
+
callback,
|
|
1875
|
+
options
|
|
1876
|
+
});
|
|
1877
|
+
} else {
|
|
1878
|
+
existingWebcam({
|
|
1879
|
+
lastCameraStream,
|
|
1880
|
+
callback,
|
|
1881
|
+
webcamVideoElement,
|
|
1882
|
+
options
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
function takeSnapShot(userOptions, callback) {
|
|
1887
|
+
callback = utils.isFunction(userOptions) ? userOptions : callback;
|
|
1888
|
+
userOptions = utils.isObject(userOptions) ? userOptions : {};
|
|
1889
|
+
if (!utils.isFunction(callback)) {
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1892
|
+
const mergedOptions = utils.normalizeOptions(defaultOptions, userOptions);
|
|
1893
|
+
const options = utils.normalizeOptions(mergedOptions, {
|
|
1894
|
+
interval: 0.1,
|
|
1895
|
+
numFrames: 1,
|
|
1896
|
+
gifWidth: Math.floor(mergedOptions.gifWidth),
|
|
1897
|
+
gifHeight: Math.floor(mergedOptions.gifHeight)
|
|
1898
|
+
});
|
|
1899
|
+
createGIF(options, callback);
|
|
1900
|
+
}
|
|
1901
|
+
const API = {
|
|
1902
|
+
utils: utils$2,
|
|
1903
|
+
error: error$2,
|
|
1904
|
+
defaultOptions: defaultOptions$2,
|
|
1905
|
+
createGIF,
|
|
1906
|
+
takeSnapShot,
|
|
1907
|
+
stopVideoStreaming,
|
|
1908
|
+
isSupported,
|
|
1909
|
+
isWebCamGIFSupported,
|
|
1910
|
+
isExistingVideoGIFSupported,
|
|
1911
|
+
isExistingImagesGIFSupported: isSupported$1,
|
|
1912
|
+
VERSION: '0.4.5'
|
|
1913
|
+
};
|
|
1914
|
+
export default API;
|
|
1915
|
+
//# sourceMappingURL=gifshot.js.map
|