-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.ts
90 lines (71 loc) · 1.96 KB
/
index.ts
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
const RIFF = new Uint8Array([
0x52, 0x49, 0x46, 0x46,
]);
const WEBP = new Uint8Array([
0x57, 0x45, 0x42, 0x50,
]);
const ANMF = new Uint8Array([
0x41, 0x4e, 0x4d, 0x46,
]);
export async function isWebP(input: ArrayBuffer | Blob) {
const chunk = await readBytes(input, 0, 12);
const buf = new Uint8Array(chunk);
return isEqual(RIFF, buf.slice(0, 4)) &&
isEqual(WEBP, buf.slice(8, 12));
}
export async function isAnimatedWebP(input: ArrayBuffer | Blob) {
if (await isWebP(input) === false) {
return false;
}
let offset = 12;
const size = getSize(input);
do {
const bufHeader = await readBytes(input, offset, 8);
offset += 8;
const chunkType = new Uint8Array(bufHeader.slice(0, 4));
const [ payloadSize ] = new Uint32Array(bufHeader.slice(4, 8));
offset += payloadSize;
if (isEqual(ANMF, chunkType)) {
return true;
}
} while (offset <= size);
return false;
}
function readBytes(input: Blob | ArrayBuffer, offset: number, size: number): Promise<ArrayBuffer> {
if (input instanceof Blob) {
return new Promise<ArrayBuffer>((resolve, reject) => {
const reader = new FileReader();
reader.onerror = (e) => {
reader.onerror = null;
reader.onload = null;
reject(e);
};
reader.onload = (e) => {
reader.onerror = null;
reader.onload = null;
resolve(e.target!.result as ArrayBuffer);
};
reader.readAsArrayBuffer(
input.slice(offset, offset + size),
);
});
}
return Promise.resolve(input.slice(offset, offset + size));
}
function getSize(input: Blob | ArrayBuffer) {
return input instanceof Blob ?
input.size :
input.byteLength;
}
function isEqual(a: Uint8Array, b: Uint8Array) {
if (a.byteLength !== b.byteLength) {
return false;
}
const maxLength = Math.max(a.byteLength, b.byteLength);
for (let i = 0 ; i < maxLength ; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}