-
Notifications
You must be signed in to change notification settings - Fork 23
/
gifsparser.js
84 lines (83 loc) · 2.96 KB
/
gifsparser.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
75
76
77
78
79
80
81
82
83
84
(function () {
function loadGIF(url, successCB, errorCB) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function (e) {
parseGIF(new Uint8Array(e.target.response), successCB, errorCB);
}
xhr.onerror = function () {
errorCB && errorCB('loadGIF: load error');
};
xhr.send();
}
function parseGIF(gif, successCB, errorCB) {
var pos = 0;
var delayTimes = [];
var loadCnt = 0;
var graphicControl = null;
var imageData = null;
var frames = [];
var loopCnt = 0;
if (gif[0] === 0x47 && gif[1] === 0x49 && gif[2] === 0x46 && // 'GIF'
gif[3] === 0x38 && gif[4] === 0x39 && gif[5] === 0x61) { // '89a'
pos += 13 + (+!!(gif[10] & 0x80) * Math.pow(2, (gif[10] & 0x07) + 1) * 3);
var gifHeader = gif.subarray(0, pos);
while (gif[pos] && gif[pos] !== 0x3b) {
var offset = pos, blockId = gif[pos];
if (blockId === 0x21) {
var label = gif[++pos];
if ([0x01, 0xfe, 0xf9, 0xff].indexOf(label) !== -1) {
label === 0xf9 && (delayTimes.push((gif[pos + 3] + (gif[pos + 4] << 8)) * 10));
label === 0xff && (loopCnt = gif[pos + 15] + (gif[pos + 16] << 8));
while (gif[++pos]) pos += gif[pos];
label === 0xf9 && (graphicControl = gif.subarray(offset, pos + 1));
} else { errorCB && errorCB('parseGIF: unknown label'); break; }
} else if (blockId === 0x2c) {
pos += 9;
pos += 1 + (+!!(gif[pos] & 0x80) * (Math.pow(2, (gif[pos] & 0x07) + 1) * 3));
while (gif[++pos]) pos += gif[pos];
var imageData = gif.subarray(offset, pos + 1);
frames.push(URL.createObjectURL(new Blob([gifHeader, graphicControl, imageData])));
} else { errorCB && errorCB('parseGIF: unknown blockId'); break; }
pos++;
}
} else { errorCB && errorCB('parseGIF: no GIF89a'); }
if (frames.length) {
var loadImg = function () {
var cnv = document.createElement('canvas');
cnv.width = frames[0].width;
cnv.height = frames[0].height;
var ctx = cnv.getContext('2d');
frames.forEach(function (src, i) {
var img = new Image();
img.onload = function (e, i) {
loadCnt++;
frames[i] = this;
if (loadCnt === frames.length) {
loadCnt = 0;
imageFix(1);
}
}.bind(img, null, i);
img.src = src;
});
}
var imageFix = function (i) {
var img = new Image();
img.onload = function (e, i) {
loadCnt++;
frames[i] = this;
if (loadCnt === frames.length) {
ctx = null, cnv = null;
successCB && successCB(delayTimes, loopCnt, frames);
} else {
imageFix(++i);
}
}.bind(img);
img.src = cnv.toDataURL('image/gif');
}
loadImg();
}
}
window.loadGIF = loadGIF;
})();