@loaders.gl/video 3.1.3 → 4.0.0-alpha.5
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.js +2 -2
- package/dist/bundle.js.map +1 -0
- package/dist/gif-builder.d.ts +1 -1
- package/dist/gif-builder.d.ts.map +1 -1
- package/dist/gif-builder.js +114 -136
- package/dist/gif-builder.js.map +1 -0
- package/dist/index.js +3 -10
- package/dist/index.js.map +1 -0
- package/dist/lib/gifshot/gifshot-loader.js +15 -18
- package/dist/lib/gifshot/gifshot-loader.js.map +1 -0
- package/dist/lib/gifshot/gifshot.js +2089 -2342
- package/dist/lib/gifshot/gifshot.js.map +1 -0
- package/dist/lib/parsers/parse-video.js +6 -12
- package/dist/lib/parsers/parse-video.js.map +1 -0
- package/dist/lib/utils/assert.js +5 -8
- package/dist/lib/utils/assert.js.map +1 -0
- package/dist/lib/utils/globals.js +9 -18
- package/dist/lib/utils/globals.js.map +1 -0
- package/dist/video-loader.js +14 -22
- package/dist/video-loader.js.map +1 -0
- package/package.json +6 -6
- package/src/gif-builder.ts +1 -1
- package/dist/es5/bundle.js +0 -7
- package/dist/es5/bundle.js.map +0 -1
- package/dist/es5/gif-builder.js +0 -245
- package/dist/es5/gif-builder.js.map +0 -1
- package/dist/es5/index.js +0 -24
- package/dist/es5/index.js.map +0 -1
- package/dist/es5/lib/gifshot/gifshot-loader.js +0 -87
- package/dist/es5/lib/gifshot/gifshot-loader.js.map +0 -1
- package/dist/es5/lib/gifshot/gifshot.js +0 -2191
- package/dist/es5/lib/gifshot/gifshot.js.map +0 -1
- package/dist/es5/lib/parsers/parse-video.js +0 -39
- package/dist/es5/lib/parsers/parse-video.js.map +0 -1
- package/dist/es5/lib/utils/assert.js +0 -13
- package/dist/es5/lib/utils/assert.js.map +0 -1
- package/dist/es5/lib/utils/globals.js +0 -33
- package/dist/es5/lib/utils/globals.js.map +0 -1
- package/dist/es5/video-loader.js +0 -31
- package/dist/es5/video-loader.js.map +0 -1
- package/dist/esm/bundle.js +0 -5
- package/dist/esm/bundle.js.map +0 -1
- package/dist/esm/gif-builder.js +0 -120
- package/dist/esm/gif-builder.js.map +0 -1
- package/dist/esm/index.js +0 -3
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/lib/gifshot/gifshot-loader.js +0 -19
- package/dist/esm/lib/gifshot/gifshot-loader.js.map +0 -1
- package/dist/esm/lib/gifshot/gifshot.js +0 -2184
- package/dist/esm/lib/gifshot/gifshot.js.map +0 -1
- package/dist/esm/lib/parsers/parse-video.js +0 -7
- package/dist/esm/lib/parsers/parse-video.js.map +0 -1
- package/dist/esm/lib/utils/assert.js +0 -6
- package/dist/esm/lib/utils/assert.js.map +0 -1
- package/dist/esm/lib/utils/globals.js +0 -16
- package/dist/esm/lib/utils/globals.js.map +0 -1
- package/dist/esm/video-loader.js +0 -19
- package/dist/esm/video-loader.js.map +0 -1
|
@@ -1,2437 +1,2184 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// @ts-nocheck
|
|
3
|
-
/* eslint-disable */
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
/* Copyrights for code authored by Yahoo Inc. is licensed under the following terms:
|
|
6
|
-
MIT License
|
|
7
|
-
Copyright 2017 Yahoo Inc.
|
|
8
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
9
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
11
|
-
*/
|
|
12
|
-
/*
|
|
13
|
-
utils.js
|
|
14
|
-
========
|
|
15
|
-
*/
|
|
16
|
-
/* Copyright 2017 Yahoo Inc.
|
|
17
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
18
|
-
*/
|
|
19
1
|
var utils = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
},
|
|
108
|
-
isSupported: {
|
|
109
|
-
canvas: function canvas() {
|
|
110
|
-
const el = document.createElement('canvas');
|
|
111
|
-
return el && el.getContext && el.getContext('2d');
|
|
112
|
-
},
|
|
113
|
-
webworkers: function webworkers() {
|
|
114
|
-
return window.Worker;
|
|
115
|
-
},
|
|
116
|
-
blob: function blob() {
|
|
117
|
-
return utils.Blob;
|
|
118
|
-
},
|
|
119
|
-
Uint8Array: function Uint8Array() {
|
|
120
|
-
return window.Uint8Array;
|
|
121
|
-
},
|
|
122
|
-
Uint32Array: function Uint32Array() {
|
|
123
|
-
return window.Uint32Array;
|
|
124
|
-
},
|
|
125
|
-
videoCodecs: (function () {
|
|
126
|
-
const testEl = document.createElement('video');
|
|
127
|
-
const supportObj = {
|
|
128
|
-
mp4: false,
|
|
129
|
-
h264: false,
|
|
130
|
-
ogv: false,
|
|
131
|
-
ogg: false,
|
|
132
|
-
webm: false
|
|
133
|
-
};
|
|
134
|
-
try {
|
|
135
|
-
if (testEl && testEl.canPlayType) {
|
|
136
|
-
// Check for MPEG-4 support
|
|
137
|
-
supportObj.mp4 = testEl.canPlayType('video/mp4; codecs="mp4v.20.8"') !== '';
|
|
138
|
-
// Check for h264 support
|
|
139
|
-
supportObj.h264 =
|
|
140
|
-
(testEl.canPlayType('video/mp4; codecs="avc1.42E01E"') ||
|
|
141
|
-
testEl.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) !== '';
|
|
142
|
-
// Check for Ogv support
|
|
143
|
-
supportObj.ogv = testEl.canPlayType('video/ogg; codecs="theora"') !== '';
|
|
144
|
-
// Check for Ogg support
|
|
145
|
-
supportObj.ogg = testEl.canPlayType('video/ogg; codecs="theora"') !== '';
|
|
146
|
-
// Check for Webm support
|
|
147
|
-
supportObj.webm = testEl.canPlayType('video/webm; codecs="vp8, vorbis"') !== -1;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
catch (e) { }
|
|
151
|
-
return supportObj;
|
|
152
|
-
})()
|
|
153
|
-
},
|
|
154
|
-
noop: function noop() { },
|
|
155
|
-
each: function each(collection, callback) {
|
|
156
|
-
let x = void 0;
|
|
157
|
-
let len = void 0;
|
|
158
|
-
if (utils.isArray(collection)) {
|
|
159
|
-
x = -1;
|
|
160
|
-
len = collection.length;
|
|
161
|
-
while (++x < len) {
|
|
162
|
-
if (callback(x, collection[x]) === false) {
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
else if (utils.isObject(collection)) {
|
|
168
|
-
for (x in collection) {
|
|
169
|
-
if (collection.hasOwnProperty(x)) {
|
|
170
|
-
if (callback(x, collection[x]) === false) {
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
normalizeOptions: function normalizeOptions(defaultOptions, userOptions) {
|
|
178
|
-
if (!utils.isObject(defaultOptions) || !utils.isObject(userOptions) || !Object.keys) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
const newObj = {};
|
|
182
|
-
utils.each(defaultOptions, function (key, val) {
|
|
183
|
-
newObj[key] = defaultOptions[key];
|
|
184
|
-
});
|
|
185
|
-
utils.each(userOptions, function (key, val) {
|
|
186
|
-
const currentUserOption = userOptions[key];
|
|
187
|
-
if (!utils.isObject(currentUserOption)) {
|
|
188
|
-
newObj[key] = currentUserOption;
|
|
189
|
-
}
|
|
190
|
-
else if (!defaultOptions[key]) {
|
|
191
|
-
newObj[key] = currentUserOption;
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
newObj[key] = utils.normalizeOptions(defaultOptions[key], currentUserOption);
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
return newObj;
|
|
198
|
-
},
|
|
199
|
-
setCSSAttr: function setCSSAttr(elem, attr, val) {
|
|
200
|
-
if (!utils.isElement(elem)) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
if (utils.isString(attr) && utils.isString(val)) {
|
|
204
|
-
elem.style[attr] = val;
|
|
205
|
-
}
|
|
206
|
-
else if (utils.isObject(attr)) {
|
|
207
|
-
utils.each(attr, function (key, val) {
|
|
208
|
-
elem.style[key] = val;
|
|
209
|
-
});
|
|
210
|
-
}
|
|
2
|
+
URL: window.URL || window.webkitURL || window.mozURL || window.msURL,
|
|
3
|
+
getUserMedia: function () {
|
|
4
|
+
const getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
|
5
|
+
return getUserMedia ? getUserMedia.bind(navigator) : getUserMedia;
|
|
6
|
+
}(),
|
|
7
|
+
requestAnimFrame: window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame,
|
|
8
|
+
requestTimeout: function requestTimeout(callback, delay) {
|
|
9
|
+
callback = callback || utils.noop;
|
|
10
|
+
delay = delay || 0;
|
|
11
|
+
|
|
12
|
+
if (!utils.requestAnimFrame) {
|
|
13
|
+
return setTimeout(callback, delay);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const start = new Date().getTime();
|
|
17
|
+
const handle = new Object();
|
|
18
|
+
const requestAnimFrame = utils.requestAnimFrame;
|
|
19
|
+
|
|
20
|
+
const loop = function loop() {
|
|
21
|
+
const current = new Date().getTime();
|
|
22
|
+
const delta = current - start;
|
|
23
|
+
delta >= delay ? callback.call() : handle.value = requestAnimFrame(loop);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
handle.value = requestAnimFrame(loop);
|
|
27
|
+
return handle;
|
|
28
|
+
},
|
|
29
|
+
Blob: window.Blob || window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder,
|
|
30
|
+
btoa: function () {
|
|
31
|
+
const btoa = window.btoa || function (input) {
|
|
32
|
+
let output = '';
|
|
33
|
+
let i = 0;
|
|
34
|
+
const l = input.length;
|
|
35
|
+
const key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
36
|
+
let chr1 = void 0;
|
|
37
|
+
let chr2 = void 0;
|
|
38
|
+
let chr3 = void 0;
|
|
39
|
+
let enc1 = void 0;
|
|
40
|
+
let enc2 = void 0;
|
|
41
|
+
let enc3 = void 0;
|
|
42
|
+
let enc4 = void 0;
|
|
43
|
+
|
|
44
|
+
while (i < l) {
|
|
45
|
+
chr1 = input.charCodeAt(i++);
|
|
46
|
+
chr2 = input.charCodeAt(i++);
|
|
47
|
+
chr3 = input.charCodeAt(i++);
|
|
48
|
+
enc1 = chr1 >> 2;
|
|
49
|
+
enc2 = (chr1 & 3) << 4 | chr2 >> 4;
|
|
50
|
+
enc3 = (chr2 & 15) << 2 | chr3 >> 6;
|
|
51
|
+
enc4 = chr3 & 63;
|
|
52
|
+
|
|
53
|
+
if (isNaN(chr2)) {
|
|
54
|
+
enc3 = enc4 = 64;
|
|
55
|
+
} else if (isNaN(chr3)) {
|
|
56
|
+
enc4 = 64;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
output = output + key.charAt(enc1) + key.charAt(enc2) + key.charAt(enc3) + key.charAt(enc4);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return output;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return btoa ? btoa.bind(window) : utils.noop;
|
|
66
|
+
}(),
|
|
67
|
+
isObject: function isObject(obj) {
|
|
68
|
+
return obj && Object.prototype.toString.call(obj) === '[object Object]';
|
|
69
|
+
},
|
|
70
|
+
isEmptyObject: function isEmptyObject(obj) {
|
|
71
|
+
return utils.isObject(obj) && !Object.keys(obj).length;
|
|
72
|
+
},
|
|
73
|
+
isArray: function isArray(arr) {
|
|
74
|
+
return arr && Array.isArray(arr);
|
|
75
|
+
},
|
|
76
|
+
isFunction: function isFunction(func) {
|
|
77
|
+
return func && typeof func === 'function';
|
|
78
|
+
},
|
|
79
|
+
isElement: function isElement(elem) {
|
|
80
|
+
return elem && elem.nodeType === 1;
|
|
81
|
+
},
|
|
82
|
+
isString: function isString(value) {
|
|
83
|
+
return typeof value === 'string' || Object.prototype.toString.call(value) === '[object String]';
|
|
84
|
+
},
|
|
85
|
+
isSupported: {
|
|
86
|
+
canvas: function canvas() {
|
|
87
|
+
const el = document.createElement('canvas');
|
|
88
|
+
return el && el.getContext && el.getContext('2d');
|
|
211
89
|
},
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if (node.parentNode) {
|
|
217
|
-
node.parentNode.removeChild(node);
|
|
218
|
-
}
|
|
90
|
+
webworkers: function webworkers() {
|
|
91
|
+
return window.Worker;
|
|
219
92
|
},
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return {};
|
|
223
|
-
}
|
|
224
|
-
try {
|
|
225
|
-
const blob = new utils.Blob([content], {
|
|
226
|
-
type: 'text/javascript'
|
|
227
|
-
});
|
|
228
|
-
const objectUrl = utils.URL.createObjectURL(blob);
|
|
229
|
-
const worker = new Worker(objectUrl);
|
|
230
|
-
return {
|
|
231
|
-
objectUrl,
|
|
232
|
-
worker
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
catch (e) {
|
|
236
|
-
return `${e}`;
|
|
237
|
-
}
|
|
93
|
+
blob: function blob() {
|
|
94
|
+
return utils.Blob;
|
|
238
95
|
},
|
|
239
|
-
|
|
240
|
-
|
|
96
|
+
Uint8Array: function Uint8Array() {
|
|
97
|
+
return window.Uint8Array;
|
|
241
98
|
},
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (!document.body || options.resizeFont === false) {
|
|
245
|
-
return options.fontSize;
|
|
246
|
-
}
|
|
247
|
-
const text = options.text;
|
|
248
|
-
const containerWidth = options.gifWidth;
|
|
249
|
-
let fontSize = parseInt(options.fontSize, 10);
|
|
250
|
-
const minFontSize = parseInt(options.minFontSize, 10);
|
|
251
|
-
const div = document.createElement('div');
|
|
252
|
-
const span = document.createElement('span');
|
|
253
|
-
div.setAttribute('width', containerWidth);
|
|
254
|
-
div.appendChild(span);
|
|
255
|
-
span.innerHTML = text;
|
|
256
|
-
span.style.fontSize = `${fontSize}px`;
|
|
257
|
-
span.style.textIndent = '-9999px';
|
|
258
|
-
span.style.visibility = 'hidden';
|
|
259
|
-
document.body.appendChild(span);
|
|
260
|
-
while (span.offsetWidth > containerWidth && fontSize >= minFontSize) {
|
|
261
|
-
span.style.fontSize = `${--fontSize}px`;
|
|
262
|
-
}
|
|
263
|
-
document.body.removeChild(span);
|
|
264
|
-
return `${fontSize}px`;
|
|
99
|
+
Uint32Array: function Uint32Array() {
|
|
100
|
+
return window.Uint32Array;
|
|
265
101
|
},
|
|
266
|
-
|
|
102
|
+
videoCodecs: function () {
|
|
103
|
+
const testEl = document.createElement('video');
|
|
104
|
+
const supportObj = {
|
|
105
|
+
mp4: false,
|
|
106
|
+
h264: false,
|
|
107
|
+
ogv: false,
|
|
108
|
+
ogg: false,
|
|
109
|
+
webm: false
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
if (testEl && testEl.canPlayType) {
|
|
114
|
+
supportObj.mp4 = testEl.canPlayType('video/mp4; codecs="mp4v.20.8"') !== '';
|
|
115
|
+
supportObj.h264 = (testEl.canPlayType('video/mp4; codecs="avc1.42E01E"') || testEl.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) !== '';
|
|
116
|
+
supportObj.ogv = testEl.canPlayType('video/ogg; codecs="theora"') !== '';
|
|
117
|
+
supportObj.ogg = testEl.canPlayType('video/ogg; codecs="theora"') !== '';
|
|
118
|
+
supportObj.webm = testEl.canPlayType('video/webm; codecs="vp8, vorbis"') !== -1;
|
|
119
|
+
}
|
|
120
|
+
} catch (e) {}
|
|
121
|
+
|
|
122
|
+
return supportObj;
|
|
123
|
+
}()
|
|
124
|
+
},
|
|
125
|
+
noop: function noop() {},
|
|
126
|
+
each: function each(collection, callback) {
|
|
127
|
+
let x = void 0;
|
|
128
|
+
let len = void 0;
|
|
129
|
+
|
|
130
|
+
if (utils.isArray(collection)) {
|
|
131
|
+
x = -1;
|
|
132
|
+
len = collection.length;
|
|
133
|
+
|
|
134
|
+
while (++x < len) {
|
|
135
|
+
if (callback(x, collection[x]) === false) {
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
} else if (utils.isObject(collection)) {
|
|
140
|
+
for (x in collection) {
|
|
141
|
+
if (collection.hasOwnProperty(x)) {
|
|
142
|
+
if (callback(x, collection[x]) === false) {
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
normalizeOptions: function normalizeOptions(defaultOptions, userOptions) {
|
|
150
|
+
if (!utils.isObject(defaultOptions) || !utils.isObject(userOptions) || !Object.keys) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const newObj = {};
|
|
155
|
+
utils.each(defaultOptions, function (key, val) {
|
|
156
|
+
newObj[key] = defaultOptions[key];
|
|
157
|
+
});
|
|
158
|
+
utils.each(userOptions, function (key, val) {
|
|
159
|
+
const currentUserOption = userOptions[key];
|
|
160
|
+
|
|
161
|
+
if (!utils.isObject(currentUserOption)) {
|
|
162
|
+
newObj[key] = currentUserOption;
|
|
163
|
+
} else if (!defaultOptions[key]) {
|
|
164
|
+
newObj[key] = currentUserOption;
|
|
165
|
+
} else {
|
|
166
|
+
newObj[key] = utils.normalizeOptions(defaultOptions[key], currentUserOption);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
return newObj;
|
|
170
|
+
},
|
|
171
|
+
setCSSAttr: function setCSSAttr(elem, attr, val) {
|
|
172
|
+
if (!utils.isElement(elem)) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (utils.isString(attr) && utils.isString(val)) {
|
|
177
|
+
elem.style[attr] = val;
|
|
178
|
+
} else if (utils.isObject(attr)) {
|
|
179
|
+
utils.each(attr, function (key, val) {
|
|
180
|
+
elem.style[key] = val;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
removeElement: function removeElement(node) {
|
|
185
|
+
if (!utils.isElement(node)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (node.parentNode) {
|
|
190
|
+
node.parentNode.removeChild(node);
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
createWebWorker: function createWebWorker(content) {
|
|
194
|
+
if (!utils.isString(content)) {
|
|
195
|
+
return {};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const blob = new utils.Blob([content], {
|
|
200
|
+
type: 'text/javascript'
|
|
201
|
+
});
|
|
202
|
+
const objectUrl = utils.URL.createObjectURL(blob);
|
|
203
|
+
const worker = new Worker(objectUrl);
|
|
204
|
+
return {
|
|
205
|
+
objectUrl,
|
|
206
|
+
worker
|
|
207
|
+
};
|
|
208
|
+
} catch (e) {
|
|
209
|
+
return "".concat(e);
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
getExtension: function getExtension(src) {
|
|
213
|
+
return src.substr(src.lastIndexOf('.') + 1, src.length);
|
|
214
|
+
},
|
|
215
|
+
getFontSize: function getFontSize() {
|
|
216
|
+
const options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
217
|
+
|
|
218
|
+
if (!document.body || options.resizeFont === false) {
|
|
219
|
+
return options.fontSize;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const text = options.text;
|
|
223
|
+
const containerWidth = options.gifWidth;
|
|
224
|
+
let fontSize = parseInt(options.fontSize, 10);
|
|
225
|
+
const minFontSize = parseInt(options.minFontSize, 10);
|
|
226
|
+
const div = document.createElement('div');
|
|
227
|
+
const span = document.createElement('span');
|
|
228
|
+
div.setAttribute('width', containerWidth);
|
|
229
|
+
div.appendChild(span);
|
|
230
|
+
span.innerHTML = text;
|
|
231
|
+
span.style.fontSize = "".concat(fontSize, "px");
|
|
232
|
+
span.style.textIndent = '-9999px';
|
|
233
|
+
span.style.visibility = 'hidden';
|
|
234
|
+
document.body.appendChild(span);
|
|
235
|
+
|
|
236
|
+
while (span.offsetWidth > containerWidth && fontSize >= minFontSize) {
|
|
237
|
+
span.style.fontSize = "".concat(--fontSize, "px");
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
document.body.removeChild(span);
|
|
241
|
+
return "".concat(fontSize, "px");
|
|
242
|
+
},
|
|
243
|
+
webWorkerError: false
|
|
267
244
|
};
|
|
268
245
|
const utils$2 = Object.freeze({
|
|
269
|
-
|
|
246
|
+
default: utils
|
|
270
247
|
});
|
|
271
|
-
/*
|
|
272
|
-
error.js
|
|
273
|
-
========
|
|
274
|
-
*/
|
|
275
|
-
/* Copyright 2017 Yahoo Inc.
|
|
276
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
277
|
-
*/
|
|
278
|
-
// Dependencies
|
|
279
248
|
var error = {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
errorMsg: 'The window.Uint32Array function constructor is not supported in your browser'
|
|
334
|
-
}
|
|
335
|
-
],
|
|
336
|
-
messages: {
|
|
337
|
-
videoCodecs: {
|
|
338
|
-
errorCode: 'videocodec',
|
|
339
|
-
errorMsg: 'The video codec you are trying to use is not supported in your browser'
|
|
340
|
-
}
|
|
249
|
+
validate: function validate(skipObj) {
|
|
250
|
+
skipObj = utils.isObject(skipObj) ? skipObj : {};
|
|
251
|
+
let errorObj = {};
|
|
252
|
+
utils.each(error.validators, function (indece, currentValidator) {
|
|
253
|
+
const errorCode = currentValidator.errorCode;
|
|
254
|
+
|
|
255
|
+
if (!skipObj[errorCode] && !currentValidator.condition) {
|
|
256
|
+
errorObj = currentValidator;
|
|
257
|
+
errorObj.error = true;
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
delete errorObj.condition;
|
|
262
|
+
return errorObj;
|
|
263
|
+
},
|
|
264
|
+
isValid: function isValid(skipObj) {
|
|
265
|
+
const errorObj = error.validate(skipObj);
|
|
266
|
+
const isValid = errorObj.error !== true;
|
|
267
|
+
return isValid;
|
|
268
|
+
},
|
|
269
|
+
validators: [{
|
|
270
|
+
condition: utils.isFunction(utils.getUserMedia),
|
|
271
|
+
errorCode: 'getUserMedia',
|
|
272
|
+
errorMsg: 'The getUserMedia API is not supported in your browser'
|
|
273
|
+
}, {
|
|
274
|
+
condition: utils.isSupported.canvas(),
|
|
275
|
+
errorCode: 'canvas',
|
|
276
|
+
errorMsg: 'Canvas elements are not supported in your browser'
|
|
277
|
+
}, {
|
|
278
|
+
condition: utils.isSupported.webworkers(),
|
|
279
|
+
errorCode: 'webworkers',
|
|
280
|
+
errorMsg: 'The Web Workers API is not supported in your browser'
|
|
281
|
+
}, {
|
|
282
|
+
condition: utils.isFunction(utils.URL),
|
|
283
|
+
errorCode: 'window.URL',
|
|
284
|
+
errorMsg: 'The window.URL API is not supported in your browser'
|
|
285
|
+
}, {
|
|
286
|
+
condition: utils.isSupported.blob(),
|
|
287
|
+
errorCode: 'window.Blob',
|
|
288
|
+
errorMsg: 'The window.Blob File API is not supported in your browser'
|
|
289
|
+
}, {
|
|
290
|
+
condition: utils.isSupported.Uint8Array(),
|
|
291
|
+
errorCode: 'window.Uint8Array',
|
|
292
|
+
errorMsg: 'The window.Uint8Array function constructor is not supported in your browser'
|
|
293
|
+
}, {
|
|
294
|
+
condition: utils.isSupported.Uint32Array(),
|
|
295
|
+
errorCode: 'window.Uint32Array',
|
|
296
|
+
errorMsg: 'The window.Uint32Array function constructor is not supported in your browser'
|
|
297
|
+
}],
|
|
298
|
+
messages: {
|
|
299
|
+
videoCodecs: {
|
|
300
|
+
errorCode: 'videocodec',
|
|
301
|
+
errorMsg: 'The video codec you are trying to use is not supported in your browser'
|
|
341
302
|
}
|
|
303
|
+
}
|
|
342
304
|
};
|
|
343
305
|
const error$2 = Object.freeze({
|
|
344
|
-
|
|
306
|
+
default: error
|
|
345
307
|
});
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
*/
|
|
350
|
-
/* Copyright 2017 Yahoo Inc.
|
|
351
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
352
|
-
*/
|
|
353
|
-
// Helpers
|
|
354
|
-
const noop = function noop() { };
|
|
308
|
+
|
|
309
|
+
const noop = function noop() {};
|
|
310
|
+
|
|
355
311
|
const defaultOptions = {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
312
|
+
sampleInterval: 10,
|
|
313
|
+
numWorkers: 2,
|
|
314
|
+
filter: '',
|
|
315
|
+
gifWidth: 200,
|
|
316
|
+
gifHeight: 200,
|
|
317
|
+
interval: 0.1,
|
|
318
|
+
numFrames: 10,
|
|
319
|
+
frameDuration: 1,
|
|
320
|
+
keepCameraOn: false,
|
|
321
|
+
images: [],
|
|
322
|
+
video: null,
|
|
323
|
+
webcamVideoElement: null,
|
|
324
|
+
cameraStream: null,
|
|
325
|
+
text: '',
|
|
326
|
+
fontWeight: 'normal',
|
|
327
|
+
fontSize: '16px',
|
|
328
|
+
minFontSize: '10px',
|
|
329
|
+
resizeFont: false,
|
|
330
|
+
fontFamily: 'sans-serif',
|
|
331
|
+
fontColor: '#ffffff',
|
|
332
|
+
textAlign: 'center',
|
|
333
|
+
textBaseline: 'bottom',
|
|
334
|
+
textXCoordinate: null,
|
|
335
|
+
textYCoordinate: null,
|
|
336
|
+
progressCallback: noop,
|
|
337
|
+
completeCallback: noop,
|
|
338
|
+
saveRenderingContexts: false,
|
|
339
|
+
savedRenderingContexts: [],
|
|
340
|
+
crossOrigin: 'Anonymous'
|
|
385
341
|
};
|
|
386
342
|
const defaultOptions$2 = Object.freeze({
|
|
387
|
-
|
|
343
|
+
default: defaultOptions
|
|
388
344
|
});
|
|
389
|
-
|
|
390
|
-
isSupported.js
|
|
391
|
-
==============
|
|
392
|
-
*/
|
|
393
|
-
/* Copyright 2017 Yahoo Inc.
|
|
394
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
395
|
-
*/
|
|
396
|
-
// Dependencies
|
|
345
|
+
|
|
397
346
|
function isSupported() {
|
|
398
|
-
|
|
347
|
+
return error.isValid();
|
|
399
348
|
}
|
|
400
|
-
|
|
401
|
-
isWebCamGIFSupported.js
|
|
402
|
-
=======================
|
|
403
|
-
*/
|
|
404
|
-
/* Copyright 2017 Yahoo Inc.
|
|
405
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
406
|
-
*/
|
|
349
|
+
|
|
407
350
|
function isWebCamGIFSupported() {
|
|
408
|
-
|
|
351
|
+
return error.isValid();
|
|
409
352
|
}
|
|
410
|
-
|
|
411
|
-
isSupported.js
|
|
412
|
-
==============
|
|
413
|
-
*/
|
|
414
|
-
/* Copyright 2017 Yahoo Inc.
|
|
415
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
416
|
-
*/
|
|
417
|
-
// Dependencies
|
|
353
|
+
|
|
418
354
|
function isSupported$1() {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
355
|
+
const options = {
|
|
356
|
+
getUserMedia: true
|
|
357
|
+
};
|
|
358
|
+
return error.isValid(options);
|
|
423
359
|
}
|
|
424
|
-
|
|
425
|
-
isExistingVideoGIFSupported.js
|
|
426
|
-
==============================
|
|
427
|
-
*/
|
|
428
|
-
/* Copyright 2017 Yahoo Inc.
|
|
429
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
430
|
-
*/
|
|
431
|
-
// Dependencies
|
|
360
|
+
|
|
432
361
|
function isExistingVideoGIFSupported(codecs) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
362
|
+
let hasValidCodec = false;
|
|
363
|
+
|
|
364
|
+
if (utils.isArray(codecs) && codecs.length) {
|
|
365
|
+
utils.each(codecs, function (indece, currentCodec) {
|
|
366
|
+
if (utils.isSupported.videoCodecs[currentCodec]) {
|
|
367
|
+
hasValidCodec = true;
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
if (!hasValidCodec) {
|
|
372
|
+
return false;
|
|
443
373
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
374
|
+
} else if (utils.isString(codecs) && codecs.length) {
|
|
375
|
+
if (!utils.isSupported.videoCodecs[codecs]) {
|
|
376
|
+
return false;
|
|
448
377
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return error.isValid({
|
|
381
|
+
getUserMedia: true
|
|
382
|
+
});
|
|
452
383
|
}
|
|
453
|
-
|
|
454
|
-
NeuQuant.js
|
|
455
|
-
===========
|
|
456
|
-
*/
|
|
457
|
-
/*
|
|
458
|
-
* NeuQuant Neural-Net Quantization Algorithm
|
|
459
|
-
* ------------------------------------------
|
|
460
|
-
*
|
|
461
|
-
* Copyright (c) 1994 Anthony Dekker
|
|
462
|
-
*
|
|
463
|
-
* NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See
|
|
464
|
-
* "Kohonen neural networks for optimal colour quantization" in "Network:
|
|
465
|
-
* Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of
|
|
466
|
-
* the algorithm.
|
|
467
|
-
*
|
|
468
|
-
* Any party obtaining a copy of these files from the author, directly or
|
|
469
|
-
* indirectly, is granted, free of charge, a full and unrestricted irrevocable,
|
|
470
|
-
* world-wide, paid up, royalty-free, nonexclusive right and license to deal in
|
|
471
|
-
* this software and documentation files (the "Software"), including without
|
|
472
|
-
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
473
|
-
* sublicense, and/or sell copies of the Software, and to permit persons who
|
|
474
|
-
* receive copies from any such party to do so, with the only requirement being
|
|
475
|
-
* that this copyright notice remain intact.
|
|
476
|
-
*/
|
|
477
|
-
/*
|
|
478
|
-
* This class handles Neural-Net quantization algorithm
|
|
479
|
-
* @author Kevin Weiner (original Java version - kweiner@fmsware.com)
|
|
480
|
-
* @author Thibault Imbert (AS3 version - bytearray.org)
|
|
481
|
-
* @version 0.1 AS3 implementation
|
|
482
|
-
* @version 0.2 JS->AS3 "translation" by antimatter15
|
|
483
|
-
* @version 0.3 JS clean up + using modern JS idioms by sole - http://soledadpenades.com
|
|
484
|
-
* Also implement fix in color conversion described at http://stackoverflow.com/questions/16371712/neuquant-js-javascript-color-quantization-hidden-bug-in-js-conversion
|
|
485
|
-
*/
|
|
384
|
+
|
|
486
385
|
function NeuQuant() {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const freq = [];
|
|
539
|
-
const radpower = [];
|
|
540
|
-
function NeuQuantConstructor(thepic, len, sample) {
|
|
541
|
-
let i;
|
|
542
|
-
let p;
|
|
543
|
-
thepicture = thepic;
|
|
544
|
-
lengthcount = len;
|
|
545
|
-
samplefac = sample;
|
|
546
|
-
network = new Array(netsize);
|
|
547
|
-
for (i = 0; i < netsize; i++) {
|
|
548
|
-
network[i] = new Array(4);
|
|
549
|
-
p = network[i];
|
|
550
|
-
p[0] = p[1] = p[2] = ((i << (netbiasshift + 8)) / netsize) | 0;
|
|
551
|
-
freq[i] = (intbias / netsize) | 0; // 1 / netsize
|
|
552
|
-
bias[i] = 0;
|
|
553
|
-
}
|
|
386
|
+
const netsize = 256;
|
|
387
|
+
const prime1 = 499;
|
|
388
|
+
const prime2 = 491;
|
|
389
|
+
const prime3 = 487;
|
|
390
|
+
const prime4 = 503;
|
|
391
|
+
const minpicturebytes = 3 * prime4;
|
|
392
|
+
const maxnetpos = netsize - 1;
|
|
393
|
+
const netbiasshift = 4;
|
|
394
|
+
const ncycles = 100;
|
|
395
|
+
const intbiasshift = 16;
|
|
396
|
+
const intbias = 1 << intbiasshift;
|
|
397
|
+
const gammashift = 10;
|
|
398
|
+
const gamma = 1 << gammashift;
|
|
399
|
+
const betashift = 10;
|
|
400
|
+
const beta = intbias >> betashift;
|
|
401
|
+
const betagamma = intbias << gammashift - betashift;
|
|
402
|
+
const initrad = netsize >> 3;
|
|
403
|
+
const radiusbiasshift = 6;
|
|
404
|
+
const radiusbias = 1 << radiusbiasshift;
|
|
405
|
+
const initradius = initrad * radiusbias;
|
|
406
|
+
const radiusdec = 30;
|
|
407
|
+
const alphabiasshift = 10;
|
|
408
|
+
const initalpha = 1 << alphabiasshift;
|
|
409
|
+
let alphadec;
|
|
410
|
+
const radbiasshift = 8;
|
|
411
|
+
const radbias = 1 << radbiasshift;
|
|
412
|
+
const alpharadbshift = alphabiasshift + radbiasshift;
|
|
413
|
+
const alpharadbias = 1 << alpharadbshift;
|
|
414
|
+
let thepicture;
|
|
415
|
+
let lengthcount;
|
|
416
|
+
let samplefac;
|
|
417
|
+
let network;
|
|
418
|
+
const netindex = [];
|
|
419
|
+
const bias = [];
|
|
420
|
+
const freq = [];
|
|
421
|
+
const radpower = [];
|
|
422
|
+
|
|
423
|
+
function NeuQuantConstructor(thepic, len, sample) {
|
|
424
|
+
let i;
|
|
425
|
+
let p;
|
|
426
|
+
thepicture = thepic;
|
|
427
|
+
lengthcount = len;
|
|
428
|
+
samplefac = sample;
|
|
429
|
+
network = new Array(netsize);
|
|
430
|
+
|
|
431
|
+
for (i = 0; i < netsize; i++) {
|
|
432
|
+
network[i] = new Array(4);
|
|
433
|
+
p = network[i];
|
|
434
|
+
p[0] = p[1] = p[2] = (i << netbiasshift + 8) / netsize | 0;
|
|
435
|
+
freq[i] = intbias / netsize | 0;
|
|
436
|
+
bias[i] = 0;
|
|
554
437
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const j = index[l];
|
|
564
|
-
map[k++] = network[j][0];
|
|
565
|
-
map[k++] = network[j][1];
|
|
566
|
-
map[k++] = network[j][2];
|
|
567
|
-
}
|
|
568
|
-
return map;
|
|
569
|
-
}
|
|
570
|
-
// Insertion sort of network and building of netindex[0..255]
|
|
571
|
-
// (to do after unbias)
|
|
572
|
-
function inxbuild() {
|
|
573
|
-
let i;
|
|
574
|
-
let j;
|
|
575
|
-
let smallpos;
|
|
576
|
-
let smallval;
|
|
577
|
-
let p;
|
|
578
|
-
let q;
|
|
579
|
-
let previouscol;
|
|
580
|
-
let startpos;
|
|
581
|
-
previouscol = 0;
|
|
582
|
-
startpos = 0;
|
|
583
|
-
for (i = 0; i < netsize; i++) {
|
|
584
|
-
p = network[i];
|
|
585
|
-
smallpos = i;
|
|
586
|
-
smallval = p[1]; // index on g
|
|
587
|
-
// find smallest in i..netsize-1
|
|
588
|
-
for (j = i + 1; j < netsize; j++) {
|
|
589
|
-
q = network[j];
|
|
590
|
-
if (q[1] < smallval) {
|
|
591
|
-
// index on g
|
|
592
|
-
smallpos = j;
|
|
593
|
-
smallval = q[1]; // index on g
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
q = network[smallpos];
|
|
597
|
-
// swap p (i) and q (smallpos) entries
|
|
598
|
-
if (i != smallpos) {
|
|
599
|
-
j = q[0];
|
|
600
|
-
q[0] = p[0];
|
|
601
|
-
p[0] = j;
|
|
602
|
-
j = q[1];
|
|
603
|
-
q[1] = p[1];
|
|
604
|
-
p[1] = j;
|
|
605
|
-
j = q[2];
|
|
606
|
-
q[2] = p[2];
|
|
607
|
-
p[2] = j;
|
|
608
|
-
j = q[3];
|
|
609
|
-
q[3] = p[3];
|
|
610
|
-
p[3] = j;
|
|
611
|
-
}
|
|
612
|
-
// smallval entry is now in position i
|
|
613
|
-
if (smallval != previouscol) {
|
|
614
|
-
netindex[previouscol] = (startpos + i) >> 1;
|
|
615
|
-
for (j = previouscol + 1; j < smallval; j++) {
|
|
616
|
-
netindex[j] = i;
|
|
617
|
-
}
|
|
618
|
-
previouscol = smallval;
|
|
619
|
-
startpos = i;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
netindex[previouscol] = (startpos + maxnetpos) >> 1;
|
|
623
|
-
for (j = previouscol + 1; j < 256; j++) {
|
|
624
|
-
netindex[j] = maxnetpos; // really 256
|
|
625
|
-
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function colorMap() {
|
|
441
|
+
const map = [];
|
|
442
|
+
const index = new Array(netsize);
|
|
443
|
+
|
|
444
|
+
for (let i = 0; i < netsize; i++) {
|
|
445
|
+
index[network[i][3]] = i;
|
|
626
446
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
let rad;
|
|
636
|
-
let alpha;
|
|
637
|
-
let step;
|
|
638
|
-
let delta;
|
|
639
|
-
let samplepixels;
|
|
640
|
-
let p;
|
|
641
|
-
let pix;
|
|
642
|
-
let lim;
|
|
643
|
-
if (lengthcount < minpicturebytes) {
|
|
644
|
-
samplefac = 1;
|
|
645
|
-
}
|
|
646
|
-
alphadec = 30 + (samplefac - 1) / 3;
|
|
647
|
-
p = thepicture;
|
|
648
|
-
pix = 0;
|
|
649
|
-
lim = lengthcount;
|
|
650
|
-
samplepixels = lengthcount / (3 * samplefac);
|
|
651
|
-
delta = (samplepixels / ncycles) | 0;
|
|
652
|
-
alpha = initalpha;
|
|
653
|
-
radius = initradius;
|
|
654
|
-
rad = radius >> radiusbiasshift;
|
|
655
|
-
if (rad <= 1) {
|
|
656
|
-
rad = 0;
|
|
657
|
-
}
|
|
658
|
-
for (i = 0; i < rad; i++) {
|
|
659
|
-
radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad));
|
|
660
|
-
}
|
|
661
|
-
if (lengthcount < minpicturebytes) {
|
|
662
|
-
step = 3;
|
|
663
|
-
}
|
|
664
|
-
else if (lengthcount % prime1 !== 0) {
|
|
665
|
-
step = 3 * prime1;
|
|
666
|
-
}
|
|
667
|
-
else if (lengthcount % prime2 !== 0) {
|
|
668
|
-
step = 3 * prime2;
|
|
669
|
-
}
|
|
670
|
-
else if (lengthcount % prime3 !== 0) {
|
|
671
|
-
step = 3 * prime3;
|
|
672
|
-
}
|
|
673
|
-
else {
|
|
674
|
-
step = 3 * prime4;
|
|
675
|
-
}
|
|
676
|
-
i = 0;
|
|
677
|
-
while (i < samplepixels) {
|
|
678
|
-
b = (p[pix + 0] & 0xff) << netbiasshift;
|
|
679
|
-
g = (p[pix + 1] & 0xff) << netbiasshift;
|
|
680
|
-
r = (p[pix + 2] & 0xff) << netbiasshift;
|
|
681
|
-
j = contest(b, g, r);
|
|
682
|
-
altersingle(alpha, j, b, g, r);
|
|
683
|
-
if (rad !== 0) {
|
|
684
|
-
// Alter neighbours
|
|
685
|
-
alterneigh(rad, j, b, g, r);
|
|
686
|
-
}
|
|
687
|
-
pix += step;
|
|
688
|
-
if (pix >= lim) {
|
|
689
|
-
pix -= lengthcount;
|
|
690
|
-
}
|
|
691
|
-
i++;
|
|
692
|
-
if (delta === 0) {
|
|
693
|
-
delta = 1;
|
|
694
|
-
}
|
|
695
|
-
if (i % delta === 0) {
|
|
696
|
-
alpha -= alpha / alphadec;
|
|
697
|
-
radius -= radius / radiusdec;
|
|
698
|
-
rad = radius >> radiusbiasshift;
|
|
699
|
-
if (rad <= 1) {
|
|
700
|
-
rad = 0;
|
|
701
|
-
}
|
|
702
|
-
for (j = 0; j < rad; j++) {
|
|
703
|
-
radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad));
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
}
|
|
447
|
+
|
|
448
|
+
let k = 0;
|
|
449
|
+
|
|
450
|
+
for (let l = 0; l < netsize; l++) {
|
|
451
|
+
const j = index[l];
|
|
452
|
+
map[k++] = network[j][0];
|
|
453
|
+
map[k++] = network[j][1];
|
|
454
|
+
map[k++] = network[j][2];
|
|
707
455
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
a = -a;
|
|
766
|
-
}
|
|
767
|
-
dist += a;
|
|
768
|
-
if (dist < bestd) {
|
|
769
|
-
a = p[2] - r;
|
|
770
|
-
if (a < 0) {
|
|
771
|
-
a = -a;
|
|
772
|
-
}
|
|
773
|
-
dist += a;
|
|
774
|
-
if (dist < bestd) {
|
|
775
|
-
bestd = dist;
|
|
776
|
-
best = p[3];
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
return best;
|
|
783
|
-
}
|
|
784
|
-
function process() {
|
|
785
|
-
learn();
|
|
786
|
-
unbiasnet();
|
|
787
|
-
inxbuild();
|
|
788
|
-
return colorMap();
|
|
789
|
-
}
|
|
790
|
-
// Unbias network to give byte values 0..255 and record position i
|
|
791
|
-
// to prepare for sort
|
|
792
|
-
function unbiasnet() {
|
|
793
|
-
let i;
|
|
794
|
-
let j;
|
|
795
|
-
for (i = 0; i < netsize; i++) {
|
|
796
|
-
network[i][0] >>= netbiasshift;
|
|
797
|
-
network[i][1] >>= netbiasshift;
|
|
798
|
-
network[i][2] >>= netbiasshift;
|
|
799
|
-
network[i][3] = i; // record colour no
|
|
800
|
-
}
|
|
456
|
+
|
|
457
|
+
return map;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function inxbuild() {
|
|
461
|
+
let i;
|
|
462
|
+
let j;
|
|
463
|
+
let smallpos;
|
|
464
|
+
let smallval;
|
|
465
|
+
let p;
|
|
466
|
+
let q;
|
|
467
|
+
let previouscol;
|
|
468
|
+
let startpos;
|
|
469
|
+
previouscol = 0;
|
|
470
|
+
startpos = 0;
|
|
471
|
+
|
|
472
|
+
for (i = 0; i < netsize; i++) {
|
|
473
|
+
p = network[i];
|
|
474
|
+
smallpos = i;
|
|
475
|
+
smallval = p[1];
|
|
476
|
+
|
|
477
|
+
for (j = i + 1; j < netsize; j++) {
|
|
478
|
+
q = network[j];
|
|
479
|
+
|
|
480
|
+
if (q[1] < smallval) {
|
|
481
|
+
smallpos = j;
|
|
482
|
+
smallval = q[1];
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
q = network[smallpos];
|
|
487
|
+
|
|
488
|
+
if (i != smallpos) {
|
|
489
|
+
j = q[0];
|
|
490
|
+
q[0] = p[0];
|
|
491
|
+
p[0] = j;
|
|
492
|
+
j = q[1];
|
|
493
|
+
q[1] = p[1];
|
|
494
|
+
p[1] = j;
|
|
495
|
+
j = q[2];
|
|
496
|
+
q[2] = p[2];
|
|
497
|
+
p[2] = j;
|
|
498
|
+
j = q[3];
|
|
499
|
+
q[3] = p[3];
|
|
500
|
+
p[3] = j;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (smallval != previouscol) {
|
|
504
|
+
netindex[previouscol] = startpos + i >> 1;
|
|
505
|
+
|
|
506
|
+
for (j = previouscol + 1; j < smallval; j++) {
|
|
507
|
+
netindex[j] = i;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
previouscol = smallval;
|
|
511
|
+
startpos = i;
|
|
512
|
+
}
|
|
801
513
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
514
|
+
|
|
515
|
+
netindex[previouscol] = startpos + maxnetpos >> 1;
|
|
516
|
+
|
|
517
|
+
for (j = previouscol + 1; j < 256; j++) {
|
|
518
|
+
netindex[j] = maxnetpos;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function learn() {
|
|
523
|
+
let i;
|
|
524
|
+
let j;
|
|
525
|
+
let b;
|
|
526
|
+
let g;
|
|
527
|
+
let r;
|
|
528
|
+
let radius;
|
|
529
|
+
let rad;
|
|
530
|
+
let alpha;
|
|
531
|
+
let step;
|
|
532
|
+
let delta;
|
|
533
|
+
let samplepixels;
|
|
534
|
+
let p;
|
|
535
|
+
let pix;
|
|
536
|
+
let lim;
|
|
537
|
+
|
|
538
|
+
if (lengthcount < minpicturebytes) {
|
|
539
|
+
samplefac = 1;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
alphadec = 30 + (samplefac - 1) / 3;
|
|
543
|
+
p = thepicture;
|
|
544
|
+
pix = 0;
|
|
545
|
+
lim = lengthcount;
|
|
546
|
+
samplepixels = lengthcount / (3 * samplefac);
|
|
547
|
+
delta = samplepixels / ncycles | 0;
|
|
548
|
+
alpha = initalpha;
|
|
549
|
+
radius = initradius;
|
|
550
|
+
rad = radius >> radiusbiasshift;
|
|
551
|
+
|
|
552
|
+
if (rad <= 1) {
|
|
553
|
+
rad = 0;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
for (i = 0; i < rad; i++) {
|
|
557
|
+
radpower[i] = alpha * ((rad * rad - i * i) * radbias / (rad * rad));
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
if (lengthcount < minpicturebytes) {
|
|
561
|
+
step = 3;
|
|
562
|
+
} else if (lengthcount % prime1 !== 0) {
|
|
563
|
+
step = 3 * prime1;
|
|
564
|
+
} else if (lengthcount % prime2 !== 0) {
|
|
565
|
+
step = 3 * prime2;
|
|
566
|
+
} else if (lengthcount % prime3 !== 0) {
|
|
567
|
+
step = 3 * prime3;
|
|
568
|
+
} else {
|
|
569
|
+
step = 3 * prime4;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
i = 0;
|
|
573
|
+
|
|
574
|
+
while (i < samplepixels) {
|
|
575
|
+
b = (p[pix + 0] & 0xff) << netbiasshift;
|
|
576
|
+
g = (p[pix + 1] & 0xff) << netbiasshift;
|
|
577
|
+
r = (p[pix + 2] & 0xff) << netbiasshift;
|
|
578
|
+
j = contest(b, g, r);
|
|
579
|
+
altersingle(alpha, j, b, g, r);
|
|
580
|
+
|
|
581
|
+
if (rad !== 0) {
|
|
582
|
+
alterneigh(rad, j, b, g, r);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
pix += step;
|
|
586
|
+
|
|
587
|
+
if (pix >= lim) {
|
|
588
|
+
pix -= lengthcount;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
i++;
|
|
592
|
+
|
|
593
|
+
if (delta === 0) {
|
|
594
|
+
delta = 1;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (i % delta === 0) {
|
|
598
|
+
alpha -= alpha / alphadec;
|
|
599
|
+
radius -= radius / radiusdec;
|
|
600
|
+
rad = radius >> radiusbiasshift;
|
|
601
|
+
|
|
602
|
+
if (rad <= 1) {
|
|
603
|
+
rad = 0;
|
|
819
604
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
while (j < hi || k > lo) {
|
|
824
|
-
a = radpower[m++];
|
|
825
|
-
if (j < hi) {
|
|
826
|
-
p = network[j++];
|
|
827
|
-
try {
|
|
828
|
-
p[0] -= ((a * (p[0] - b)) / alpharadbias) | 0;
|
|
829
|
-
p[1] -= ((a * (p[1] - g)) / alpharadbias) | 0;
|
|
830
|
-
p[2] -= ((a * (p[2] - r)) / alpharadbias) | 0;
|
|
831
|
-
}
|
|
832
|
-
catch (e) { }
|
|
833
|
-
}
|
|
834
|
-
if (k > lo) {
|
|
835
|
-
p = network[k--];
|
|
836
|
-
try {
|
|
837
|
-
p[0] -= ((a * (p[0] - b)) / alpharadbias) | 0;
|
|
838
|
-
p[1] -= ((a * (p[1] - g)) / alpharadbias) | 0;
|
|
839
|
-
p[2] -= ((a * (p[2] - r)) / alpharadbias) | 0;
|
|
840
|
-
}
|
|
841
|
-
catch (e) { }
|
|
842
|
-
}
|
|
605
|
+
|
|
606
|
+
for (j = 0; j < rad; j++) {
|
|
607
|
+
radpower[j] = alpha * ((rad * rad - j * j) * radbias / (rad * rad));
|
|
843
608
|
}
|
|
609
|
+
}
|
|
844
610
|
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
function map(b, g, r) {
|
|
614
|
+
let i;
|
|
615
|
+
let j;
|
|
616
|
+
let dist;
|
|
617
|
+
let a;
|
|
618
|
+
let bestd;
|
|
619
|
+
let p;
|
|
620
|
+
let best;
|
|
621
|
+
bestd = 1000;
|
|
622
|
+
best = -1;
|
|
623
|
+
i = netindex[g];
|
|
624
|
+
j = i - 1;
|
|
625
|
+
|
|
626
|
+
while (i < netsize || j >= 0) {
|
|
627
|
+
if (i < netsize) {
|
|
628
|
+
p = network[i];
|
|
629
|
+
dist = p[1] - g;
|
|
630
|
+
|
|
631
|
+
if (dist >= bestd) {
|
|
632
|
+
i = netsize;
|
|
633
|
+
} else {
|
|
634
|
+
i++;
|
|
635
|
+
|
|
636
|
+
if (dist < 0) {
|
|
637
|
+
dist = -dist;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
a = p[0] - b;
|
|
641
|
+
|
|
642
|
+
if (a < 0) {
|
|
643
|
+
a = -a;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
dist += a;
|
|
647
|
+
|
|
648
|
+
if (dist < bestd) {
|
|
649
|
+
a = p[2] - r;
|
|
650
|
+
|
|
881
651
|
if (a < 0) {
|
|
882
|
-
|
|
652
|
+
a = -a;
|
|
883
653
|
}
|
|
654
|
+
|
|
884
655
|
dist += a;
|
|
885
|
-
|
|
656
|
+
|
|
657
|
+
if (dist < bestd) {
|
|
658
|
+
bestd = dist;
|
|
659
|
+
best = p[3];
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
if (j >= 0) {
|
|
666
|
+
p = network[j];
|
|
667
|
+
dist = g - p[1];
|
|
668
|
+
|
|
669
|
+
if (dist >= bestd) {
|
|
670
|
+
j = -1;
|
|
671
|
+
} else {
|
|
672
|
+
j--;
|
|
673
|
+
|
|
674
|
+
if (dist < 0) {
|
|
675
|
+
dist = -dist;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
a = p[0] - b;
|
|
679
|
+
|
|
680
|
+
if (a < 0) {
|
|
681
|
+
a = -a;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
dist += a;
|
|
685
|
+
|
|
686
|
+
if (dist < bestd) {
|
|
687
|
+
a = p[2] - r;
|
|
688
|
+
|
|
886
689
|
if (a < 0) {
|
|
887
|
-
|
|
690
|
+
a = -a;
|
|
888
691
|
}
|
|
692
|
+
|
|
889
693
|
dist += a;
|
|
694
|
+
|
|
890
695
|
if (dist < bestd) {
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
}
|
|
894
|
-
biasdist = dist - (bias[i] >> (intbiasshift - netbiasshift));
|
|
895
|
-
if (biasdist < bestbiasd) {
|
|
896
|
-
bestbiasd = biasdist;
|
|
897
|
-
bestbiaspos = i;
|
|
696
|
+
bestd = dist;
|
|
697
|
+
best = p[3];
|
|
898
698
|
}
|
|
899
|
-
|
|
900
|
-
freq[i] -= betafreq;
|
|
901
|
-
bias[i] += betafreq << gammashift;
|
|
699
|
+
}
|
|
902
700
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return best;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
function process() {
|
|
708
|
+
learn();
|
|
709
|
+
unbiasnet();
|
|
710
|
+
inxbuild();
|
|
711
|
+
return colorMap();
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function unbiasnet() {
|
|
715
|
+
let i;
|
|
716
|
+
let j;
|
|
717
|
+
|
|
718
|
+
for (i = 0; i < netsize; i++) {
|
|
719
|
+
network[i][0] >>= netbiasshift;
|
|
720
|
+
network[i][1] >>= netbiasshift;
|
|
721
|
+
network[i][2] >>= netbiasshift;
|
|
722
|
+
network[i][3] = i;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function alterneigh(rad, i, b, g, r) {
|
|
727
|
+
let j;
|
|
728
|
+
let k;
|
|
729
|
+
let lo;
|
|
730
|
+
let hi;
|
|
731
|
+
let a;
|
|
732
|
+
let m;
|
|
733
|
+
let p;
|
|
734
|
+
lo = i - rad;
|
|
735
|
+
|
|
736
|
+
if (lo < -1) {
|
|
737
|
+
lo = -1;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
hi = i + rad;
|
|
741
|
+
|
|
742
|
+
if (hi > netsize) {
|
|
743
|
+
hi = netsize;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
j = i + 1;
|
|
747
|
+
k = i - 1;
|
|
748
|
+
m = 1;
|
|
749
|
+
|
|
750
|
+
while (j < hi || k > lo) {
|
|
751
|
+
a = radpower[m++];
|
|
752
|
+
|
|
753
|
+
if (j < hi) {
|
|
754
|
+
p = network[j++];
|
|
755
|
+
|
|
756
|
+
try {
|
|
757
|
+
p[0] -= a * (p[0] - b) / alpharadbias | 0;
|
|
758
|
+
p[1] -= a * (p[1] - g) / alpharadbias | 0;
|
|
759
|
+
p[2] -= a * (p[2] - r) / alpharadbias | 0;
|
|
760
|
+
} catch (e) {}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
if (k > lo) {
|
|
764
|
+
p = network[k--];
|
|
765
|
+
|
|
766
|
+
try {
|
|
767
|
+
p[0] -= a * (p[0] - b) / alpharadbias | 0;
|
|
768
|
+
p[1] -= a * (p[1] - g) / alpharadbias | 0;
|
|
769
|
+
p[2] -= a * (p[2] - r) / alpharadbias | 0;
|
|
770
|
+
} catch (e) {}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
function altersingle(alpha, i, b, g, r) {
|
|
776
|
+
const n = network[i];
|
|
777
|
+
const alphaMult = alpha / initalpha;
|
|
778
|
+
n[0] -= alphaMult * (n[0] - b) | 0;
|
|
779
|
+
n[1] -= alphaMult * (n[1] - g) | 0;
|
|
780
|
+
n[2] -= alphaMult * (n[2] - r) | 0;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function contest(b, g, r) {
|
|
784
|
+
let i;
|
|
785
|
+
let dist;
|
|
786
|
+
let a;
|
|
787
|
+
let biasdist;
|
|
788
|
+
let betafreq;
|
|
789
|
+
let bestpos;
|
|
790
|
+
let bestbiaspos;
|
|
791
|
+
let bestd;
|
|
792
|
+
let bestbiasd;
|
|
793
|
+
let n;
|
|
794
|
+
bestd = ~(1 << 31);
|
|
795
|
+
bestbiasd = bestd;
|
|
796
|
+
bestpos = -1;
|
|
797
|
+
bestbiaspos = bestpos;
|
|
798
|
+
|
|
799
|
+
for (i = 0; i < netsize; i++) {
|
|
800
|
+
n = network[i];
|
|
801
|
+
dist = n[0] - b;
|
|
802
|
+
|
|
803
|
+
if (dist < 0) {
|
|
804
|
+
dist = -dist;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
a = n[1] - g;
|
|
808
|
+
|
|
809
|
+
if (a < 0) {
|
|
810
|
+
a = -a;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
dist += a;
|
|
814
|
+
a = n[2] - r;
|
|
815
|
+
|
|
816
|
+
if (a < 0) {
|
|
817
|
+
a = -a;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
dist += a;
|
|
821
|
+
|
|
822
|
+
if (dist < bestd) {
|
|
823
|
+
bestd = dist;
|
|
824
|
+
bestpos = i;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
biasdist = dist - (bias[i] >> intbiasshift - netbiasshift);
|
|
828
|
+
|
|
829
|
+
if (biasdist < bestbiasd) {
|
|
830
|
+
bestbiasd = biasdist;
|
|
831
|
+
bestbiaspos = i;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
betafreq = freq[i] >> betashift;
|
|
835
|
+
freq[i] -= betafreq;
|
|
836
|
+
bias[i] += betafreq << gammashift;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
freq[bestpos] += beta;
|
|
840
|
+
bias[bestpos] -= betagamma;
|
|
841
|
+
return bestbiaspos;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
NeuQuantConstructor.apply(this, arguments);
|
|
845
|
+
const exports = {};
|
|
846
|
+
exports.map = map;
|
|
847
|
+
exports.process = process;
|
|
848
|
+
return exports;
|
|
912
849
|
}
|
|
913
|
-
|
|
914
|
-
processFrameWorker.js
|
|
915
|
-
=====================
|
|
916
|
-
*/
|
|
917
|
-
/* Copyright 2017 Yahoo Inc.
|
|
918
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
919
|
-
*/
|
|
850
|
+
|
|
920
851
|
function workerCode() {
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
catch (e) { }
|
|
933
|
-
var workerMethods = {
|
|
934
|
-
dataToRGB: function dataToRGB(data, width, height) {
|
|
935
|
-
const length = width * height * 4;
|
|
936
|
-
let i = 0;
|
|
937
|
-
const rgb = [];
|
|
938
|
-
while (i < length) {
|
|
939
|
-
rgb.push(data[i++]);
|
|
940
|
-
rgb.push(data[i++]);
|
|
941
|
-
rgb.push(data[i++]);
|
|
942
|
-
i++; // for the alpha channel which we don't care about
|
|
943
|
-
}
|
|
944
|
-
return rgb;
|
|
945
|
-
},
|
|
946
|
-
componentizedPaletteToArray: function componentizedPaletteToArray(paletteRGB) {
|
|
947
|
-
paletteRGB = paletteRGB || [];
|
|
948
|
-
const paletteArray = [];
|
|
949
|
-
for (let i = 0; i < paletteRGB.length; i += 3) {
|
|
950
|
-
const r = paletteRGB[i];
|
|
951
|
-
const g = paletteRGB[i + 1];
|
|
952
|
-
const b = paletteRGB[i + 2];
|
|
953
|
-
paletteArray.push((r << 16) | (g << 8) | b);
|
|
954
|
-
}
|
|
955
|
-
return paletteArray;
|
|
956
|
-
},
|
|
957
|
-
// This is the "traditional" Animated_GIF style of going from RGBA to indexed color frames
|
|
958
|
-
processFrameWithQuantizer: function processFrameWithQuantizer(imageData, width, height, sampleInterval) {
|
|
959
|
-
const rgbComponents = this.dataToRGB(imageData, width, height);
|
|
960
|
-
const nq = new NeuQuant(rgbComponents, rgbComponents.length, sampleInterval);
|
|
961
|
-
const paletteRGB = nq.process();
|
|
962
|
-
const paletteArray = new Uint32Array(this.componentizedPaletteToArray(paletteRGB));
|
|
963
|
-
const numberPixels = width * height;
|
|
964
|
-
const indexedPixels = new Uint8Array(numberPixels);
|
|
965
|
-
let k = 0;
|
|
966
|
-
for (let i = 0; i < numberPixels; i++) {
|
|
967
|
-
const r = rgbComponents[k++];
|
|
968
|
-
const g = rgbComponents[k++];
|
|
969
|
-
const b = rgbComponents[k++];
|
|
970
|
-
indexedPixels[i] = nq.map(r, g, b);
|
|
971
|
-
}
|
|
972
|
-
return {
|
|
973
|
-
pixels: indexedPixels,
|
|
974
|
-
palette: paletteArray
|
|
975
|
-
};
|
|
976
|
-
},
|
|
977
|
-
run: function run(frame) {
|
|
978
|
-
frame = frame || {};
|
|
979
|
-
const _frame = frame;
|
|
980
|
-
const height = _frame.height;
|
|
981
|
-
const palette = _frame.palette;
|
|
982
|
-
const sampleInterval = _frame.sampleInterval;
|
|
983
|
-
const width = _frame.width;
|
|
984
|
-
const imageData = frame.data;
|
|
985
|
-
return this.processFrameWithQuantizer(imageData, width, height, sampleInterval);
|
|
986
|
-
}
|
|
852
|
+
const self = this;
|
|
853
|
+
|
|
854
|
+
try {
|
|
855
|
+
self.onmessage = function (ev) {
|
|
856
|
+
const data = ev.data || {};
|
|
857
|
+
let response;
|
|
858
|
+
|
|
859
|
+
if (data.gifshot) {
|
|
860
|
+
response = workerMethods.run(data);
|
|
861
|
+
postMessage(response);
|
|
862
|
+
}
|
|
987
863
|
};
|
|
988
|
-
|
|
864
|
+
} catch (e) {}
|
|
865
|
+
|
|
866
|
+
var workerMethods = {
|
|
867
|
+
dataToRGB: function dataToRGB(data, width, height) {
|
|
868
|
+
const length = width * height * 4;
|
|
869
|
+
let i = 0;
|
|
870
|
+
const rgb = [];
|
|
871
|
+
|
|
872
|
+
while (i < length) {
|
|
873
|
+
rgb.push(data[i++]);
|
|
874
|
+
rgb.push(data[i++]);
|
|
875
|
+
rgb.push(data[i++]);
|
|
876
|
+
i++;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
return rgb;
|
|
880
|
+
},
|
|
881
|
+
componentizedPaletteToArray: function componentizedPaletteToArray(paletteRGB) {
|
|
882
|
+
paletteRGB = paletteRGB || [];
|
|
883
|
+
const paletteArray = [];
|
|
884
|
+
|
|
885
|
+
for (let i = 0; i < paletteRGB.length; i += 3) {
|
|
886
|
+
const r = paletteRGB[i];
|
|
887
|
+
const g = paletteRGB[i + 1];
|
|
888
|
+
const b = paletteRGB[i + 2];
|
|
889
|
+
paletteArray.push(r << 16 | g << 8 | b);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return paletteArray;
|
|
893
|
+
},
|
|
894
|
+
processFrameWithQuantizer: function processFrameWithQuantizer(imageData, width, height, sampleInterval) {
|
|
895
|
+
const rgbComponents = this.dataToRGB(imageData, width, height);
|
|
896
|
+
const nq = new NeuQuant(rgbComponents, rgbComponents.length, sampleInterval);
|
|
897
|
+
const paletteRGB = nq.process();
|
|
898
|
+
const paletteArray = new Uint32Array(this.componentizedPaletteToArray(paletteRGB));
|
|
899
|
+
const numberPixels = width * height;
|
|
900
|
+
const indexedPixels = new Uint8Array(numberPixels);
|
|
901
|
+
let k = 0;
|
|
902
|
+
|
|
903
|
+
for (let i = 0; i < numberPixels; i++) {
|
|
904
|
+
const r = rgbComponents[k++];
|
|
905
|
+
const g = rgbComponents[k++];
|
|
906
|
+
const b = rgbComponents[k++];
|
|
907
|
+
indexedPixels[i] = nq.map(r, g, b);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
return {
|
|
911
|
+
pixels: indexedPixels,
|
|
912
|
+
palette: paletteArray
|
|
913
|
+
};
|
|
914
|
+
},
|
|
915
|
+
run: function run(frame) {
|
|
916
|
+
frame = frame || {};
|
|
917
|
+
const _frame = frame;
|
|
918
|
+
const height = _frame.height;
|
|
919
|
+
const palette = _frame.palette;
|
|
920
|
+
const sampleInterval = _frame.sampleInterval;
|
|
921
|
+
const width = _frame.width;
|
|
922
|
+
const imageData = frame.data;
|
|
923
|
+
return this.processFrameWithQuantizer(imageData, width, height, sampleInterval);
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
return workerMethods;
|
|
989
927
|
}
|
|
990
|
-
|
|
991
|
-
gifWriter.js
|
|
992
|
-
============
|
|
993
|
-
*/
|
|
994
|
-
// (c) Dean McNamee <dean@gmail.com>, 2013.
|
|
995
|
-
//
|
|
996
|
-
// https://github.com/deanm/omggif
|
|
997
|
-
//
|
|
998
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
999
|
-
// of this software and associated documentation files (the "Software"), to
|
|
1000
|
-
// deal in the Software without restriction, including without limitation the
|
|
1001
|
-
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
1002
|
-
// sell copies of the Software, and to permit persons to whom the Software is
|
|
1003
|
-
// furnished to do so, subject to the following conditions:
|
|
1004
|
-
//
|
|
1005
|
-
// The above copyright notice and this permission notice shall be included in
|
|
1006
|
-
// all copies or substantial portions of the Software.
|
|
1007
|
-
//
|
|
1008
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1009
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1010
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1011
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1012
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
1013
|
-
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
1014
|
-
// IN THE SOFTWARE.
|
|
1015
|
-
//
|
|
1016
|
-
// omggif is a JavaScript implementation of a GIF 89a encoder and decoder,
|
|
1017
|
-
// including animation and compression. It does not rely on any specific
|
|
1018
|
-
// underlying system, so should run in the browser, Node, or Plask.
|
|
928
|
+
|
|
1019
929
|
function gifWriter(buf, width, height, gopts) {
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
buf[p++] =
|
|
1053
|
-
buf[p++] =
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
// continue this chain (almost like a linked list) to always have small
|
|
1235
|
-
// integer values that represent the current byte chains in the encoder.
|
|
1236
|
-
// This means instead of tracking the input bytes (AAAABCD) to know our
|
|
1237
|
-
// current state, we can track the table entry for AAAABC (it is guaranteed
|
|
1238
|
-
// to exist by the nature of the algorithm) and the next character D.
|
|
1239
|
-
// Therefor the tuple of (table_entry, byte) is guaranteed to also be
|
|
1240
|
-
// unique. This allows us to create a simple lookup key for mapping input
|
|
1241
|
-
// sequences to codes (table indices) without having to store or search
|
|
1242
|
-
// any of the code sequences. So if 'AAAA' has a table entry of 12, the
|
|
1243
|
-
// tuple of ('AAAA', K) for any input byte K will be unique, and can be our
|
|
1244
|
-
// key. This leads to a integer value at most 20-bits, which can always
|
|
1245
|
-
// fit in an SMI value and be used as a fast sparse array / object key.
|
|
1246
|
-
// Output code for the current contents of the index buffer.
|
|
1247
|
-
let ib_code = index_stream[0] & code_mask; // Load first input index.
|
|
1248
|
-
let code_table = {}; // Key'd on our 20-bit "tuple".
|
|
1249
|
-
emit_code(clear_code); // Spec says first code should be a clear code.
|
|
1250
|
-
// First index already loaded, process the rest of the stream.
|
|
1251
|
-
for (let i = 1, il = index_stream.length; i < il; ++i) {
|
|
1252
|
-
const k = index_stream[i] & code_mask;
|
|
1253
|
-
const cur_key = (ib_code << 8) | k; // (prev, k) unique tuple.
|
|
1254
|
-
const cur_code = code_table[cur_key]; // buffer + k.
|
|
1255
|
-
// Check if we have to create a new code table entry.
|
|
1256
|
-
if (cur_code === undefined) {
|
|
1257
|
-
// We don't have buffer + k.
|
|
1258
|
-
// Emit index buffer (without k).
|
|
1259
|
-
// This is an inline version of emit_code, because this is the core
|
|
1260
|
-
// writing routine of the compressor (and V8 cannot inline emit_code
|
|
1261
|
-
// because it is a closure here in a different context). Additionally
|
|
1262
|
-
// we can call emit_byte_to_buffer less often, because we can have
|
|
1263
|
-
// 30-bits (from our 31-bit signed SMI), and we know our codes will only
|
|
1264
|
-
// be 12-bits, so can safely have 18-bits there without overflow.
|
|
1265
|
-
// emit_code(ib_code);
|
|
1266
|
-
cur |= ib_code << cur_shift;
|
|
1267
|
-
cur_shift += cur_code_size;
|
|
1268
|
-
while (cur_shift >= 8) {
|
|
1269
|
-
buf[p++] = cur & 0xff;
|
|
1270
|
-
cur >>= 8;
|
|
1271
|
-
cur_shift -= 8;
|
|
1272
|
-
if (p === cur_subblock + 256) {
|
|
1273
|
-
// Finished a subblock.
|
|
1274
|
-
buf[cur_subblock] = 255;
|
|
1275
|
-
cur_subblock = p++;
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
if (next_code === 4096) {
|
|
1279
|
-
// Table full, need a clear.
|
|
1280
|
-
emit_code(clear_code);
|
|
1281
|
-
next_code = eoi_code + 1;
|
|
1282
|
-
cur_code_size = min_code_size + 1;
|
|
1283
|
-
code_table = {};
|
|
1284
|
-
}
|
|
1285
|
-
else {
|
|
1286
|
-
// Table not full, insert a new entry.
|
|
1287
|
-
// Increase our variable bit code sizes if necessary. This is a bit
|
|
1288
|
-
// tricky as it is based on "timing" between the encoding and
|
|
1289
|
-
// decoder. From the encoders perspective this should happen after
|
|
1290
|
-
// we've already emitted the index buffer and are about to create the
|
|
1291
|
-
// first table entry that would overflow our current code bit size.
|
|
1292
|
-
if (next_code >= 1 << cur_code_size)
|
|
1293
|
-
++cur_code_size;
|
|
1294
|
-
code_table[cur_key] = next_code++; // Insert into code table.
|
|
1295
|
-
}
|
|
1296
|
-
ib_code = k; // Index buffer to single input k.
|
|
1297
|
-
}
|
|
1298
|
-
else {
|
|
1299
|
-
ib_code = cur_code; // Index buffer to sequence in code table.
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
emit_code(ib_code); // There will still be something in the index buffer.
|
|
1303
|
-
emit_code(eoi_code); // End Of Information.
|
|
1304
|
-
// Flush / finalize the sub-blocks stream to the buffer.
|
|
1305
|
-
emit_bytes_to_buffer(1);
|
|
1306
|
-
// Finish the sub-blocks, writing out any unfinished lengths and
|
|
1307
|
-
// terminating with a sub-block of length 0. If we have already started
|
|
1308
|
-
// but not yet used a sub-block it can just become the terminator.
|
|
1309
|
-
if (cur_subblock + 1 === p) {
|
|
1310
|
-
// Started but unused.
|
|
1311
|
-
buf[cur_subblock] = 0;
|
|
1312
|
-
}
|
|
1313
|
-
else {
|
|
1314
|
-
// Started and used, write length and additional terminator block.
|
|
1315
|
-
buf[cur_subblock] = p - cur_subblock - 1;
|
|
1316
|
-
buf[p++] = 0;
|
|
1317
|
-
}
|
|
1318
|
-
return p;
|
|
930
|
+
let p = 0;
|
|
931
|
+
gopts = gopts === undefined ? {} : gopts;
|
|
932
|
+
const loop_count = gopts.loop === undefined ? null : gopts.loop;
|
|
933
|
+
const global_palette = gopts.palette === undefined ? null : gopts.palette;
|
|
934
|
+
if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw 'Width/Height invalid.';
|
|
935
|
+
|
|
936
|
+
function check_palette_and_num_colors(palette) {
|
|
937
|
+
const num_colors = palette.length;
|
|
938
|
+
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.';
|
|
939
|
+
return num_colors;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
buf[p++] = 0x47;
|
|
943
|
+
buf[p++] = 0x49;
|
|
944
|
+
buf[p++] = 0x46;
|
|
945
|
+
buf[p++] = 0x38;
|
|
946
|
+
buf[p++] = 0x39;
|
|
947
|
+
buf[p++] = 0x61;
|
|
948
|
+
const gp_num_colors_pow2 = 0;
|
|
949
|
+
const background = 0;
|
|
950
|
+
buf[p++] = width & 0xff;
|
|
951
|
+
buf[p++] = width >> 8 & 0xff;
|
|
952
|
+
buf[p++] = height & 0xff;
|
|
953
|
+
buf[p++] = height >> 8 & 0xff;
|
|
954
|
+
buf[p++] = (global_palette !== null ? 0x80 : 0) | gp_num_colors_pow2;
|
|
955
|
+
buf[p++] = background;
|
|
956
|
+
buf[p++] = 0;
|
|
957
|
+
|
|
958
|
+
if (loop_count !== null) {
|
|
959
|
+
if (loop_count < 0 || loop_count > 65535) throw 'Loop count invalid.';
|
|
960
|
+
buf[p++] = 0x21;
|
|
961
|
+
buf[p++] = 0xff;
|
|
962
|
+
buf[p++] = 0x0b;
|
|
963
|
+
buf[p++] = 0x4e;
|
|
964
|
+
buf[p++] = 0x45;
|
|
965
|
+
buf[p++] = 0x54;
|
|
966
|
+
buf[p++] = 0x53;
|
|
967
|
+
buf[p++] = 0x43;
|
|
968
|
+
buf[p++] = 0x41;
|
|
969
|
+
buf[p++] = 0x50;
|
|
970
|
+
buf[p++] = 0x45;
|
|
971
|
+
buf[p++] = 0x32;
|
|
972
|
+
buf[p++] = 0x2e;
|
|
973
|
+
buf[p++] = 0x30;
|
|
974
|
+
buf[p++] = 0x03;
|
|
975
|
+
buf[p++] = 0x01;
|
|
976
|
+
buf[p++] = loop_count & 0xff;
|
|
977
|
+
buf[p++] = loop_count >> 8 & 0xff;
|
|
978
|
+
buf[p++] = 0x00;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
let ended = false;
|
|
982
|
+
|
|
983
|
+
this.addFrame = function (x, y, w, h, indexed_pixels, opts) {
|
|
984
|
+
if (ended === true) {
|
|
985
|
+
--p;
|
|
986
|
+
ended = false;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
opts = opts === undefined ? {} : opts;
|
|
990
|
+
if (x < 0 || y < 0 || x > 65535 || y > 65535) throw 'x/y invalid.';
|
|
991
|
+
if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw 'Width/Height invalid.';
|
|
992
|
+
if (indexed_pixels.length < w * h) throw 'Not enough pixels for the frame size.';
|
|
993
|
+
let using_local_palette = true;
|
|
994
|
+
let palette = opts.palette;
|
|
995
|
+
|
|
996
|
+
if (palette === undefined || palette === null) {
|
|
997
|
+
using_local_palette = false;
|
|
998
|
+
palette = global_palette;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
if (palette === undefined || palette === null) throw 'Must supply either a local or global palette.';
|
|
1002
|
+
let num_colors = check_palette_and_num_colors(palette);
|
|
1003
|
+
let min_code_size = 0;
|
|
1004
|
+
|
|
1005
|
+
while (num_colors >>= 1) {
|
|
1006
|
+
++min_code_size;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
num_colors = 1 << min_code_size;
|
|
1010
|
+
const delay = opts.delay === undefined ? 0 : opts.delay;
|
|
1011
|
+
const disposal = opts.disposal === undefined ? 0 : opts.disposal;
|
|
1012
|
+
if (disposal < 0 || disposal > 3) throw 'Disposal out of range.';
|
|
1013
|
+
let use_transparency = false;
|
|
1014
|
+
let transparent_index = 0;
|
|
1015
|
+
|
|
1016
|
+
if (opts.transparent !== undefined && opts.transparent !== null) {
|
|
1017
|
+
use_transparency = true;
|
|
1018
|
+
transparent_index = opts.transparent;
|
|
1019
|
+
if (transparent_index < 0 || transparent_index >= num_colors) throw 'Transparent color index.';
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
if (disposal !== 0 || use_transparency || delay !== 0) {
|
|
1023
|
+
buf[p++] = 0x21;
|
|
1024
|
+
buf[p++] = 0xf9;
|
|
1025
|
+
buf[p++] = 4;
|
|
1026
|
+
buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0);
|
|
1027
|
+
buf[p++] = delay & 0xff;
|
|
1028
|
+
buf[p++] = delay >> 8 & 0xff;
|
|
1029
|
+
buf[p++] = transparent_index;
|
|
1030
|
+
buf[p++] = 0;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
buf[p++] = 0x2c;
|
|
1034
|
+
buf[p++] = x & 0xff;
|
|
1035
|
+
buf[p++] = x >> 8 & 0xff;
|
|
1036
|
+
buf[p++] = y & 0xff;
|
|
1037
|
+
buf[p++] = y >> 8 & 0xff;
|
|
1038
|
+
buf[p++] = w & 0xff;
|
|
1039
|
+
buf[p++] = w >> 8 & 0xff;
|
|
1040
|
+
buf[p++] = h & 0xff;
|
|
1041
|
+
buf[p++] = h >> 8 & 0xff;
|
|
1042
|
+
buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0;
|
|
1043
|
+
|
|
1044
|
+
if (using_local_palette === true) {
|
|
1045
|
+
for (let i = 0, il = palette.length; i < il; ++i) {
|
|
1046
|
+
const rgb = palette[i];
|
|
1047
|
+
buf[p++] = rgb >> 16 & 0xff;
|
|
1048
|
+
buf[p++] = rgb >> 8 & 0xff;
|
|
1049
|
+
buf[p++] = rgb & 0xff;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels);
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
this.end = function () {
|
|
1057
|
+
if (ended === false) {
|
|
1058
|
+
buf[p++] = 0x3b;
|
|
1059
|
+
ended = true;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
return p;
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) {
|
|
1066
|
+
buf[p++] = min_code_size;
|
|
1067
|
+
let cur_subblock = p++;
|
|
1068
|
+
const clear_code = 1 << min_code_size;
|
|
1069
|
+
const code_mask = clear_code - 1;
|
|
1070
|
+
const eoi_code = clear_code + 1;
|
|
1071
|
+
let next_code = eoi_code + 1;
|
|
1072
|
+
let cur_code_size = min_code_size + 1;
|
|
1073
|
+
let cur_shift = 0;
|
|
1074
|
+
let cur = 0;
|
|
1075
|
+
|
|
1076
|
+
function emit_bytes_to_buffer(bit_block_size) {
|
|
1077
|
+
while (cur_shift >= bit_block_size) {
|
|
1078
|
+
buf[p++] = cur & 0xff;
|
|
1079
|
+
cur >>= 8;
|
|
1080
|
+
cur_shift -= 8;
|
|
1081
|
+
|
|
1082
|
+
if (p === cur_subblock + 256) {
|
|
1083
|
+
buf[cur_subblock] = 255;
|
|
1084
|
+
cur_subblock = p++;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
function emit_code(c) {
|
|
1090
|
+
cur |= c << cur_shift;
|
|
1091
|
+
cur_shift += cur_code_size;
|
|
1092
|
+
emit_bytes_to_buffer(8);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
let ib_code = index_stream[0] & code_mask;
|
|
1096
|
+
let code_table = {};
|
|
1097
|
+
emit_code(clear_code);
|
|
1098
|
+
|
|
1099
|
+
for (let i = 1, il = index_stream.length; i < il; ++i) {
|
|
1100
|
+
const k = index_stream[i] & code_mask;
|
|
1101
|
+
const cur_key = ib_code << 8 | k;
|
|
1102
|
+
const cur_code = code_table[cur_key];
|
|
1103
|
+
|
|
1104
|
+
if (cur_code === undefined) {
|
|
1105
|
+
cur |= ib_code << cur_shift;
|
|
1106
|
+
cur_shift += cur_code_size;
|
|
1107
|
+
|
|
1108
|
+
while (cur_shift >= 8) {
|
|
1109
|
+
buf[p++] = cur & 0xff;
|
|
1110
|
+
cur >>= 8;
|
|
1111
|
+
cur_shift -= 8;
|
|
1112
|
+
|
|
1113
|
+
if (p === cur_subblock + 256) {
|
|
1114
|
+
buf[cur_subblock] = 255;
|
|
1115
|
+
cur_subblock = p++;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
if (next_code === 4096) {
|
|
1120
|
+
emit_code(clear_code);
|
|
1121
|
+
next_code = eoi_code + 1;
|
|
1122
|
+
cur_code_size = min_code_size + 1;
|
|
1123
|
+
code_table = {};
|
|
1124
|
+
} else {
|
|
1125
|
+
if (next_code >= 1 << cur_code_size) ++cur_code_size;
|
|
1126
|
+
code_table[cur_key] = next_code++;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
ib_code = k;
|
|
1130
|
+
} else {
|
|
1131
|
+
ib_code = cur_code;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
emit_code(ib_code);
|
|
1136
|
+
emit_code(eoi_code);
|
|
1137
|
+
emit_bytes_to_buffer(1);
|
|
1138
|
+
|
|
1139
|
+
if (cur_subblock + 1 === p) {
|
|
1140
|
+
buf[cur_subblock] = 0;
|
|
1141
|
+
} else {
|
|
1142
|
+
buf[cur_subblock] = p - cur_subblock - 1;
|
|
1143
|
+
buf[p++] = 0;
|
|
1319
1144
|
}
|
|
1145
|
+
|
|
1146
|
+
return p;
|
|
1147
|
+
}
|
|
1320
1148
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
*/
|
|
1325
|
-
/* Copyright 2017 Yahoo Inc.
|
|
1326
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
1327
|
-
*/
|
|
1328
|
-
// Dependencies
|
|
1329
|
-
// Helpers
|
|
1330
|
-
const noop$2 = function noop() { };
|
|
1149
|
+
|
|
1150
|
+
const noop$2 = function noop() {};
|
|
1151
|
+
|
|
1331
1152
|
const AnimatedGIF = function AnimatedGIF(options) {
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
this.initializeWebWorkers(options);
|
|
1153
|
+
this.canvas = null;
|
|
1154
|
+
this.ctx = null;
|
|
1155
|
+
this.repeat = 0;
|
|
1156
|
+
this.frames = [];
|
|
1157
|
+
this.numRenderedFrames = 0;
|
|
1158
|
+
this.onRenderCompleteCallback = noop$2;
|
|
1159
|
+
this.onRenderProgressCallback = noop$2;
|
|
1160
|
+
this.workers = [];
|
|
1161
|
+
this.availableWorkers = [];
|
|
1162
|
+
this.generatingGIF = false;
|
|
1163
|
+
this.options = options;
|
|
1164
|
+
this.initializeWebWorkers(options);
|
|
1345
1165
|
};
|
|
1166
|
+
|
|
1346
1167
|
AnimatedGIF.prototype = {
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
}
|
|
1369
|
-
else {
|
|
1370
|
-
workerError = webWorkerObj;
|
|
1371
|
-
utils.webWorkerError = Boolean(webWorkerObj);
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
this.workerError = workerError;
|
|
1375
|
-
this.canvas = document.createElement('canvas');
|
|
1376
|
-
this.canvas.width = options.gifWidth;
|
|
1377
|
-
this.canvas.height = options.gifHeight;
|
|
1378
|
-
this.ctx = this.canvas.getContext('2d');
|
|
1379
|
-
this.frames = [];
|
|
1380
|
-
},
|
|
1381
|
-
// Return a worker for processing a frame
|
|
1382
|
-
getWorker: function getWorker() {
|
|
1383
|
-
return this.availableWorkers.pop();
|
|
1384
|
-
},
|
|
1385
|
-
// Restores a worker to the pool
|
|
1386
|
-
freeWorker: function freeWorker(worker) {
|
|
1387
|
-
this.availableWorkers.push(worker);
|
|
1388
|
-
},
|
|
1389
|
-
byteMap: (function () {
|
|
1390
|
-
const byteMap = [];
|
|
1391
|
-
for (let i = 0; i < 256; i++) {
|
|
1392
|
-
byteMap[i] = String.fromCharCode(i);
|
|
1393
|
-
}
|
|
1394
|
-
return byteMap;
|
|
1395
|
-
})(),
|
|
1396
|
-
bufferToString: function bufferToString(buffer) {
|
|
1397
|
-
const numberValues = buffer.length;
|
|
1398
|
-
let str = '';
|
|
1399
|
-
let x = -1;
|
|
1400
|
-
while (++x < numberValues) {
|
|
1401
|
-
str += this.byteMap[buffer[x]];
|
|
1402
|
-
}
|
|
1403
|
-
return str;
|
|
1404
|
-
},
|
|
1405
|
-
onFrameFinished: function onFrameFinished(progressCallback) {
|
|
1406
|
-
// The GIF is not written until we're done with all the frames
|
|
1407
|
-
// because they might not be processed in the same order
|
|
1408
|
-
const self = this;
|
|
1409
|
-
const frames = self.frames;
|
|
1410
|
-
const options = self.options;
|
|
1411
|
-
const hasExistingImages = Boolean((options.images || []).length);
|
|
1412
|
-
const allDone = frames.every(function (frame) {
|
|
1413
|
-
return !frame.beingProcessed && frame.done;
|
|
1414
|
-
});
|
|
1415
|
-
self.numRenderedFrames++;
|
|
1416
|
-
if (hasExistingImages) {
|
|
1417
|
-
progressCallback(self.numRenderedFrames / frames.length);
|
|
1418
|
-
}
|
|
1419
|
-
self.onRenderProgressCallback((self.numRenderedFrames * 0.75) / frames.length);
|
|
1420
|
-
if (allDone) {
|
|
1421
|
-
if (!self.generatingGIF) {
|
|
1422
|
-
self.generateGIF(frames, self.onRenderCompleteCallback);
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
else {
|
|
1426
|
-
utils.requestTimeout(function () {
|
|
1427
|
-
self.processNextFrame();
|
|
1428
|
-
}, 1);
|
|
1429
|
-
}
|
|
1430
|
-
},
|
|
1431
|
-
processFrame: function processFrame(position) {
|
|
1432
|
-
const AnimatedGifContext = this;
|
|
1433
|
-
const options = this.options;
|
|
1434
|
-
const _options = this.options;
|
|
1435
|
-
const progressCallback = _options.progressCallback;
|
|
1436
|
-
const sampleInterval = _options.sampleInterval;
|
|
1437
|
-
const frames = this.frames;
|
|
1438
|
-
let frame = void 0;
|
|
1439
|
-
let worker = void 0;
|
|
1440
|
-
const done = function done() {
|
|
1441
|
-
const ev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1442
|
-
const data = ev.data;
|
|
1443
|
-
// Delete original data, and free memory
|
|
1444
|
-
delete frame.data;
|
|
1445
|
-
frame.pixels = Array.prototype.slice.call(data.pixels);
|
|
1446
|
-
frame.palette = Array.prototype.slice.call(data.palette);
|
|
1447
|
-
frame.done = true;
|
|
1448
|
-
frame.beingProcessed = false;
|
|
1449
|
-
AnimatedGifContext.freeWorker(worker);
|
|
1450
|
-
AnimatedGifContext.onFrameFinished(progressCallback);
|
|
1451
|
-
};
|
|
1452
|
-
frame = frames[position];
|
|
1453
|
-
if (frame.beingProcessed || frame.done) {
|
|
1454
|
-
this.onFrameFinished();
|
|
1455
|
-
return;
|
|
1456
|
-
}
|
|
1457
|
-
frame.sampleInterval = sampleInterval;
|
|
1458
|
-
frame.beingProcessed = true;
|
|
1459
|
-
frame.gifshot = true;
|
|
1460
|
-
worker = this.getWorker();
|
|
1461
|
-
if (worker) {
|
|
1462
|
-
// Process the frame in a web worker
|
|
1463
|
-
worker.onmessage = done;
|
|
1464
|
-
worker.postMessage(frame);
|
|
1465
|
-
}
|
|
1466
|
-
else {
|
|
1467
|
-
// Process the frame in the current thread
|
|
1468
|
-
done({
|
|
1469
|
-
data: AnimatedGifContext.workerMethods.run(frame)
|
|
1470
|
-
});
|
|
1471
|
-
}
|
|
1472
|
-
},
|
|
1473
|
-
startRendering: function startRendering(completeCallback) {
|
|
1474
|
-
this.onRenderCompleteCallback = completeCallback;
|
|
1475
|
-
for (let i = 0; i < this.options.numWorkers && i < this.frames.length; i++) {
|
|
1476
|
-
this.processFrame(i);
|
|
1477
|
-
}
|
|
1478
|
-
},
|
|
1479
|
-
processNextFrame: function processNextFrame() {
|
|
1480
|
-
let position = -1;
|
|
1481
|
-
for (let i = 0; i < this.frames.length; i++) {
|
|
1482
|
-
const frame = this.frames[i];
|
|
1483
|
-
if (!frame.done && !frame.beingProcessed) {
|
|
1484
|
-
position = i;
|
|
1485
|
-
break;
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
if (position >= 0) {
|
|
1489
|
-
this.processFrame(position);
|
|
1490
|
-
}
|
|
1491
|
-
},
|
|
1492
|
-
// Takes the already processed data in frames and feeds it to a new
|
|
1493
|
-
// GifWriter instance in order to get the binary GIF file
|
|
1494
|
-
generateGIF: function generateGIF(frames, callback) {
|
|
1495
|
-
// TODO: Weird: using a simple JS array instead of a typed array,
|
|
1496
|
-
// the files are WAY smaller o_o. Patches/explanations welcome!
|
|
1497
|
-
const buffer = []; // new Uint8Array(width * height * frames.length * 5);
|
|
1498
|
-
const gifOptions = {
|
|
1499
|
-
loop: this.repeat
|
|
1500
|
-
};
|
|
1501
|
-
const options = this.options;
|
|
1502
|
-
const interval = options.interval;
|
|
1503
|
-
const frameDuration = options.frameDuration;
|
|
1504
|
-
const existingImages = options.images;
|
|
1505
|
-
const hasExistingImages = Boolean(existingImages.length);
|
|
1506
|
-
const height = options.gifHeight;
|
|
1507
|
-
const width = options.gifWidth;
|
|
1508
|
-
const gifWriter$$1 = new gifWriter(buffer, width, height, gifOptions);
|
|
1509
|
-
const onRenderProgressCallback = this.onRenderProgressCallback;
|
|
1510
|
-
const delay = hasExistingImages ? interval * 100 : 0;
|
|
1511
|
-
let bufferToString = void 0;
|
|
1512
|
-
let gif = void 0;
|
|
1513
|
-
this.generatingGIF = true;
|
|
1514
|
-
utils.each(frames, function (iterator, frame) {
|
|
1515
|
-
const framePalette = frame.palette;
|
|
1516
|
-
onRenderProgressCallback(0.75 + (0.25 * frame.position * 1.0) / frames.length);
|
|
1517
|
-
for (let i = 0; i < frameDuration; i++) {
|
|
1518
|
-
gifWriter$$1.addFrame(0, 0, width, height, frame.pixels, {
|
|
1519
|
-
palette: framePalette,
|
|
1520
|
-
delay
|
|
1521
|
-
});
|
|
1522
|
-
}
|
|
1523
|
-
});
|
|
1524
|
-
gifWriter$$1.end();
|
|
1525
|
-
onRenderProgressCallback(1.0);
|
|
1526
|
-
this.frames = [];
|
|
1527
|
-
this.generatingGIF = false;
|
|
1528
|
-
if (utils.isFunction(callback)) {
|
|
1529
|
-
bufferToString = this.bufferToString(buffer);
|
|
1530
|
-
gif = `data:image/gif;base64,${utils.btoa(bufferToString)}`;
|
|
1531
|
-
callback(gif);
|
|
1532
|
-
}
|
|
1533
|
-
},
|
|
1534
|
-
// From GIF: 0 = loop forever, null = not looping, n > 0 = loop n times and stop
|
|
1535
|
-
setRepeat: function setRepeat(r) {
|
|
1536
|
-
this.repeat = r;
|
|
1537
|
-
},
|
|
1538
|
-
addFrame: function addFrame(element, gifshotOptions) {
|
|
1539
|
-
gifshotOptions = utils.isObject(gifshotOptions) ? gifshotOptions : {};
|
|
1540
|
-
const self = this;
|
|
1541
|
-
const ctx = self.ctx;
|
|
1542
|
-
const options = self.options;
|
|
1543
|
-
const width = options.gifWidth;
|
|
1544
|
-
const height = options.gifHeight;
|
|
1545
|
-
const fontSize = utils.getFontSize(gifshotOptions);
|
|
1546
|
-
const _gifshotOptions = gifshotOptions;
|
|
1547
|
-
const filter = _gifshotOptions.filter;
|
|
1548
|
-
const fontColor = _gifshotOptions.fontColor;
|
|
1549
|
-
const fontFamily = _gifshotOptions.fontFamily;
|
|
1550
|
-
const fontWeight = _gifshotOptions.fontWeight;
|
|
1551
|
-
const gifHeight = _gifshotOptions.gifHeight;
|
|
1552
|
-
const gifWidth = _gifshotOptions.gifWidth;
|
|
1553
|
-
const text = _gifshotOptions.text;
|
|
1554
|
-
const textAlign = _gifshotOptions.textAlign;
|
|
1555
|
-
const textBaseline = _gifshotOptions.textBaseline;
|
|
1556
|
-
const textXCoordinate = gifshotOptions.textXCoordinate
|
|
1557
|
-
? gifshotOptions.textXCoordinate
|
|
1558
|
-
: textAlign === 'left'
|
|
1559
|
-
? 1
|
|
1560
|
-
: textAlign === 'right'
|
|
1561
|
-
? width
|
|
1562
|
-
: width / 2;
|
|
1563
|
-
const textYCoordinate = gifshotOptions.textYCoordinate
|
|
1564
|
-
? gifshotOptions.textYCoordinate
|
|
1565
|
-
: textBaseline === 'top'
|
|
1566
|
-
? 1
|
|
1567
|
-
: textBaseline === 'center'
|
|
1568
|
-
? height / 2
|
|
1569
|
-
: height;
|
|
1570
|
-
const font = `${fontWeight} ${fontSize} ${fontFamily}`;
|
|
1571
|
-
let imageData = void 0;
|
|
1572
|
-
try {
|
|
1573
|
-
ctx.filter = filter;
|
|
1574
|
-
ctx.drawImage(element, 0, 0, width, height);
|
|
1575
|
-
if (text) {
|
|
1576
|
-
ctx.font = font;
|
|
1577
|
-
ctx.fillStyle = fontColor;
|
|
1578
|
-
ctx.textAlign = textAlign;
|
|
1579
|
-
ctx.textBaseline = textBaseline;
|
|
1580
|
-
ctx.fillText(text, textXCoordinate, textYCoordinate);
|
|
1581
|
-
}
|
|
1582
|
-
imageData = ctx.getImageData(0, 0, width, height);
|
|
1583
|
-
self.addFrameImageData(imageData);
|
|
1584
|
-
}
|
|
1585
|
-
catch (e) {
|
|
1586
|
-
return `${e}`;
|
|
1587
|
-
}
|
|
1588
|
-
},
|
|
1589
|
-
addFrameImageData: function addFrameImageData() {
|
|
1590
|
-
const imageData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1591
|
-
const frames = this.frames;
|
|
1592
|
-
const imageDataArray = imageData.data;
|
|
1593
|
-
this.frames.push({
|
|
1594
|
-
data: imageDataArray,
|
|
1595
|
-
width: imageData.width,
|
|
1596
|
-
height: imageData.height,
|
|
1597
|
-
palette: null,
|
|
1598
|
-
dithering: null,
|
|
1599
|
-
done: false,
|
|
1600
|
-
beingProcessed: false,
|
|
1601
|
-
position: frames.length
|
|
1168
|
+
workerMethods: workerCode(),
|
|
1169
|
+
initializeWebWorkers: function initializeWebWorkers(options) {
|
|
1170
|
+
const self = this;
|
|
1171
|
+
const processFrameWorkerCode = "".concat(NeuQuant.toString(), "(").concat(workerCode.toString(), "());");
|
|
1172
|
+
let webWorkerObj = void 0;
|
|
1173
|
+
let objectUrl = void 0;
|
|
1174
|
+
let webWorker = void 0;
|
|
1175
|
+
let numWorkers = void 0;
|
|
1176
|
+
let x = -1;
|
|
1177
|
+
let workerError = '';
|
|
1178
|
+
numWorkers = options.numWorkers;
|
|
1179
|
+
|
|
1180
|
+
while (++x < numWorkers) {
|
|
1181
|
+
webWorkerObj = utils.createWebWorker(processFrameWorkerCode);
|
|
1182
|
+
|
|
1183
|
+
if (utils.isObject(webWorkerObj)) {
|
|
1184
|
+
objectUrl = webWorkerObj.objectUrl;
|
|
1185
|
+
webWorker = webWorkerObj.worker;
|
|
1186
|
+
self.workers.push({
|
|
1187
|
+
worker: webWorker,
|
|
1188
|
+
objectUrl
|
|
1602
1189
|
});
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1190
|
+
self.availableWorkers.push(webWorker);
|
|
1191
|
+
} else {
|
|
1192
|
+
workerError = webWorkerObj;
|
|
1193
|
+
utils.webWorkerError = Boolean(webWorkerObj);
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
this.workerError = workerError;
|
|
1198
|
+
this.canvas = document.createElement('canvas');
|
|
1199
|
+
this.canvas.width = options.gifWidth;
|
|
1200
|
+
this.canvas.height = options.gifHeight;
|
|
1201
|
+
this.ctx = this.canvas.getContext('2d');
|
|
1202
|
+
this.frames = [];
|
|
1203
|
+
},
|
|
1204
|
+
getWorker: function getWorker() {
|
|
1205
|
+
return this.availableWorkers.pop();
|
|
1206
|
+
},
|
|
1207
|
+
freeWorker: function freeWorker(worker) {
|
|
1208
|
+
this.availableWorkers.push(worker);
|
|
1209
|
+
},
|
|
1210
|
+
byteMap: function () {
|
|
1211
|
+
const byteMap = [];
|
|
1212
|
+
|
|
1213
|
+
for (let i = 0; i < 256; i++) {
|
|
1214
|
+
byteMap[i] = String.fromCharCode(i);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
return byteMap;
|
|
1218
|
+
}(),
|
|
1219
|
+
bufferToString: function bufferToString(buffer) {
|
|
1220
|
+
const numberValues = buffer.length;
|
|
1221
|
+
let str = '';
|
|
1222
|
+
let x = -1;
|
|
1223
|
+
|
|
1224
|
+
while (++x < numberValues) {
|
|
1225
|
+
str += this.byteMap[buffer[x]];
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
return str;
|
|
1229
|
+
},
|
|
1230
|
+
onFrameFinished: function onFrameFinished(progressCallback) {
|
|
1231
|
+
const self = this;
|
|
1232
|
+
const frames = self.frames;
|
|
1233
|
+
const options = self.options;
|
|
1234
|
+
const hasExistingImages = Boolean((options.images || []).length);
|
|
1235
|
+
const allDone = frames.every(function (frame) {
|
|
1236
|
+
return !frame.beingProcessed && frame.done;
|
|
1237
|
+
});
|
|
1238
|
+
self.numRenderedFrames++;
|
|
1239
|
+
|
|
1240
|
+
if (hasExistingImages) {
|
|
1241
|
+
progressCallback(self.numRenderedFrames / frames.length);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
self.onRenderProgressCallback(self.numRenderedFrames * 0.75 / frames.length);
|
|
1245
|
+
|
|
1246
|
+
if (allDone) {
|
|
1247
|
+
if (!self.generatingGIF) {
|
|
1248
|
+
self.generateGIF(frames, self.onRenderCompleteCallback);
|
|
1249
|
+
}
|
|
1250
|
+
} else {
|
|
1251
|
+
utils.requestTimeout(function () {
|
|
1252
|
+
self.processNextFrame();
|
|
1253
|
+
}, 1);
|
|
1254
|
+
}
|
|
1255
|
+
},
|
|
1256
|
+
processFrame: function processFrame(position) {
|
|
1257
|
+
const AnimatedGifContext = this;
|
|
1258
|
+
const options = this.options;
|
|
1259
|
+
const _options = this.options;
|
|
1260
|
+
const progressCallback = _options.progressCallback;
|
|
1261
|
+
const sampleInterval = _options.sampleInterval;
|
|
1262
|
+
const frames = this.frames;
|
|
1263
|
+
let frame = void 0;
|
|
1264
|
+
let worker = void 0;
|
|
1265
|
+
|
|
1266
|
+
const done = function done() {
|
|
1267
|
+
const ev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1268
|
+
const data = ev.data;
|
|
1269
|
+
delete frame.data;
|
|
1270
|
+
frame.pixels = Array.prototype.slice.call(data.pixels);
|
|
1271
|
+
frame.palette = Array.prototype.slice.call(data.palette);
|
|
1272
|
+
frame.done = true;
|
|
1273
|
+
frame.beingProcessed = false;
|
|
1274
|
+
AnimatedGifContext.freeWorker(worker);
|
|
1275
|
+
AnimatedGifContext.onFrameFinished(progressCallback);
|
|
1276
|
+
};
|
|
1277
|
+
|
|
1278
|
+
frame = frames[position];
|
|
1279
|
+
|
|
1280
|
+
if (frame.beingProcessed || frame.done) {
|
|
1281
|
+
this.onFrameFinished();
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
frame.sampleInterval = sampleInterval;
|
|
1286
|
+
frame.beingProcessed = true;
|
|
1287
|
+
frame.gifshot = true;
|
|
1288
|
+
worker = this.getWorker();
|
|
1289
|
+
|
|
1290
|
+
if (worker) {
|
|
1291
|
+
worker.onmessage = done;
|
|
1292
|
+
worker.postMessage(frame);
|
|
1293
|
+
} else {
|
|
1294
|
+
done({
|
|
1295
|
+
data: AnimatedGifContext.workerMethods.run(frame)
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
},
|
|
1299
|
+
startRendering: function startRendering(completeCallback) {
|
|
1300
|
+
this.onRenderCompleteCallback = completeCallback;
|
|
1301
|
+
|
|
1302
|
+
for (let i = 0; i < this.options.numWorkers && i < this.frames.length; i++) {
|
|
1303
|
+
this.processFrame(i);
|
|
1304
|
+
}
|
|
1305
|
+
},
|
|
1306
|
+
processNextFrame: function processNextFrame() {
|
|
1307
|
+
let position = -1;
|
|
1308
|
+
|
|
1309
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
1310
|
+
const frame = this.frames[i];
|
|
1311
|
+
|
|
1312
|
+
if (!frame.done && !frame.beingProcessed) {
|
|
1313
|
+
position = i;
|
|
1314
|
+
break;
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
if (position >= 0) {
|
|
1319
|
+
this.processFrame(position);
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
generateGIF: function generateGIF(frames, callback) {
|
|
1323
|
+
const buffer = [];
|
|
1324
|
+
const gifOptions = {
|
|
1325
|
+
loop: this.repeat
|
|
1326
|
+
};
|
|
1327
|
+
const options = this.options;
|
|
1328
|
+
const interval = options.interval;
|
|
1329
|
+
const frameDuration = options.frameDuration;
|
|
1330
|
+
const existingImages = options.images;
|
|
1331
|
+
const hasExistingImages = Boolean(existingImages.length);
|
|
1332
|
+
const height = options.gifHeight;
|
|
1333
|
+
const width = options.gifWidth;
|
|
1334
|
+
const gifWriter$$1 = new gifWriter(buffer, width, height, gifOptions);
|
|
1335
|
+
const onRenderProgressCallback = this.onRenderProgressCallback;
|
|
1336
|
+
const delay = hasExistingImages ? interval * 100 : 0;
|
|
1337
|
+
let bufferToString = void 0;
|
|
1338
|
+
let gif = void 0;
|
|
1339
|
+
this.generatingGIF = true;
|
|
1340
|
+
utils.each(frames, function (iterator, frame) {
|
|
1341
|
+
const framePalette = frame.palette;
|
|
1342
|
+
onRenderProgressCallback(0.75 + 0.25 * frame.position * 1.0 / frames.length);
|
|
1343
|
+
|
|
1344
|
+
for (let i = 0; i < frameDuration; i++) {
|
|
1345
|
+
gifWriter$$1.addFrame(0, 0, width, height, frame.pixels, {
|
|
1346
|
+
palette: framePalette,
|
|
1347
|
+
delay
|
|
1631
1348
|
});
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
gifWriter$$1.end();
|
|
1352
|
+
onRenderProgressCallback(1.0);
|
|
1353
|
+
this.frames = [];
|
|
1354
|
+
this.generatingGIF = false;
|
|
1355
|
+
|
|
1356
|
+
if (utils.isFunction(callback)) {
|
|
1357
|
+
bufferToString = this.bufferToString(buffer);
|
|
1358
|
+
gif = "data:image/gif;base64,".concat(utils.btoa(bufferToString));
|
|
1359
|
+
callback(gif);
|
|
1632
1360
|
}
|
|
1361
|
+
},
|
|
1362
|
+
setRepeat: function setRepeat(r) {
|
|
1363
|
+
this.repeat = r;
|
|
1364
|
+
},
|
|
1365
|
+
addFrame: function addFrame(element, gifshotOptions) {
|
|
1366
|
+
gifshotOptions = utils.isObject(gifshotOptions) ? gifshotOptions : {};
|
|
1367
|
+
const self = this;
|
|
1368
|
+
const ctx = self.ctx;
|
|
1369
|
+
const options = self.options;
|
|
1370
|
+
const width = options.gifWidth;
|
|
1371
|
+
const height = options.gifHeight;
|
|
1372
|
+
const fontSize = utils.getFontSize(gifshotOptions);
|
|
1373
|
+
const _gifshotOptions = gifshotOptions;
|
|
1374
|
+
const filter = _gifshotOptions.filter;
|
|
1375
|
+
const fontColor = _gifshotOptions.fontColor;
|
|
1376
|
+
const fontFamily = _gifshotOptions.fontFamily;
|
|
1377
|
+
const fontWeight = _gifshotOptions.fontWeight;
|
|
1378
|
+
const gifHeight = _gifshotOptions.gifHeight;
|
|
1379
|
+
const gifWidth = _gifshotOptions.gifWidth;
|
|
1380
|
+
const text = _gifshotOptions.text;
|
|
1381
|
+
const textAlign = _gifshotOptions.textAlign;
|
|
1382
|
+
const textBaseline = _gifshotOptions.textBaseline;
|
|
1383
|
+
const textXCoordinate = gifshotOptions.textXCoordinate ? gifshotOptions.textXCoordinate : textAlign === 'left' ? 1 : textAlign === 'right' ? width : width / 2;
|
|
1384
|
+
const textYCoordinate = gifshotOptions.textYCoordinate ? gifshotOptions.textYCoordinate : textBaseline === 'top' ? 1 : textBaseline === 'center' ? height / 2 : height;
|
|
1385
|
+
const font = "".concat(fontWeight, " ").concat(fontSize, " ").concat(fontFamily);
|
|
1386
|
+
let imageData = void 0;
|
|
1387
|
+
|
|
1388
|
+
try {
|
|
1389
|
+
ctx.filter = filter;
|
|
1390
|
+
ctx.drawImage(element, 0, 0, width, height);
|
|
1391
|
+
|
|
1392
|
+
if (text) {
|
|
1393
|
+
ctx.font = font;
|
|
1394
|
+
ctx.fillStyle = fontColor;
|
|
1395
|
+
ctx.textAlign = textAlign;
|
|
1396
|
+
ctx.textBaseline = textBaseline;
|
|
1397
|
+
ctx.fillText(text, textXCoordinate, textYCoordinate);
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
imageData = ctx.getImageData(0, 0, width, height);
|
|
1401
|
+
self.addFrameImageData(imageData);
|
|
1402
|
+
} catch (e) {
|
|
1403
|
+
return "".concat(e);
|
|
1404
|
+
}
|
|
1405
|
+
},
|
|
1406
|
+
addFrameImageData: function addFrameImageData() {
|
|
1407
|
+
const imageData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1408
|
+
const frames = this.frames;
|
|
1409
|
+
const imageDataArray = imageData.data;
|
|
1410
|
+
this.frames.push({
|
|
1411
|
+
data: imageDataArray,
|
|
1412
|
+
width: imageData.width,
|
|
1413
|
+
height: imageData.height,
|
|
1414
|
+
palette: null,
|
|
1415
|
+
dithering: null,
|
|
1416
|
+
done: false,
|
|
1417
|
+
beingProcessed: false,
|
|
1418
|
+
position: frames.length
|
|
1419
|
+
});
|
|
1420
|
+
},
|
|
1421
|
+
onRenderProgress: function onRenderProgress(callback) {
|
|
1422
|
+
this.onRenderProgressCallback = callback;
|
|
1423
|
+
},
|
|
1424
|
+
isRendering: function isRendering() {
|
|
1425
|
+
return this.generatingGIF;
|
|
1426
|
+
},
|
|
1427
|
+
getBase64GIF: function getBase64GIF(completeCallback) {
|
|
1428
|
+
const self = this;
|
|
1429
|
+
|
|
1430
|
+
const onRenderComplete = function onRenderComplete(gif) {
|
|
1431
|
+
self.destroyWorkers();
|
|
1432
|
+
utils.requestTimeout(function () {
|
|
1433
|
+
completeCallback(gif);
|
|
1434
|
+
}, 0);
|
|
1435
|
+
};
|
|
1436
|
+
|
|
1437
|
+
self.startRendering(onRenderComplete);
|
|
1438
|
+
},
|
|
1439
|
+
destroyWorkers: function destroyWorkers() {
|
|
1440
|
+
if (this.workerError) {
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
const workers = this.workers;
|
|
1445
|
+
utils.each(workers, function (iterator, workerObj) {
|
|
1446
|
+
const worker = workerObj.worker;
|
|
1447
|
+
const objectUrl = workerObj.objectUrl;
|
|
1448
|
+
worker.terminate();
|
|
1449
|
+
utils.URL.revokeObjectURL(objectUrl);
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1633
1452
|
};
|
|
1634
|
-
|
|
1635
|
-
getBase64GIF.js
|
|
1636
|
-
===============
|
|
1637
|
-
*/
|
|
1638
|
-
/* Copyright 2017 Yahoo Inc.
|
|
1639
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
1640
|
-
*/
|
|
1453
|
+
|
|
1641
1454
|
function getBase64GIF(animatedGifInstance, callback) {
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
image
|
|
1649
|
-
});
|
|
1455
|
+
animatedGifInstance.getBase64GIF(function (image) {
|
|
1456
|
+
callback({
|
|
1457
|
+
error: false,
|
|
1458
|
+
errorCode: '',
|
|
1459
|
+
errorMsg: '',
|
|
1460
|
+
image
|
|
1650
1461
|
});
|
|
1462
|
+
});
|
|
1651
1463
|
}
|
|
1652
|
-
|
|
1653
|
-
existingImages.js
|
|
1654
|
-
=================
|
|
1655
|
-
*/
|
|
1656
|
-
/* Copyright 2017 Yahoo Inc.
|
|
1657
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
1658
|
-
*/
|
|
1464
|
+
|
|
1659
1465
|
function existingImages() {
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
ag.addFrame(loadedImage, options);
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
});
|
|
1749
|
-
getBase64GIF(ag, callback);
|
|
1466
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1467
|
+
const self = this;
|
|
1468
|
+
const callback = obj.callback;
|
|
1469
|
+
const images = obj.images;
|
|
1470
|
+
const options = obj.options;
|
|
1471
|
+
let imagesLength = obj.imagesLength;
|
|
1472
|
+
const skipObj = {
|
|
1473
|
+
getUserMedia: true,
|
|
1474
|
+
'window.URL': true
|
|
1475
|
+
};
|
|
1476
|
+
const errorObj = error.validate(skipObj);
|
|
1477
|
+
const loadedImages = [];
|
|
1478
|
+
let loadedImagesLength = 0;
|
|
1479
|
+
let tempImage = void 0;
|
|
1480
|
+
let ag = void 0;
|
|
1481
|
+
|
|
1482
|
+
if (errorObj.error) {
|
|
1483
|
+
return callback(errorObj);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
ag = new AnimatedGIF(options);
|
|
1487
|
+
utils.each(images, function (index, image) {
|
|
1488
|
+
const currentImage = image;
|
|
1489
|
+
|
|
1490
|
+
if (utils.isElement(currentImage)) {
|
|
1491
|
+
if (options.crossOrigin) {
|
|
1492
|
+
currentImage.crossOrigin = options.crossOrigin;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
loadedImages[index] = currentImage;
|
|
1496
|
+
loadedImagesLength += 1;
|
|
1497
|
+
|
|
1498
|
+
if (loadedImagesLength === imagesLength) {
|
|
1499
|
+
addLoadedImagesToGif();
|
|
1500
|
+
}
|
|
1501
|
+
} else if (utils.isString(currentImage)) {
|
|
1502
|
+
tempImage = new Image();
|
|
1503
|
+
|
|
1504
|
+
if (options.crossOrigin) {
|
|
1505
|
+
tempImage.crossOrigin = options.crossOrigin;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
(function (tempImage) {
|
|
1509
|
+
if (image.text) {
|
|
1510
|
+
tempImage.text = image.text;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
tempImage.onerror = function (e) {
|
|
1514
|
+
let obj = void 0;
|
|
1515
|
+
--imagesLength;
|
|
1516
|
+
|
|
1517
|
+
if (imagesLength === 0) {
|
|
1518
|
+
obj = {};
|
|
1519
|
+
obj.error = 'None of the requested images was capable of being retrieved';
|
|
1520
|
+
return callback(obj);
|
|
1521
|
+
}
|
|
1522
|
+
};
|
|
1523
|
+
|
|
1524
|
+
tempImage.onload = function (e) {
|
|
1525
|
+
if (image.text) {
|
|
1526
|
+
loadedImages[index] = {
|
|
1527
|
+
img: tempImage,
|
|
1528
|
+
text: tempImage.text
|
|
1529
|
+
};
|
|
1530
|
+
} else {
|
|
1531
|
+
loadedImages[index] = tempImage;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
loadedImagesLength += 1;
|
|
1535
|
+
|
|
1536
|
+
if (loadedImagesLength === imagesLength) {
|
|
1537
|
+
addLoadedImagesToGif();
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
utils.removeElement(tempImage);
|
|
1541
|
+
};
|
|
1542
|
+
|
|
1543
|
+
tempImage.src = currentImage;
|
|
1544
|
+
})(tempImage);
|
|
1545
|
+
|
|
1546
|
+
utils.setCSSAttr(tempImage, {
|
|
1547
|
+
position: 'fixed',
|
|
1548
|
+
opacity: '0'
|
|
1549
|
+
});
|
|
1550
|
+
document.body.appendChild(tempImage);
|
|
1750
1551
|
}
|
|
1552
|
+
});
|
|
1553
|
+
|
|
1554
|
+
function addLoadedImagesToGif() {
|
|
1555
|
+
utils.each(loadedImages, function (index, loadedImage) {
|
|
1556
|
+
if (loadedImage) {
|
|
1557
|
+
if (loadedImage.text) {
|
|
1558
|
+
ag.addFrame(loadedImage.img, options, loadedImage.text);
|
|
1559
|
+
} else {
|
|
1560
|
+
ag.addFrame(loadedImage, options);
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
});
|
|
1564
|
+
getBase64GIF(ag, callback);
|
|
1565
|
+
}
|
|
1751
1566
|
}
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
*/
|
|
1756
|
-
/* Copyright 2017 Yahoo Inc.
|
|
1757
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
1758
|
-
*/
|
|
1759
|
-
// Dependencies
|
|
1760
|
-
// Helpers
|
|
1761
|
-
const noop$3 = function noop() { };
|
|
1567
|
+
|
|
1568
|
+
const noop$3 = function noop() {};
|
|
1569
|
+
|
|
1762
1570
|
const screenShot = {
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
error: false,
|
|
1886
|
-
errorCode: '',
|
|
1887
|
-
errorMsg: '',
|
|
1888
|
-
image,
|
|
1889
|
-
cameraStream,
|
|
1890
|
-
videoElement,
|
|
1891
|
-
webcamVideoElement,
|
|
1892
|
-
savedRenderingContexts: renderingContextsToSave,
|
|
1893
|
-
keepCameraOn
|
|
1894
|
-
});
|
|
1895
|
-
});
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
};
|
|
1899
|
-
numFrames = numFrames !== undefined ? numFrames : 10;
|
|
1900
|
-
interval = interval !== undefined ? interval : 0.1; // In seconds
|
|
1901
|
-
canvas.width = gifWidth;
|
|
1902
|
-
canvas.height = gifHeight;
|
|
1903
|
-
context = canvas.getContext('2d');
|
|
1904
|
-
(function capture() {
|
|
1905
|
-
if (!savedRenderingContexts.length && videoElement.currentTime === 0) {
|
|
1906
|
-
utils.requestTimeout(capture, 100);
|
|
1907
|
-
return;
|
|
1908
|
-
}
|
|
1909
|
-
captureFrames();
|
|
1910
|
-
})();
|
|
1911
|
-
},
|
|
1912
|
-
getCropDimensions: function getCropDimensions() {
|
|
1913
|
-
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1914
|
-
const width = obj.videoWidth;
|
|
1915
|
-
const height = obj.videoHeight;
|
|
1916
|
-
const gifWidth = obj.gifWidth;
|
|
1917
|
-
const gifHeight = obj.gifHeight;
|
|
1918
|
-
const result = {
|
|
1919
|
-
width: 0,
|
|
1920
|
-
height: 0,
|
|
1921
|
-
scaledWidth: 0,
|
|
1922
|
-
scaledHeight: 0
|
|
1923
|
-
};
|
|
1924
|
-
if (width > height) {
|
|
1925
|
-
result.width = Math.round(width * (gifHeight / height)) - gifWidth;
|
|
1926
|
-
result.scaledWidth = Math.round(result.width * (height / gifHeight));
|
|
1927
|
-
}
|
|
1928
|
-
else {
|
|
1929
|
-
result.height = Math.round(height * (gifWidth / width)) - gifHeight;
|
|
1930
|
-
result.scaledHeight = Math.round(result.height * (width / gifWidth));
|
|
1571
|
+
getGIF: function getGIF() {
|
|
1572
|
+
const options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1573
|
+
let callback = arguments[1];
|
|
1574
|
+
callback = utils.isFunction(callback) ? callback : noop$3;
|
|
1575
|
+
const canvas = document.createElement('canvas');
|
|
1576
|
+
let context = void 0;
|
|
1577
|
+
const existingImages = options.images;
|
|
1578
|
+
const hasExistingImages = Boolean(existingImages.length);
|
|
1579
|
+
const cameraStream = options.cameraStream;
|
|
1580
|
+
const crop = options.crop;
|
|
1581
|
+
const filter = options.filter;
|
|
1582
|
+
const fontColor = options.fontColor;
|
|
1583
|
+
const fontFamily = options.fontFamily;
|
|
1584
|
+
const fontWeight = options.fontWeight;
|
|
1585
|
+
const keepCameraOn = options.keepCameraOn;
|
|
1586
|
+
const numWorkers = options.numWorkers;
|
|
1587
|
+
const progressCallback = options.progressCallback;
|
|
1588
|
+
const saveRenderingContexts = options.saveRenderingContexts;
|
|
1589
|
+
const savedRenderingContexts = options.savedRenderingContexts;
|
|
1590
|
+
const text = options.text;
|
|
1591
|
+
const textAlign = options.textAlign;
|
|
1592
|
+
const textBaseline = options.textBaseline;
|
|
1593
|
+
const videoElement = options.videoElement;
|
|
1594
|
+
const videoHeight = options.videoHeight;
|
|
1595
|
+
const videoWidth = options.videoWidth;
|
|
1596
|
+
const webcamVideoElement = options.webcamVideoElement;
|
|
1597
|
+
const gifWidth = Number(options.gifWidth);
|
|
1598
|
+
const gifHeight = Number(options.gifHeight);
|
|
1599
|
+
let interval = Number(options.interval);
|
|
1600
|
+
const sampleInterval = Number(options.sampleInterval);
|
|
1601
|
+
const waitBetweenFrames = hasExistingImages ? 0 : interval * 1000;
|
|
1602
|
+
const renderingContextsToSave = [];
|
|
1603
|
+
let numFrames = savedRenderingContexts.length ? savedRenderingContexts.length : options.numFrames;
|
|
1604
|
+
let pendingFrames = numFrames;
|
|
1605
|
+
const ag = new AnimatedGIF(options);
|
|
1606
|
+
const fontSize = utils.getFontSize(options);
|
|
1607
|
+
const textXCoordinate = options.textXCoordinate ? options.textXCoordinate : textAlign === 'left' ? 1 : textAlign === 'right' ? gifWidth : gifWidth / 2;
|
|
1608
|
+
const textYCoordinate = options.textYCoordinate ? options.textYCoordinate : textBaseline === 'top' ? 1 : textBaseline === 'center' ? gifHeight / 2 : gifHeight;
|
|
1609
|
+
const font = "".concat(fontWeight, " ").concat(fontSize, " ").concat(fontFamily);
|
|
1610
|
+
let sourceX = crop ? Math.floor(crop.scaledWidth / 2) : 0;
|
|
1611
|
+
let sourceWidth = crop ? videoWidth - crop.scaledWidth : 0;
|
|
1612
|
+
let sourceY = crop ? Math.floor(crop.scaledHeight / 2) : 0;
|
|
1613
|
+
let sourceHeight = crop ? videoHeight - crop.scaledHeight : 0;
|
|
1614
|
+
|
|
1615
|
+
const captureFrames = function captureSingleFrame() {
|
|
1616
|
+
const framesLeft = pendingFrames - 1;
|
|
1617
|
+
|
|
1618
|
+
if (savedRenderingContexts.length) {
|
|
1619
|
+
context.putImageData(savedRenderingContexts[numFrames - pendingFrames], 0, 0);
|
|
1620
|
+
finishCapture();
|
|
1621
|
+
} else {
|
|
1622
|
+
drawVideo();
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
function drawVideo() {
|
|
1626
|
+
try {
|
|
1627
|
+
if (sourceWidth > videoWidth) {
|
|
1628
|
+
sourceWidth = videoWidth;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
if (sourceHeight > videoHeight) {
|
|
1632
|
+
sourceHeight = videoHeight;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
if (sourceX < 0) {
|
|
1636
|
+
sourceX = 0;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
if (sourceY < 0) {
|
|
1640
|
+
sourceY = 0;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
context.filter = filter;
|
|
1644
|
+
context.drawImage(videoElement, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, gifWidth, gifHeight);
|
|
1645
|
+
finishCapture();
|
|
1646
|
+
} catch (e) {
|
|
1647
|
+
if (e.name === 'NS_ERROR_NOT_AVAILABLE') {
|
|
1648
|
+
utils.requestTimeout(drawVideo, 100);
|
|
1649
|
+
} else {
|
|
1650
|
+
throw e;
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
function finishCapture() {
|
|
1656
|
+
let imageData = void 0;
|
|
1657
|
+
|
|
1658
|
+
if (saveRenderingContexts) {
|
|
1659
|
+
renderingContextsToSave.push(context.getImageData(0, 0, gifWidth, gifHeight));
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
if (text) {
|
|
1663
|
+
context.font = font;
|
|
1664
|
+
context.fillStyle = fontColor;
|
|
1665
|
+
context.textAlign = textAlign;
|
|
1666
|
+
context.textBaseline = textBaseline;
|
|
1667
|
+
context.fillText(text, textXCoordinate, textYCoordinate);
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
imageData = context.getImageData(0, 0, gifWidth, gifHeight);
|
|
1671
|
+
ag.addFrameImageData(imageData);
|
|
1672
|
+
pendingFrames = framesLeft;
|
|
1673
|
+
progressCallback((numFrames - pendingFrames) / numFrames);
|
|
1674
|
+
|
|
1675
|
+
if (framesLeft > 0) {
|
|
1676
|
+
utils.requestTimeout(captureSingleFrame, waitBetweenFrames);
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
if (!pendingFrames) {
|
|
1680
|
+
ag.getBase64GIF(function (image) {
|
|
1681
|
+
callback({
|
|
1682
|
+
error: false,
|
|
1683
|
+
errorCode: '',
|
|
1684
|
+
errorMsg: '',
|
|
1685
|
+
image,
|
|
1686
|
+
cameraStream,
|
|
1687
|
+
videoElement,
|
|
1688
|
+
webcamVideoElement,
|
|
1689
|
+
savedRenderingContexts: renderingContextsToSave,
|
|
1690
|
+
keepCameraOn
|
|
1691
|
+
});
|
|
1692
|
+
});
|
|
1931
1693
|
}
|
|
1932
|
-
|
|
1694
|
+
}
|
|
1695
|
+
};
|
|
1696
|
+
|
|
1697
|
+
numFrames = numFrames !== undefined ? numFrames : 10;
|
|
1698
|
+
interval = interval !== undefined ? interval : 0.1;
|
|
1699
|
+
canvas.width = gifWidth;
|
|
1700
|
+
canvas.height = gifHeight;
|
|
1701
|
+
context = canvas.getContext('2d');
|
|
1702
|
+
|
|
1703
|
+
(function capture() {
|
|
1704
|
+
if (!savedRenderingContexts.length && videoElement.currentTime === 0) {
|
|
1705
|
+
utils.requestTimeout(capture, 100);
|
|
1706
|
+
return;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
captureFrames();
|
|
1710
|
+
})();
|
|
1711
|
+
},
|
|
1712
|
+
getCropDimensions: function getCropDimensions() {
|
|
1713
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1714
|
+
const width = obj.videoWidth;
|
|
1715
|
+
const height = obj.videoHeight;
|
|
1716
|
+
const gifWidth = obj.gifWidth;
|
|
1717
|
+
const gifHeight = obj.gifHeight;
|
|
1718
|
+
const result = {
|
|
1719
|
+
width: 0,
|
|
1720
|
+
height: 0,
|
|
1721
|
+
scaledWidth: 0,
|
|
1722
|
+
scaledHeight: 0
|
|
1723
|
+
};
|
|
1724
|
+
|
|
1725
|
+
if (width > height) {
|
|
1726
|
+
result.width = Math.round(width * (gifHeight / height)) - gifWidth;
|
|
1727
|
+
result.scaledWidth = Math.round(result.width * (height / gifHeight));
|
|
1728
|
+
} else {
|
|
1729
|
+
result.height = Math.round(height * (gifWidth / width)) - gifHeight;
|
|
1730
|
+
result.scaledHeight = Math.round(result.height * (width / gifWidth));
|
|
1933
1731
|
}
|
|
1732
|
+
|
|
1733
|
+
return result;
|
|
1734
|
+
}
|
|
1934
1735
|
};
|
|
1935
|
-
/*
|
|
1936
|
-
videoStream.js
|
|
1937
|
-
==============
|
|
1938
|
-
*/
|
|
1939
|
-
/* Copyright 2017 Yahoo Inc.
|
|
1940
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
1941
|
-
*/
|
|
1942
|
-
// Dependencies
|
|
1943
1736
|
var videoStream = {
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1737
|
+
loadedData: false,
|
|
1738
|
+
defaultVideoDimensions: {
|
|
1739
|
+
width: 640,
|
|
1740
|
+
height: 480
|
|
1741
|
+
},
|
|
1742
|
+
findVideoSize: function findVideoSizeMethod(obj) {
|
|
1743
|
+
findVideoSizeMethod.attempts = findVideoSizeMethod.attempts || 0;
|
|
1744
|
+
const cameraStream = obj.cameraStream;
|
|
1745
|
+
const completedCallback = obj.completedCallback;
|
|
1746
|
+
const videoElement = obj.videoElement;
|
|
1747
|
+
|
|
1748
|
+
if (!videoElement) {
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
if (videoElement.videoWidth > 0 && videoElement.videoHeight > 0) {
|
|
1753
|
+
videoElement.removeEventListener('loadeddata', videoStream.findVideoSize);
|
|
1754
|
+
completedCallback({
|
|
1755
|
+
videoElement,
|
|
1756
|
+
cameraStream,
|
|
1757
|
+
videoWidth: videoElement.videoWidth,
|
|
1758
|
+
videoHeight: videoElement.videoHeight
|
|
1759
|
+
});
|
|
1760
|
+
} else if (findVideoSizeMethod.attempts < 10) {
|
|
1761
|
+
findVideoSizeMethod.attempts += 1;
|
|
1762
|
+
utils.requestTimeout(function () {
|
|
1763
|
+
videoStream.findVideoSize(obj);
|
|
1764
|
+
}, 400);
|
|
1765
|
+
} else {
|
|
1766
|
+
completedCallback({
|
|
1767
|
+
videoElement,
|
|
1768
|
+
cameraStream,
|
|
1769
|
+
videoWidth: videoStream.defaultVideoDimensions.width,
|
|
1770
|
+
videoHeight: videoStream.defaultVideoDimensions.height
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
},
|
|
1774
|
+
onStreamingTimeout: function onStreamingTimeout(callback) {
|
|
1775
|
+
if (utils.isFunction(callback)) {
|
|
1776
|
+
callback({
|
|
1777
|
+
error: true,
|
|
1778
|
+
errorCode: 'getUserMedia',
|
|
1779
|
+
errorMsg: 'There was an issue with the getUserMedia API - Timed out while trying to start streaming',
|
|
1780
|
+
image: null,
|
|
1781
|
+
cameraStream: {}
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
},
|
|
1785
|
+
stream: function stream(obj) {
|
|
1786
|
+
const existingVideo = utils.isArray(obj.existingVideo) ? obj.existingVideo[0] : obj.existingVideo;
|
|
1787
|
+
const cameraStream = obj.cameraStream;
|
|
1788
|
+
const completedCallback = obj.completedCallback;
|
|
1789
|
+
const streamedCallback = obj.streamedCallback;
|
|
1790
|
+
const videoElement = obj.videoElement;
|
|
1791
|
+
|
|
1792
|
+
if (utils.isFunction(streamedCallback)) {
|
|
1793
|
+
streamedCallback();
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
if (existingVideo) {
|
|
1797
|
+
if (utils.isString(existingVideo)) {
|
|
1798
|
+
videoElement.src = existingVideo;
|
|
1799
|
+
videoElement.innerHTML = "<source src=\"".concat(existingVideo, "\" type=\"video/").concat(utils.getExtension(existingVideo), "\" />");
|
|
1800
|
+
} else if (existingVideo instanceof Blob) {
|
|
1801
|
+
try {
|
|
1802
|
+
videoElement.src = utils.URL.createObjectURL(existingVideo);
|
|
1803
|
+
} catch (e) {}
|
|
1804
|
+
|
|
1805
|
+
videoElement.innerHTML = "<source src=\"".concat(existingVideo, "\" type=\"").concat(existingVideo.type, "\" />");
|
|
1806
|
+
}
|
|
1807
|
+
} else if (videoElement.mozSrcObject) {
|
|
1808
|
+
videoElement.mozSrcObject = cameraStream;
|
|
1809
|
+
} else if (utils.URL) {
|
|
1810
|
+
try {
|
|
1811
|
+
videoElement.srcObject = cameraStream;
|
|
1812
|
+
videoElement.src = utils.URL.createObjectURL(cameraStream);
|
|
1813
|
+
} catch (e) {
|
|
1814
|
+
videoElement.srcObject = cameraStream;
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
videoElement.play();
|
|
1819
|
+
utils.requestTimeout(function checkLoadedData() {
|
|
1820
|
+
checkLoadedData.count = checkLoadedData.count || 0;
|
|
1821
|
+
|
|
1822
|
+
if (videoStream.loadedData === true) {
|
|
1823
|
+
videoStream.findVideoSize({
|
|
1824
|
+
videoElement,
|
|
1825
|
+
cameraStream,
|
|
1826
|
+
completedCallback
|
|
1827
|
+
});
|
|
1828
|
+
videoStream.loadedData = false;
|
|
1829
|
+
} else {
|
|
1830
|
+
checkLoadedData.count += 1;
|
|
1831
|
+
|
|
1832
|
+
if (checkLoadedData.count > 10) {
|
|
1833
|
+
videoStream.findVideoSize({
|
|
1834
|
+
videoElement,
|
|
1835
|
+
cameraStream,
|
|
1836
|
+
completedCallback
|
|
1837
|
+
});
|
|
1838
|
+
} else {
|
|
1839
|
+
checkLoadedData();
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
}, 0);
|
|
1843
|
+
},
|
|
1844
|
+
startStreaming: function startStreaming(obj) {
|
|
1845
|
+
const errorCallback = utils.isFunction(obj.error) ? obj.error : utils.noop;
|
|
1846
|
+
const streamedCallback = utils.isFunction(obj.streamed) ? obj.streamed : utils.noop;
|
|
1847
|
+
const completedCallback = utils.isFunction(obj.completed) ? obj.completed : utils.noop;
|
|
1848
|
+
const crossOrigin = obj.crossOrigin;
|
|
1849
|
+
const existingVideo = obj.existingVideo;
|
|
1850
|
+
const lastCameraStream = obj.lastCameraStream;
|
|
1851
|
+
const options = obj.options;
|
|
1852
|
+
const webcamVideoElement = obj.webcamVideoElement;
|
|
1853
|
+
const videoElement = utils.isElement(existingVideo) ? existingVideo : webcamVideoElement ? webcamVideoElement : document.createElement('video');
|
|
1854
|
+
const cameraStream = void 0;
|
|
1855
|
+
|
|
1856
|
+
if (crossOrigin) {
|
|
1857
|
+
videoElement.crossOrigin = options.crossOrigin;
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
videoElement.autoplay = true;
|
|
1861
|
+
videoElement.loop = true;
|
|
1862
|
+
videoElement.muted = true;
|
|
1863
|
+
videoElement.addEventListener('loadeddata', function (event) {
|
|
1864
|
+
videoStream.loadedData = true;
|
|
1865
|
+
|
|
1866
|
+
if (options.offset) {
|
|
1867
|
+
videoElement.currentTime = options.offset;
|
|
1868
|
+
}
|
|
1869
|
+
});
|
|
1870
|
+
|
|
1871
|
+
if (existingVideo) {
|
|
1872
|
+
videoStream.stream({
|
|
1873
|
+
videoElement,
|
|
1874
|
+
existingVideo,
|
|
1875
|
+
completedCallback
|
|
1876
|
+
});
|
|
1877
|
+
} else if (lastCameraStream) {
|
|
1878
|
+
videoStream.stream({
|
|
1879
|
+
videoElement,
|
|
1880
|
+
cameraStream: lastCameraStream,
|
|
1881
|
+
streamedCallback,
|
|
1882
|
+
completedCallback
|
|
1883
|
+
});
|
|
1884
|
+
} else {
|
|
1885
|
+
utils.getUserMedia({
|
|
1886
|
+
video: true
|
|
1887
|
+
}, function (stream) {
|
|
1888
|
+
videoStream.stream({
|
|
1889
|
+
videoElement,
|
|
1890
|
+
cameraStream: stream,
|
|
1891
|
+
streamedCallback,
|
|
1892
|
+
completedCallback
|
|
1893
|
+
});
|
|
1894
|
+
}, errorCallback);
|
|
1895
|
+
}
|
|
1896
|
+
},
|
|
1897
|
+
startVideoStreaming: function startVideoStreaming(callback) {
|
|
1898
|
+
const options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1899
|
+
const timeoutLength = options.timeout !== undefined ? options.timeout : 0;
|
|
1900
|
+
const originalCallback = options.callback;
|
|
1901
|
+
const webcamVideoElement = options.webcamVideoElement;
|
|
1902
|
+
let noGetUserMediaSupportTimeout = void 0;
|
|
1903
|
+
|
|
1904
|
+
if (timeoutLength > 0) {
|
|
1905
|
+
noGetUserMediaSupportTimeout = utils.requestTimeout(function () {
|
|
1906
|
+
videoStream.onStreamingTimeout(originalCallback);
|
|
1907
|
+
}, 10000);
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
videoStream.startStreaming({
|
|
1911
|
+
error: function error() {
|
|
1912
|
+
originalCallback({
|
|
1913
|
+
error: true,
|
|
1914
|
+
errorCode: 'getUserMedia',
|
|
1915
|
+
errorMsg: 'There was an issue with the getUserMedia API - the user probably denied permission',
|
|
1916
|
+
image: null,
|
|
1917
|
+
cameraStream: {}
|
|
1918
|
+
});
|
|
1919
|
+
},
|
|
1920
|
+
streamed: function streamed() {
|
|
1921
|
+
clearTimeout(noGetUserMediaSupportTimeout);
|
|
1922
|
+
},
|
|
1923
|
+
completed: function completed() {
|
|
1924
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1996
1925
|
const cameraStream = obj.cameraStream;
|
|
1997
|
-
const completedCallback = obj.completedCallback;
|
|
1998
|
-
const streamedCallback = obj.streamedCallback;
|
|
1999
1926
|
const videoElement = obj.videoElement;
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
}
|
|
2008
|
-
else if (existingVideo instanceof Blob) {
|
|
2009
|
-
try {
|
|
2010
|
-
videoElement.src = utils.URL.createObjectURL(existingVideo);
|
|
2011
|
-
}
|
|
2012
|
-
catch (e) { }
|
|
2013
|
-
videoElement.innerHTML = `<source src="${existingVideo}" type="${existingVideo.type}" />`;
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
else if (videoElement.mozSrcObject) {
|
|
2017
|
-
videoElement.mozSrcObject = cameraStream;
|
|
2018
|
-
}
|
|
2019
|
-
else if (utils.URL) {
|
|
2020
|
-
try {
|
|
2021
|
-
videoElement.srcObject = cameraStream;
|
|
2022
|
-
videoElement.src = utils.URL.createObjectURL(cameraStream);
|
|
2023
|
-
}
|
|
2024
|
-
catch (e) {
|
|
2025
|
-
videoElement.srcObject = cameraStream;
|
|
2026
|
-
}
|
|
2027
|
-
}
|
|
2028
|
-
videoElement.play();
|
|
2029
|
-
utils.requestTimeout(function checkLoadedData() {
|
|
2030
|
-
checkLoadedData.count = checkLoadedData.count || 0;
|
|
2031
|
-
if (videoStream.loadedData === true) {
|
|
2032
|
-
videoStream.findVideoSize({
|
|
2033
|
-
videoElement,
|
|
2034
|
-
cameraStream,
|
|
2035
|
-
completedCallback
|
|
2036
|
-
});
|
|
2037
|
-
videoStream.loadedData = false;
|
|
2038
|
-
}
|
|
2039
|
-
else {
|
|
2040
|
-
checkLoadedData.count += 1;
|
|
2041
|
-
if (checkLoadedData.count > 10) {
|
|
2042
|
-
videoStream.findVideoSize({
|
|
2043
|
-
videoElement,
|
|
2044
|
-
cameraStream,
|
|
2045
|
-
completedCallback
|
|
2046
|
-
});
|
|
2047
|
-
}
|
|
2048
|
-
else {
|
|
2049
|
-
checkLoadedData();
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2052
|
-
}, 0);
|
|
2053
|
-
},
|
|
2054
|
-
startStreaming: function startStreaming(obj) {
|
|
2055
|
-
const errorCallback = utils.isFunction(obj.error) ? obj.error : utils.noop;
|
|
2056
|
-
const streamedCallback = utils.isFunction(obj.streamed) ? obj.streamed : utils.noop;
|
|
2057
|
-
const completedCallback = utils.isFunction(obj.completed) ? obj.completed : utils.noop;
|
|
2058
|
-
const crossOrigin = obj.crossOrigin;
|
|
2059
|
-
const existingVideo = obj.existingVideo;
|
|
2060
|
-
const lastCameraStream = obj.lastCameraStream;
|
|
2061
|
-
const options = obj.options;
|
|
2062
|
-
const webcamVideoElement = obj.webcamVideoElement;
|
|
2063
|
-
const videoElement = utils.isElement(existingVideo)
|
|
2064
|
-
? existingVideo
|
|
2065
|
-
: webcamVideoElement
|
|
2066
|
-
? webcamVideoElement
|
|
2067
|
-
: document.createElement('video');
|
|
2068
|
-
const cameraStream = void 0;
|
|
2069
|
-
if (crossOrigin) {
|
|
2070
|
-
videoElement.crossOrigin = options.crossOrigin;
|
|
2071
|
-
}
|
|
2072
|
-
videoElement.autoplay = true;
|
|
2073
|
-
videoElement.loop = true;
|
|
2074
|
-
videoElement.muted = true;
|
|
2075
|
-
videoElement.addEventListener('loadeddata', function (event) {
|
|
2076
|
-
videoStream.loadedData = true;
|
|
2077
|
-
if (options.offset) {
|
|
2078
|
-
videoElement.currentTime = options.offset;
|
|
2079
|
-
}
|
|
2080
|
-
});
|
|
2081
|
-
if (existingVideo) {
|
|
2082
|
-
videoStream.stream({
|
|
2083
|
-
videoElement,
|
|
2084
|
-
existingVideo,
|
|
2085
|
-
completedCallback
|
|
2086
|
-
});
|
|
2087
|
-
}
|
|
2088
|
-
else if (lastCameraStream) {
|
|
2089
|
-
videoStream.stream({
|
|
2090
|
-
videoElement,
|
|
2091
|
-
cameraStream: lastCameraStream,
|
|
2092
|
-
streamedCallback,
|
|
2093
|
-
completedCallback
|
|
2094
|
-
});
|
|
2095
|
-
}
|
|
2096
|
-
else {
|
|
2097
|
-
utils.getUserMedia({
|
|
2098
|
-
video: true
|
|
2099
|
-
}, function (stream) {
|
|
2100
|
-
videoStream.stream({
|
|
2101
|
-
videoElement,
|
|
2102
|
-
cameraStream: stream,
|
|
2103
|
-
streamedCallback,
|
|
2104
|
-
completedCallback
|
|
2105
|
-
});
|
|
2106
|
-
}, errorCallback);
|
|
2107
|
-
}
|
|
2108
|
-
},
|
|
2109
|
-
startVideoStreaming: function startVideoStreaming(callback) {
|
|
2110
|
-
const options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
2111
|
-
const timeoutLength = options.timeout !== undefined ? options.timeout : 0;
|
|
2112
|
-
const originalCallback = options.callback;
|
|
2113
|
-
const webcamVideoElement = options.webcamVideoElement;
|
|
2114
|
-
let noGetUserMediaSupportTimeout = void 0;
|
|
2115
|
-
// Some browsers apparently have support for video streaming because of the
|
|
2116
|
-
// presence of the getUserMedia function, but then do not answer our
|
|
2117
|
-
// calls for streaming.
|
|
2118
|
-
// So we'll set up this timeout and if nothing happens after a while, we'll
|
|
2119
|
-
// conclude that there's no actual getUserMedia support.
|
|
2120
|
-
if (timeoutLength > 0) {
|
|
2121
|
-
noGetUserMediaSupportTimeout = utils.requestTimeout(function () {
|
|
2122
|
-
videoStream.onStreamingTimeout(originalCallback);
|
|
2123
|
-
}, 10000);
|
|
2124
|
-
}
|
|
2125
|
-
videoStream.startStreaming({
|
|
2126
|
-
error: function error() {
|
|
2127
|
-
originalCallback({
|
|
2128
|
-
error: true,
|
|
2129
|
-
errorCode: 'getUserMedia',
|
|
2130
|
-
errorMsg: 'There was an issue with the getUserMedia API - the user probably denied permission',
|
|
2131
|
-
image: null,
|
|
2132
|
-
cameraStream: {}
|
|
2133
|
-
});
|
|
2134
|
-
},
|
|
2135
|
-
streamed: function streamed() {
|
|
2136
|
-
// The streaming started somehow, so we can assume there is getUserMedia support
|
|
2137
|
-
clearTimeout(noGetUserMediaSupportTimeout);
|
|
2138
|
-
},
|
|
2139
|
-
completed: function completed() {
|
|
2140
|
-
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
2141
|
-
const cameraStream = obj.cameraStream;
|
|
2142
|
-
const videoElement = obj.videoElement;
|
|
2143
|
-
const videoHeight = obj.videoHeight;
|
|
2144
|
-
const videoWidth = obj.videoWidth;
|
|
2145
|
-
callback({
|
|
2146
|
-
cameraStream,
|
|
2147
|
-
videoElement,
|
|
2148
|
-
videoHeight,
|
|
2149
|
-
videoWidth
|
|
2150
|
-
});
|
|
2151
|
-
},
|
|
2152
|
-
lastCameraStream: options.lastCameraStream,
|
|
2153
|
-
webcamVideoElement,
|
|
2154
|
-
crossOrigin: options.crossOrigin,
|
|
2155
|
-
options
|
|
1927
|
+
const videoHeight = obj.videoHeight;
|
|
1928
|
+
const videoWidth = obj.videoWidth;
|
|
1929
|
+
callback({
|
|
1930
|
+
cameraStream,
|
|
1931
|
+
videoElement,
|
|
1932
|
+
videoHeight,
|
|
1933
|
+
videoWidth
|
|
2156
1934
|
});
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
1935
|
+
},
|
|
1936
|
+
lastCameraStream: options.lastCameraStream,
|
|
1937
|
+
webcamVideoElement,
|
|
1938
|
+
crossOrigin: options.crossOrigin,
|
|
1939
|
+
options
|
|
1940
|
+
});
|
|
1941
|
+
},
|
|
1942
|
+
stopVideoStreaming: function stopVideoStreaming(obj) {
|
|
1943
|
+
obj = utils.isObject(obj) ? obj : {};
|
|
1944
|
+
const _obj = obj;
|
|
1945
|
+
const keepCameraOn = _obj.keepCameraOn;
|
|
1946
|
+
const videoElement = _obj.videoElement;
|
|
1947
|
+
const webcamVideoElement = _obj.webcamVideoElement;
|
|
1948
|
+
const cameraStream = obj.cameraStream || {};
|
|
1949
|
+
const cameraStreamTracks = cameraStream.getTracks ? cameraStream.getTracks() || [] : [];
|
|
1950
|
+
const hasCameraStreamTracks = Boolean(cameraStreamTracks.length);
|
|
1951
|
+
const firstCameraStreamTrack = cameraStreamTracks[0];
|
|
1952
|
+
|
|
1953
|
+
if (!keepCameraOn && hasCameraStreamTracks) {
|
|
1954
|
+
if (utils.isFunction(firstCameraStreamTrack.stop)) {
|
|
1955
|
+
firstCameraStreamTrack.stop();
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
if (utils.isElement(videoElement) && !webcamVideoElement) {
|
|
1960
|
+
videoElement.pause();
|
|
1961
|
+
|
|
1962
|
+
if (utils.isFunction(utils.URL.revokeObjectURL) && !utils.webWorkerError) {
|
|
1963
|
+
if (videoElement.src) {
|
|
1964
|
+
utils.URL.revokeObjectURL(videoElement.src);
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
utils.removeElement(videoElement);
|
|
2186
1969
|
}
|
|
1970
|
+
}
|
|
2187
1971
|
};
|
|
2188
|
-
|
|
2189
|
-
stopVideoStreaming.js
|
|
2190
|
-
=====================
|
|
2191
|
-
*/
|
|
2192
|
-
/* Copyright 2017 Yahoo Inc.
|
|
2193
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
2194
|
-
*/
|
|
1972
|
+
|
|
2195
1973
|
function stopVideoStreaming(options) {
|
|
2196
|
-
|
|
2197
|
-
|
|
1974
|
+
options = utils.isObject(options) ? options : {};
|
|
1975
|
+
videoStream.stopVideoStreaming(options);
|
|
2198
1976
|
}
|
|
2199
|
-
|
|
2200
|
-
createAndGetGIF.js
|
|
2201
|
-
==================
|
|
2202
|
-
*/
|
|
2203
|
-
/* Copyright 2017 Yahoo Inc.
|
|
2204
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
2205
|
-
*/
|
|
2206
|
-
// Dependencies
|
|
1977
|
+
|
|
2207
1978
|
function createAndGetGIF(obj, callback) {
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
1979
|
+
const options = obj.options || {};
|
|
1980
|
+
const images = options.images;
|
|
1981
|
+
const video = options.video;
|
|
1982
|
+
const gifWidth = Number(options.gifWidth);
|
|
1983
|
+
const gifHeight = Number(options.gifHeight);
|
|
1984
|
+
const numFrames = Number(options.numFrames);
|
|
1985
|
+
const cameraStream = obj.cameraStream;
|
|
1986
|
+
const videoElement = obj.videoElement;
|
|
1987
|
+
const videoWidth = obj.videoWidth;
|
|
1988
|
+
const videoHeight = obj.videoHeight;
|
|
1989
|
+
const cropDimensions = screenShot.getCropDimensions({
|
|
1990
|
+
videoWidth,
|
|
1991
|
+
videoHeight,
|
|
1992
|
+
gifHeight,
|
|
1993
|
+
gifWidth
|
|
1994
|
+
});
|
|
1995
|
+
const completeCallback = callback;
|
|
1996
|
+
options.crop = cropDimensions;
|
|
1997
|
+
options.videoElement = videoElement;
|
|
1998
|
+
options.videoWidth = videoWidth;
|
|
1999
|
+
options.videoHeight = videoHeight;
|
|
2000
|
+
options.cameraStream = cameraStream;
|
|
2001
|
+
|
|
2002
|
+
if (!utils.isElement(videoElement)) {
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
videoElement.width = gifWidth + cropDimensions.width;
|
|
2007
|
+
videoElement.height = gifHeight + cropDimensions.height;
|
|
2008
|
+
|
|
2009
|
+
if (!options.webcamVideoElement) {
|
|
2010
|
+
utils.setCSSAttr(videoElement, {
|
|
2011
|
+
position: 'fixed',
|
|
2012
|
+
opacity: '0'
|
|
2223
2013
|
});
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
return;
|
|
2014
|
+
document.body.appendChild(videoElement);
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
videoElement.play();
|
|
2018
|
+
screenShot.getGIF(options, function (obj) {
|
|
2019
|
+
if ((!images || !images.length) && (!video || !video.length)) {
|
|
2020
|
+
stopVideoStreaming(obj);
|
|
2232
2021
|
}
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
utils.setCSSAttr(videoElement, {
|
|
2237
|
-
position: 'fixed',
|
|
2238
|
-
opacity: '0'
|
|
2239
|
-
});
|
|
2240
|
-
document.body.appendChild(videoElement);
|
|
2241
|
-
}
|
|
2242
|
-
// Firefox doesn't seem to obey autoplay if the element is not in the DOM when the content
|
|
2243
|
-
// is loaded, so we must manually trigger play after adding it, or the video will be frozen
|
|
2244
|
-
videoElement.play();
|
|
2245
|
-
screenShot.getGIF(options, function (obj) {
|
|
2246
|
-
if ((!images || !images.length) && (!video || !video.length)) {
|
|
2247
|
-
stopVideoStreaming(obj);
|
|
2248
|
-
}
|
|
2249
|
-
completeCallback(obj);
|
|
2250
|
-
});
|
|
2022
|
+
|
|
2023
|
+
completeCallback(obj);
|
|
2024
|
+
});
|
|
2251
2025
|
}
|
|
2252
|
-
|
|
2253
|
-
existingVideo.js
|
|
2254
|
-
================
|
|
2255
|
-
*/
|
|
2256
|
-
/* Copyright 2017 Yahoo Inc.
|
|
2257
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
2258
|
-
*/
|
|
2259
|
-
// Dependencies
|
|
2026
|
+
|
|
2260
2027
|
function existingVideo() {
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
utils.each(existingVideo, function (iterator, videoSrc) {
|
|
2287
|
-
if (videoSrc instanceof Blob) {
|
|
2288
|
-
videoType = videoSrc.type.substr(videoSrc.type.lastIndexOf('/') + 1, videoSrc.length);
|
|
2289
|
-
}
|
|
2290
|
-
else {
|
|
2291
|
-
videoType = videoSrc.substr(videoSrc.lastIndexOf('.') + 1, videoSrc.length);
|
|
2292
|
-
}
|
|
2293
|
-
if (utils.isSupported.videoCodecs[videoType]) {
|
|
2294
|
-
existingVideo = videoSrc;
|
|
2295
|
-
return false;
|
|
2296
|
-
}
|
|
2297
|
-
});
|
|
2028
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
2029
|
+
const callback = obj.callback;
|
|
2030
|
+
let existingVideo = obj.existingVideo;
|
|
2031
|
+
const options = obj.options;
|
|
2032
|
+
const skipObj = {
|
|
2033
|
+
getUserMedia: true,
|
|
2034
|
+
'window.URL': true
|
|
2035
|
+
};
|
|
2036
|
+
const errorObj = error.validate(skipObj);
|
|
2037
|
+
const loadedImages = 0;
|
|
2038
|
+
let videoType = void 0;
|
|
2039
|
+
let videoSrc = void 0;
|
|
2040
|
+
const tempImage = void 0;
|
|
2041
|
+
const ag = void 0;
|
|
2042
|
+
|
|
2043
|
+
if (errorObj.error) {
|
|
2044
|
+
return callback(errorObj);
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
if (utils.isElement(existingVideo) && existingVideo.src) {
|
|
2048
|
+
videoSrc = existingVideo.src;
|
|
2049
|
+
videoType = utils.getExtension(videoSrc);
|
|
2050
|
+
|
|
2051
|
+
if (!utils.isSupported.videoCodecs[videoType]) {
|
|
2052
|
+
return callback(error.messages.videoCodecs);
|
|
2298
2053
|
}
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2054
|
+
} else if (utils.isArray(existingVideo)) {
|
|
2055
|
+
utils.each(existingVideo, function (iterator, videoSrc) {
|
|
2056
|
+
if (videoSrc instanceof Blob) {
|
|
2057
|
+
videoType = videoSrc.type.substr(videoSrc.type.lastIndexOf('/') + 1, videoSrc.length);
|
|
2058
|
+
} else {
|
|
2059
|
+
videoType = videoSrc.substr(videoSrc.lastIndexOf('.') + 1, videoSrc.length);
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
if (utils.isSupported.videoCodecs[videoType]) {
|
|
2063
|
+
existingVideo = videoSrc;
|
|
2064
|
+
return false;
|
|
2065
|
+
}
|
|
2307
2066
|
});
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
videoStream.startStreaming({
|
|
2070
|
+
completed: function completed(obj) {
|
|
2071
|
+
obj.options = options || {};
|
|
2072
|
+
createAndGetGIF(obj, callback);
|
|
2073
|
+
},
|
|
2074
|
+
existingVideo,
|
|
2075
|
+
crossOrigin: options.crossOrigin,
|
|
2076
|
+
options
|
|
2077
|
+
});
|
|
2308
2078
|
}
|
|
2309
|
-
|
|
2310
|
-
existingWebcam.js
|
|
2311
|
-
=================
|
|
2312
|
-
*/
|
|
2313
|
-
/* Copyright 2017 Yahoo Inc.
|
|
2314
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
2315
|
-
*/
|
|
2316
|
-
// Dependencies
|
|
2079
|
+
|
|
2317
2080
|
function existingWebcam() {
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
}
|
|
2332
|
-
videoStream.startVideoStreaming(function () {
|
|
2333
|
-
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
2334
|
-
obj.options = options || {};
|
|
2335
|
-
createAndGetGIF(obj, callback);
|
|
2336
|
-
}, {
|
|
2337
|
-
lastCameraStream,
|
|
2338
|
-
callback,
|
|
2339
|
-
webcamVideoElement,
|
|
2340
|
-
crossOrigin: options.crossOrigin
|
|
2081
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
2082
|
+
const callback = obj.callback;
|
|
2083
|
+
const lastCameraStream = obj.lastCameraStream;
|
|
2084
|
+
const options = obj.options;
|
|
2085
|
+
const webcamVideoElement = obj.webcamVideoElement;
|
|
2086
|
+
|
|
2087
|
+
if (!isWebCamGIFSupported()) {
|
|
2088
|
+
return callback(error.validate());
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
if (options.savedRenderingContexts.length) {
|
|
2092
|
+
screenShot.getGIF(options, function (obj) {
|
|
2093
|
+
callback(obj);
|
|
2341
2094
|
});
|
|
2095
|
+
return;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
videoStream.startVideoStreaming(function () {
|
|
2099
|
+
const obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
2100
|
+
obj.options = options || {};
|
|
2101
|
+
createAndGetGIF(obj, callback);
|
|
2102
|
+
}, {
|
|
2103
|
+
lastCameraStream,
|
|
2104
|
+
callback,
|
|
2105
|
+
webcamVideoElement,
|
|
2106
|
+
crossOrigin: options.crossOrigin
|
|
2107
|
+
});
|
|
2342
2108
|
}
|
|
2343
|
-
|
|
2344
|
-
createGIF.js
|
|
2345
|
-
============
|
|
2346
|
-
*/
|
|
2347
|
-
/* Copyright 2017 Yahoo Inc.
|
|
2348
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
2349
|
-
*/
|
|
2350
|
-
// Dependencies
|
|
2109
|
+
|
|
2351
2110
|
function createGIF(userOptions, callback) {
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2111
|
+
callback = utils.isFunction(userOptions) ? userOptions : callback;
|
|
2112
|
+
userOptions = utils.isObject(userOptions) ? userOptions : {};
|
|
2113
|
+
|
|
2114
|
+
if (!utils.isFunction(callback)) {
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
let options = utils.normalizeOptions(defaultOptions, userOptions) || {};
|
|
2119
|
+
const lastCameraStream = userOptions.cameraStream;
|
|
2120
|
+
const images = options.images;
|
|
2121
|
+
const imagesLength = images ? images.length : 0;
|
|
2122
|
+
const video = options.video;
|
|
2123
|
+
const webcamVideoElement = options.webcamVideoElement;
|
|
2124
|
+
options = utils.normalizeOptions(options, {
|
|
2125
|
+
gifWidth: Math.floor(options.gifWidth),
|
|
2126
|
+
gifHeight: Math.floor(options.gifHeight)
|
|
2127
|
+
});
|
|
2128
|
+
|
|
2129
|
+
if (imagesLength) {
|
|
2130
|
+
existingImages({
|
|
2131
|
+
images,
|
|
2132
|
+
imagesLength,
|
|
2133
|
+
callback,
|
|
2134
|
+
options
|
|
2366
2135
|
});
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
options
|
|
2382
|
-
});
|
|
2383
|
-
}
|
|
2384
|
-
else {
|
|
2385
|
-
// If the user would like to create a GIF from a webcam stream
|
|
2386
|
-
existingWebcam({
|
|
2387
|
-
lastCameraStream,
|
|
2388
|
-
callback,
|
|
2389
|
-
webcamVideoElement,
|
|
2390
|
-
options
|
|
2391
|
-
});
|
|
2392
|
-
}
|
|
2136
|
+
} else if (video) {
|
|
2137
|
+
existingVideo({
|
|
2138
|
+
existingVideo: video,
|
|
2139
|
+
callback,
|
|
2140
|
+
options
|
|
2141
|
+
});
|
|
2142
|
+
} else {
|
|
2143
|
+
existingWebcam({
|
|
2144
|
+
lastCameraStream,
|
|
2145
|
+
callback,
|
|
2146
|
+
webcamVideoElement,
|
|
2147
|
+
options
|
|
2148
|
+
});
|
|
2149
|
+
}
|
|
2393
2150
|
}
|
|
2394
|
-
|
|
2395
|
-
takeSnapShot.js
|
|
2396
|
-
===============
|
|
2397
|
-
*/
|
|
2398
|
-
/* Copyright 2017 Yahoo Inc.
|
|
2399
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
2400
|
-
*/
|
|
2151
|
+
|
|
2401
2152
|
function takeSnapShot(userOptions, callback) {
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2153
|
+
callback = utils.isFunction(userOptions) ? userOptions : callback;
|
|
2154
|
+
userOptions = utils.isObject(userOptions) ? userOptions : {};
|
|
2155
|
+
|
|
2156
|
+
if (!utils.isFunction(callback)) {
|
|
2157
|
+
return;
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
const mergedOptions = utils.normalizeOptions(defaultOptions, userOptions);
|
|
2161
|
+
const options = utils.normalizeOptions(mergedOptions, {
|
|
2162
|
+
interval: 0.1,
|
|
2163
|
+
numFrames: 1,
|
|
2164
|
+
gifWidth: Math.floor(mergedOptions.gifWidth),
|
|
2165
|
+
gifHeight: Math.floor(mergedOptions.gifHeight)
|
|
2166
|
+
});
|
|
2167
|
+
createGIF(options, callback);
|
|
2415
2168
|
}
|
|
2416
|
-
|
|
2417
|
-
API.js
|
|
2418
|
-
======
|
|
2419
|
-
*/
|
|
2420
|
-
/* Copyright 2017 Yahoo Inc.
|
|
2421
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
2422
|
-
*/
|
|
2423
|
-
// Dependencies
|
|
2169
|
+
|
|
2424
2170
|
const API = {
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2171
|
+
utils: utils$2,
|
|
2172
|
+
error: error$2,
|
|
2173
|
+
defaultOptions: defaultOptions$2,
|
|
2174
|
+
createGIF,
|
|
2175
|
+
takeSnapShot,
|
|
2176
|
+
stopVideoStreaming,
|
|
2177
|
+
isSupported,
|
|
2178
|
+
isWebCamGIFSupported,
|
|
2179
|
+
isExistingVideoGIFSupported,
|
|
2180
|
+
isExistingImagesGIFSupported: isSupported$1,
|
|
2181
|
+
VERSION: '0.4.5'
|
|
2436
2182
|
};
|
|
2437
|
-
|
|
2183
|
+
export default API;
|
|
2184
|
+
//# sourceMappingURL=gifshot.js.map
|