@jsenv/terminal-recorder 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,510 @@
1
+ /* eslint-disable */
2
+
3
+ /*
4
+ * NeuQuant Neural-Net Quantization Algorithm
5
+ * ------------------------------------------
6
+ *
7
+ * Copyright (c) 1994 Anthony Dekker
8
+ *
9
+ * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See
10
+ * "Kohonen neural networks for optimal colour quantization" in "Network:
11
+ * Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of
12
+ * the algorithm.
13
+ *
14
+ * Any party obtaining a copy of these files from the author, directly or
15
+ * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
16
+ * world-wide, paid up, royalty-free, nonexclusive right and license to deal in
17
+ * this software and documentation files (the "Software"), including without
18
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
19
+ * sublicense, and/or sell copies of the Software, and to permit persons who
20
+ * receive copies from any such party to do so, with the only requirement being
21
+ * that this copyright notice remain intact.
22
+ */
23
+
24
+ /*
25
+ * This class handles Neural-Net quantization algorithm
26
+ * @author Kevin Weiner (original Java version - kweiner@fmsware.com)
27
+ * @author Thibault Imbert (AS3 version - bytearray.org)
28
+ * @author Kevin Kwok (JavaScript version - https://github.com/antimatter15/jsgif)
29
+ * @version 0.1 AS3 implementation
30
+ */
31
+
32
+ NeuQuant = function () {
33
+ var exports = {};
34
+ var netsize = 256; /* number of colours used */
35
+
36
+ /* four primes near 500 - assume no image has a length so large */
37
+ /* that it is divisible by all four primes */
38
+
39
+ var prime1 = 499;
40
+ var prime2 = 491;
41
+ var prime3 = 487;
42
+ var prime4 = 503;
43
+ var minpicturebytes = 3 * prime4; /* minimum size for input image */
44
+
45
+ /*
46
+ * Program Skeleton ---------------- [select samplefac in range 1..30] [read
47
+ * image from input file] pic = (unsigned char*) malloc(3*width*height);
48
+ * initnet(pic,3*width*height,samplefac); learn(); unbiasnet(); [write output
49
+ * image header, using writecolourmap(f)] inxbuild(); write output image using
50
+ * inxsearch(b,g,r)
51
+ */
52
+
53
+ /*
54
+ * Network Definitions -------------------
55
+ */
56
+
57
+ var maxnetpos = netsize - 1;
58
+ var netbiasshift = 4; /* bias for colour values */
59
+ var ncycles = 100; /* no. of learning cycles */
60
+
61
+ /* defs for freq and bias */
62
+ var intbiasshift = 16; /* bias for fractions */
63
+ var intbias = 1 << intbiasshift;
64
+ var gammashift = 10; /* gamma = 1024 */
65
+ var gamma = 1 << gammashift;
66
+ var betashift = 10;
67
+ var beta = intbias >> betashift; /* beta = 1/1024 */
68
+ var betagamma = intbias << (gammashift - betashift);
69
+
70
+ /* defs for decreasing radius factor */
71
+ var initrad = netsize >> 3; /* for 256 cols, radius starts */
72
+ var radiusbiasshift = 6; /* at 32.0 biased by 6 bits */
73
+ var radiusbias = 1 << radiusbiasshift;
74
+ var initradius = initrad * radiusbias; /* and decreases by a */
75
+ var radiusdec = 30; /* factor of 1/30 each cycle */
76
+
77
+ /* defs for decreasing alpha factor */
78
+ var alphabiasshift = 10; /* alpha starts at 1.0 */
79
+ var initalpha = 1 << alphabiasshift;
80
+ var alphadec; /* biased by 10 bits */
81
+
82
+ /* radbias and alpharadbias used for radpower calculation */
83
+ var radbiasshift = 8;
84
+ var radbias = 1 << radbiasshift;
85
+ var alpharadbshift = alphabiasshift + radbiasshift;
86
+ var alpharadbias = 1 << alpharadbshift;
87
+
88
+ /*
89
+ * Types and Global Variables --------------------------
90
+ */
91
+
92
+ var thepicture; /* the input image itself */
93
+ var lengthcount; /* lengthcount = H*W*3 */
94
+ var samplefac; /* sampling factor 1..30 */
95
+
96
+ // typedef int pixel[4]; /* BGRc */
97
+ var network; /* the network itself - [netsize][4] */
98
+ var netindex = [];
99
+
100
+ /* for network lookup - really 256 */
101
+ var bias = [];
102
+
103
+ /* bias and freq arrays for learning */
104
+ var freq = [];
105
+ var radpower = [];
106
+
107
+ var NeuQuant = (exports.NeuQuant = function NeuQuant(thepic, len, sample) {
108
+ var i;
109
+ var p;
110
+
111
+ thepicture = thepic;
112
+ lengthcount = len;
113
+ samplefac = sample;
114
+
115
+ network = new Array(netsize);
116
+
117
+ for (i = 0; i < netsize; i++) {
118
+ network[i] = new Array(4);
119
+ p = network[i];
120
+ p[0] = p[1] = p[2] = (i << (netbiasshift + 8)) / netsize;
121
+ freq[i] = intbias / netsize; /* 1/netsize */
122
+ bias[i] = 0;
123
+ }
124
+ });
125
+
126
+ var colorMap = function colorMap() {
127
+ var map = [];
128
+ var index = new Array(netsize);
129
+
130
+ for (var i = 0; i < netsize; i++) index[network[i][3]] = i;
131
+
132
+ var k = 0;
133
+ for (var l = 0; l < netsize; l++) {
134
+ var j = index[l];
135
+ map[k++] = network[j][0];
136
+ map[k++] = network[j][1];
137
+ map[k++] = network[j][2];
138
+ }
139
+
140
+ return map;
141
+ };
142
+
143
+ /*
144
+ * Insertion sort of network and building of netindex[0..255] (to do after
145
+ * unbias)
146
+ * -------------------------------------------------------------------------------
147
+ */
148
+
149
+ var inxbuild = function inxbuild() {
150
+ var i;
151
+ var j;
152
+ var smallpos;
153
+ var smallval;
154
+ var p;
155
+ var q;
156
+ var previouscol;
157
+ var startpos;
158
+
159
+ previouscol = 0;
160
+ startpos = 0;
161
+ for (i = 0; i < netsize; i++) {
162
+ p = network[i];
163
+ smallpos = i;
164
+ smallval = p[1]; /* index on g */
165
+
166
+ /* find smallest in i..netsize-1 */
167
+ for (j = i + 1; j < netsize; j++) {
168
+ q = network[j];
169
+ if (q[1] < smallval) {
170
+ /* index on g */
171
+ smallpos = j;
172
+ smallval = q[1]; /* index on g */
173
+ }
174
+ }
175
+ q = network[smallpos];
176
+
177
+ /* swap p (i) and q (smallpos) entries */
178
+ if (i != smallpos) {
179
+ j = q[0];
180
+ q[0] = p[0];
181
+ p[0] = j;
182
+ j = q[1];
183
+ q[1] = p[1];
184
+ p[1] = j;
185
+ j = q[2];
186
+ q[2] = p[2];
187
+ p[2] = j;
188
+ j = q[3];
189
+ q[3] = p[3];
190
+ p[3] = j;
191
+ }
192
+
193
+ /* smallval entry is now in position i */
194
+
195
+ if (smallval != previouscol) {
196
+ netindex[previouscol] = (startpos + i) >> 1;
197
+
198
+ for (j = previouscol + 1; j < smallval; j++) netindex[j] = i;
199
+
200
+ previouscol = smallval;
201
+ startpos = i;
202
+ }
203
+ }
204
+
205
+ netindex[previouscol] = (startpos + maxnetpos) >> 1;
206
+ for (j = previouscol + 1; j < 256; j++)
207
+ netindex[j] = maxnetpos; /* really 256 */
208
+ };
209
+
210
+ /*
211
+ * Main Learning Loop ------------------
212
+ */
213
+
214
+ var learn = function learn() {
215
+ var i;
216
+ var j;
217
+ var b;
218
+ var g;
219
+ var r;
220
+ var radius;
221
+ var rad;
222
+ var alpha;
223
+ var step;
224
+ var delta;
225
+ var samplepixels;
226
+ var p;
227
+ var pix;
228
+ var lim;
229
+
230
+ if (lengthcount < minpicturebytes) samplefac = 1;
231
+
232
+ alphadec = 30 + (samplefac - 1) / 3;
233
+ p = thepicture;
234
+ pix = 0;
235
+ lim = lengthcount;
236
+ samplepixels = lengthcount / (3 * samplefac);
237
+ delta = (samplepixels / ncycles) | 0;
238
+ alpha = initalpha;
239
+ radius = initradius;
240
+
241
+ rad = radius >> radiusbiasshift;
242
+ if (rad <= 1) rad = 0;
243
+
244
+ for (i = 0; i < rad; i++)
245
+ radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad));
246
+
247
+ if (lengthcount < minpicturebytes) step = 3;
248
+ else if (lengthcount % prime1 !== 0) step = 3 * prime1;
249
+ else {
250
+ if (lengthcount % prime2 !== 0) step = 3 * prime2;
251
+ else {
252
+ if (lengthcount % prime3 !== 0) step = 3 * prime3;
253
+ else step = 3 * prime4;
254
+ }
255
+ }
256
+
257
+ i = 0;
258
+ while (i < samplepixels) {
259
+ b = (p[pix + 0] & 0xff) << netbiasshift;
260
+ g = (p[pix + 1] & 0xff) << netbiasshift;
261
+ r = (p[pix + 2] & 0xff) << netbiasshift;
262
+ j = contest(b, g, r);
263
+
264
+ altersingle(alpha, j, b, g, r);
265
+ if (rad !== 0) alterneigh(rad, j, b, g, r); /* alter neighbours */
266
+
267
+ pix += step;
268
+ if (pix >= lim) pix -= lengthcount;
269
+
270
+ i++;
271
+
272
+ if (delta === 0) delta = 1;
273
+
274
+ if (i % delta === 0) {
275
+ alpha -= alpha / alphadec;
276
+ radius -= radius / radiusdec;
277
+ rad = radius >> radiusbiasshift;
278
+
279
+ if (rad <= 1) rad = 0;
280
+
281
+ for (j = 0; j < rad; j++)
282
+ radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad));
283
+ }
284
+ }
285
+ };
286
+
287
+ /*
288
+ ** Search for BGR values 0..255 (after net is unbiased) and return colour
289
+ * index
290
+ * ----------------------------------------------------------------------------
291
+ */
292
+
293
+ var map = (exports.map = function map(b, g, r) {
294
+ var i;
295
+ var j;
296
+ var dist;
297
+ var a;
298
+ var bestd;
299
+ var p;
300
+ var best;
301
+
302
+ bestd = 1000; /* biggest possible dist is 256*3 */
303
+ best = -1;
304
+ i = netindex[g]; /* index on g */
305
+ j = i - 1; /* start at netindex[g] and work outwards */
306
+
307
+ while (i < netsize || j >= 0) {
308
+ if (i < netsize) {
309
+ p = network[i];
310
+ dist = p[1] - g; /* inx key */
311
+
312
+ if (dist >= bestd) i = netsize; /* stop iter */
313
+ else {
314
+ i++;
315
+ if (dist < 0) dist = -dist;
316
+ a = p[0] - b;
317
+ if (a < 0) a = -a;
318
+ dist += a;
319
+
320
+ if (dist < bestd) {
321
+ a = p[2] - r;
322
+ if (a < 0) a = -a;
323
+ dist += a;
324
+
325
+ if (dist < bestd) {
326
+ bestd = dist;
327
+ best = p[3];
328
+ }
329
+ }
330
+ }
331
+ }
332
+
333
+ if (j >= 0) {
334
+ p = network[j];
335
+ dist = g - p[1]; /* inx key - reverse dif */
336
+
337
+ if (dist >= bestd) j = -1; /* stop iter */
338
+ else {
339
+ j--;
340
+ if (dist < 0) dist = -dist;
341
+ a = p[0] - b;
342
+ if (a < 0) a = -a;
343
+ dist += a;
344
+
345
+ if (dist < bestd) {
346
+ a = p[2] - r;
347
+ if (a < 0) a = -a;
348
+ dist += a;
349
+ if (dist < bestd) {
350
+ bestd = dist;
351
+ best = p[3];
352
+ }
353
+ }
354
+ }
355
+ }
356
+ }
357
+
358
+ return best;
359
+ });
360
+
361
+ var process = (exports.process = function process() {
362
+ learn();
363
+ unbiasnet();
364
+ inxbuild();
365
+ return colorMap();
366
+ });
367
+
368
+ /*
369
+ * Unbias network to give byte values 0..255 and record position i to prepare
370
+ * for sort
371
+ * -----------------------------------------------------------------------------------
372
+ */
373
+
374
+ var unbiasnet = function unbiasnet() {
375
+ var i;
376
+ var j;
377
+
378
+ for (i = 0; i < netsize; i++) {
379
+ network[i][0] >>= netbiasshift;
380
+ network[i][1] >>= netbiasshift;
381
+ network[i][2] >>= netbiasshift;
382
+ network[i][3] = i; /* record colour no */
383
+ }
384
+ };
385
+
386
+ /*
387
+ * Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in
388
+ * radpower[|i-j|]
389
+ * ---------------------------------------------------------------------------------
390
+ */
391
+
392
+ var alterneigh = function alterneigh(rad, i, b, g, r) {
393
+ var j;
394
+ var k;
395
+ var lo;
396
+ var hi;
397
+ var a;
398
+ var m;
399
+ var p;
400
+
401
+ lo = i - rad;
402
+ if (lo < -1) lo = -1;
403
+
404
+ hi = i + rad;
405
+ if (hi > netsize) hi = netsize;
406
+
407
+ j = i + 1;
408
+ k = i - 1;
409
+ m = 1;
410
+
411
+ while (j < hi || k > lo) {
412
+ a = radpower[m++];
413
+
414
+ if (j < hi) {
415
+ p = network[j++];
416
+
417
+ try {
418
+ p[0] -= (a * (p[0] - b)) / alpharadbias;
419
+ p[1] -= (a * (p[1] - g)) / alpharadbias;
420
+ p[2] -= (a * (p[2] - r)) / alpharadbias;
421
+ } catch (e) {} // prevents 1.3 miscompilation
422
+ }
423
+
424
+ if (k > lo) {
425
+ p = network[k--];
426
+
427
+ try {
428
+ p[0] -= (a * (p[0] - b)) / alpharadbias;
429
+ p[1] -= (a * (p[1] - g)) / alpharadbias;
430
+ p[2] -= (a * (p[2] - r)) / alpharadbias;
431
+ } catch (e) {}
432
+ }
433
+ }
434
+ };
435
+
436
+ /*
437
+ * Move neuron i towards biased (b,g,r) by factor alpha
438
+ * ----------------------------------------------------
439
+ */
440
+
441
+ var altersingle = function altersingle(alpha, i, b, g, r) {
442
+ /* alter hit neuron */
443
+ var n = network[i];
444
+ n[0] -= (alpha * (n[0] - b)) / initalpha;
445
+ n[1] -= (alpha * (n[1] - g)) / initalpha;
446
+ n[2] -= (alpha * (n[2] - r)) / initalpha;
447
+ };
448
+
449
+ /*
450
+ * Search for biased BGR values ----------------------------
451
+ */
452
+
453
+ var contest = function contest(b, g, r) {
454
+ /* finds closest neuron (min dist) and updates freq */
455
+ /* finds best neuron (min dist-bias) and returns position */
456
+ /* for frequently chosen neurons, freq[i] is high and bias[i] is negative */
457
+ /* bias[i] = gamma*((1/netsize)-freq[i]) */
458
+
459
+ var i;
460
+ var dist;
461
+ var a;
462
+ var biasdist;
463
+ var betafreq;
464
+ var bestpos;
465
+ var bestbiaspos;
466
+ var bestd;
467
+ var bestbiasd;
468
+ var n;
469
+
470
+ bestd = ~(1 << 31);
471
+ bestbiasd = bestd;
472
+ bestpos = -1;
473
+ bestbiaspos = bestpos;
474
+
475
+ for (i = 0; i < netsize; i++) {
476
+ n = network[i];
477
+ dist = n[0] - b;
478
+ if (dist < 0) dist = -dist;
479
+ a = n[1] - g;
480
+ if (a < 0) a = -a;
481
+ dist += a;
482
+ a = n[2] - r;
483
+ if (a < 0) a = -a;
484
+ dist += a;
485
+
486
+ if (dist < bestd) {
487
+ bestd = dist;
488
+ bestpos = i;
489
+ }
490
+
491
+ biasdist = dist - (bias[i] >> (intbiasshift - netbiasshift));
492
+
493
+ if (biasdist < bestbiasd) {
494
+ bestbiasd = biasdist;
495
+ bestbiaspos = i;
496
+ }
497
+
498
+ betafreq = freq[i] >> betashift;
499
+ freq[i] -= betafreq;
500
+ bias[i] += betafreq << gammashift;
501
+ }
502
+
503
+ freq[bestpos] += beta;
504
+ bias[bestpos] -= betagamma;
505
+ return bestbiaspos;
506
+ };
507
+
508
+ NeuQuant.apply(this, arguments);
509
+ return exports;
510
+ };
@@ -0,0 +1,94 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>Title</title>
5
+ <meta charset="utf-8" />
6
+ <link rel="icon" href="data:," />
7
+ </head>
8
+
9
+ <body>
10
+ <div style="display: flex">
11
+ <canvas id="canvas"></canvas>
12
+ <img src="data:," />
13
+ </div>
14
+ <script type="module">
15
+ import { createGifEncoder } from "../gif_encoder.js";
16
+
17
+ const width = 100;
18
+ const height = 200;
19
+ const canvas = document.querySelector("canvas");
20
+ const context = canvas.getContext("2d", { willReadFrequently: true });
21
+ canvas.width = width;
22
+ canvas.height = height;
23
+
24
+ const encoder = createGifEncoder({
25
+ width: canvas.width,
26
+ height: canvas.height,
27
+ repeat: 0,
28
+ quality: 16, // [1,30] | Best=1 | >20 not much speed improvement. 10 is default.
29
+ });
30
+
31
+ const updateCanvasColor = (color) => {
32
+ drawRectangle(context, {
33
+ x: 0,
34
+ y: 0,
35
+ width: canvas.width,
36
+ height: canvas.height,
37
+ fill: color,
38
+ });
39
+ };
40
+
41
+ const addFrame = (delayBeforeDisplayingNextFrameInMs) => {
42
+ encoder.addFrame(context, {
43
+ delay: delayBeforeDisplayingNextFrameInMs,
44
+ });
45
+ };
46
+
47
+ const drawRectangle = (
48
+ context,
49
+ { x, y, width, height, radius, fill, stroke, strokeWidth },
50
+ ) => {
51
+ if (radius) {
52
+ context.beginPath();
53
+ context.roundRect(x, y, width, height, [radius]);
54
+ if (fill) {
55
+ context.fillStyle = fill;
56
+ context.fill();
57
+ }
58
+ if (stroke) {
59
+ context.strokeWidth = strokeWidth;
60
+ context.strokeStyle = stroke;
61
+ context.stroke();
62
+ }
63
+ return;
64
+ }
65
+ context.beginPath();
66
+ context.rect(x, y, width, height);
67
+ if (fill) {
68
+ context.fillStyle = fill;
69
+ context.fill();
70
+ }
71
+ if (stroke) {
72
+ context.strokeWidth = strokeWidth;
73
+ context.strokeStyle = stroke;
74
+ context.stroke();
75
+ }
76
+ };
77
+
78
+ const startTime = Date.now();
79
+ updateCanvasColor("red");
80
+ await new Promise((resolve) => {
81
+ setTimeout(resolve, 700);
82
+ });
83
+ addFrame(Date.now() - startTime);
84
+ updateCanvasColor("blue");
85
+ await new Promise((resolve) => {
86
+ setTimeout(resolve, 1_500);
87
+ });
88
+ addFrame(Date.now() - startTime);
89
+ encoder.finish();
90
+ const gifDataUrl = encoder.toDataUrl();
91
+ document.querySelector("img").src = gifDataUrl;
92
+ </script>
93
+ </body>
94
+ </html>