-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsegrle.js
74 lines (68 loc) · 1.74 KB
/
segrle.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
function segrle({aid, width, height, data}){
let buf = new Uint8Array(width * height);
let pos = 0;
const te = new TextEncoder();
bytes(te.encode("SegRLEv1"));
const aidbuf = te.encode(aid);
code(aidbuf.length);
bytes(aidbuf);
const stats = new Map();
for (const v of data)
stats.set(v, stats.has(v) ? stats.get(v) + 1 : 1);
code(stats.size);
const bytemode = stats.size <= 256;
let codes = new Map();
for (const pair of [...stats.entries()].sort((x, y) => y[1] - x[1])) {
code(atlas.remap[pair[0]]);
codes.set(pair[0], codes.size);
}
code(width);
code(height);
let current = -1;
let count = 0;
for (const v of data) {
if (v !== current) {
if (current !== -1) {
if (bytemode)
byte(codes.get(current));
else
code(codes.get(current));
code(count);
}
current = v;
count = 0;
} else
count++;
}
if (bytemode)
byte(codes.get(current));
else
code(codes.get(current));
code(count);
resize(pos);
return buf;
function resize(newsize) {
const newbuf = new Uint8Array(newsize);
const len = Math.min(buf.length, newsize);
for (let i = 0; i < len; i++)
newbuf[i] = buf[i];
buf = newbuf;
}
function byte(b) {
if (buf.length <= pos)
resize(buf.length * 2);
buf[pos] = b;
pos++;
}
function bytes(bs) {
for (const b of bs)
byte(b);
}
function code(c) {
while (c > 127) {
byte(c | 128);
c >>>= 7;
}
byte(c);
}
}