forked from Tevemadar/WebAlign
-
Notifications
You must be signed in to change notification settings - Fork 3
/
segrle.js
74 lines (68 loc) · 1.66 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);
}
}