@lijuhong1981/jsgif 1.3.16 → 1.3.18
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.
- package/LICENSE +15 -0
- package/README.md +17 -11
- package/package.json +8 -8
- package/src/GIFPlayer.js +24 -18
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022-2026 lijuhong1981
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
# @lijuhong1981/jsgif
|
|
2
|
+
|
|
3
|
+
> GIF 动图加载与播放工具,可将 GIF 动图加载并播放到 Canvas。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lijuhong1981/jsgif
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 导出
|
|
12
|
+
|
|
13
|
+
- `loadGIFImage(...)` — 加载 GIF 动图
|
|
14
|
+
- `GIFImageLoader` — GIF 图片加载器类
|
|
15
|
+
- `GIFPlayer` — GIF 播放器类
|
|
16
|
+
|
|
17
|
+
依赖:`@lijuhong1981/jscheck`、`@lijuhong1981/jsdestroy`、`@lijuhong1981/jsevents`、`@lijuhong1981/jsload`、`@lijuhong1981/jstask`
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lijuhong1981/jsgif",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.3.18",
|
|
4
|
+
"description": "GIF animation loading and playing.",
|
|
5
5
|
"author": "lijuhong1981 <lijuhong@hotmail.com>",
|
|
6
6
|
"homepage": "https://github.com/lijuhong1981/jslibs#readme",
|
|
7
7
|
"license": "ISC",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"bugs": {
|
|
19
19
|
"url": "https://github.com/lijuhong1981/jslibs/issues"
|
|
20
20
|
},
|
|
21
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "5d4bd57b654be98c46364160070d5dd11600afa6",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@lijuhong1981/jscheck": "^1.1.
|
|
24
|
-
"@lijuhong1981/jsdestroy": "^1.2.
|
|
25
|
-
"@lijuhong1981/jsevents": "^1.2.
|
|
26
|
-
"@lijuhong1981/jsload": "^1.3.
|
|
27
|
-
"@lijuhong1981/jstask": "^1.2.
|
|
23
|
+
"@lijuhong1981/jscheck": "^1.1.8",
|
|
24
|
+
"@lijuhong1981/jsdestroy": "^1.2.8",
|
|
25
|
+
"@lijuhong1981/jsevents": "^1.2.14",
|
|
26
|
+
"@lijuhong1981/jsload": "^1.3.19",
|
|
27
|
+
"@lijuhong1981/jstask": "^1.2.14"
|
|
28
28
|
}
|
|
29
29
|
}
|
package/src/GIFPlayer.js
CHANGED
|
@@ -15,7 +15,7 @@ function byteToBitArr(bite) {
|
|
|
15
15
|
return byteArr;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
//
|
|
18
|
+
// 通用函数
|
|
19
19
|
function bitsToNum(ba) {
|
|
20
20
|
return ba.reduce(function (s, n) {
|
|
21
21
|
return s * 2 + n;
|
|
@@ -69,7 +69,10 @@ function lzwDecode(minCodeSize, data) {
|
|
|
69
69
|
function readCode(size) {
|
|
70
70
|
let code = 0;
|
|
71
71
|
for (let i = 0; i < size; i++) {
|
|
72
|
-
|
|
72
|
+
const byteIndex = pos >> 3;
|
|
73
|
+
if (byteIndex >= data.length)
|
|
74
|
+
return -1;
|
|
75
|
+
if (data.charCodeAt(byteIndex) & (1 << (pos & 7))) {
|
|
73
76
|
code |= 1 << i;
|
|
74
77
|
}
|
|
75
78
|
pos++;
|
|
@@ -98,6 +101,8 @@ function lzwDecode(minCodeSize, data) {
|
|
|
98
101
|
while (true) {
|
|
99
102
|
last = code;
|
|
100
103
|
code = readCode(codeSize);
|
|
104
|
+
if (code === -1)
|
|
105
|
+
break;
|
|
101
106
|
|
|
102
107
|
if (code === clearCode) {
|
|
103
108
|
clear();
|
|
@@ -106,6 +111,8 @@ function lzwDecode(minCodeSize, data) {
|
|
|
106
111
|
if (code === eoiCode) {
|
|
107
112
|
break
|
|
108
113
|
};
|
|
114
|
+
if (last === null)
|
|
115
|
+
break;
|
|
109
116
|
if (code < dict.length) {
|
|
110
117
|
if (last !== clearCode) {
|
|
111
118
|
dict.push(dict[last].concat(dict[code][0]));
|
|
@@ -120,7 +127,7 @@ function lzwDecode(minCodeSize, data) {
|
|
|
120
127
|
output.push.apply(output, dict[code]);
|
|
121
128
|
|
|
122
129
|
if (dict.length === (1 << codeSize) && codeSize < 12) {
|
|
123
|
-
//
|
|
130
|
+
// 如果已经到达最后一个码且 codeSize 为 12,则下一个码将是 clearCode,其长度为 12 位。
|
|
124
131
|
codeSize++;
|
|
125
132
|
}
|
|
126
133
|
}
|
|
@@ -135,7 +142,6 @@ const defaultOptions = {
|
|
|
135
142
|
|
|
136
143
|
function GIFPlayer(options = {}) {
|
|
137
144
|
options = Object.assign({}, defaultOptions, options);
|
|
138
|
-
console.log('options:', options);
|
|
139
145
|
const CANVAS = options.canvas || document.createElement("canvas");
|
|
140
146
|
const CANVAS_CTX = CANVAS.getContext('2d');
|
|
141
147
|
const TEMP_CANVAS = document.createElement("canvas");//用来拿 imageData 的缓存canvas
|
|
@@ -180,11 +186,11 @@ function GIFPlayer(options = {}) {
|
|
|
180
186
|
if (currIdx > 0) {
|
|
181
187
|
// 这块不要动
|
|
182
188
|
if (LAST_DISPOSA_METHOD === 3) {
|
|
183
|
-
//
|
|
184
|
-
//
|
|
185
|
-
//
|
|
189
|
+
// 恢复到前一帧
|
|
190
|
+
// 如果到此为止已释放了包括第一个 TEMP_CANVAS_CTX 在内的所有画布,则没有可恢复的合成画布。
|
|
191
|
+
// 此时改为恢复到背景。
|
|
186
192
|
if (CURRENT_FRAME_INDEX > -1) {
|
|
187
|
-
TEMP_CANVAS_CTX.putImageData(FRAME_LIST[CURRENT_FRAME_INDEX].
|
|
193
|
+
TEMP_CANVAS_CTX.putImageData(FRAME_LIST[CURRENT_FRAME_INDEX].imgData, 0, 0);
|
|
188
194
|
} else {
|
|
189
195
|
TEMP_CANVAS_CTX.clearRect(0, 0, TEMP_CANVAS.width, TEMP_CANVAS.height);
|
|
190
196
|
}
|
|
@@ -193,8 +199,8 @@ function GIFPlayer(options = {}) {
|
|
|
193
199
|
}
|
|
194
200
|
|
|
195
201
|
if (LAST_DISPOSA_METHOD === 2) {
|
|
196
|
-
//
|
|
197
|
-
//
|
|
202
|
+
// 恢复到背景色
|
|
203
|
+
// 浏览器实现历史上会恢复到透明;我们保持一致。
|
|
198
204
|
// http://www.wizards-toolkit.org/discourse-server/viewtopic.php?f=1&t=21172#p86079
|
|
199
205
|
TEMP_CANVAS_CTX.clearRect(0, 0, TEMP_CANVAS.width, TEMP_CANVAS.height);
|
|
200
206
|
}
|
|
@@ -211,10 +217,10 @@ function GIFPlayer(options = {}) {
|
|
|
211
217
|
|
|
212
218
|
TEMP_CANVAS_CTX.putImageData(imgData, img.leftPos, img.topPos);
|
|
213
219
|
|
|
214
|
-
if (FRAME_LIST[
|
|
215
|
-
FRAME_LIST[
|
|
216
|
-
FRAME_LIST[
|
|
217
|
-
FRAME_LIST[
|
|
220
|
+
if (FRAME_LIST[currIdx - 1]) {
|
|
221
|
+
FRAME_LIST[currIdx - 1].imgData = TEMP_CANVAS_CTX.getImageData(0, 0, TEMP_CANVAS.width, TEMP_CANVAS.height);
|
|
222
|
+
FRAME_LIST[currIdx - 1].leftPos = img.leftPos;
|
|
223
|
+
FRAME_LIST[currIdx - 1].topPos = img.topPos;
|
|
218
224
|
// console.log(CURRENT_FRAME_INDEX, FRAME_LIST[CURRENT_FRAME_INDEX]);
|
|
219
225
|
}
|
|
220
226
|
};
|
|
@@ -252,7 +258,7 @@ function GIFPlayer(options = {}) {
|
|
|
252
258
|
};
|
|
253
259
|
|
|
254
260
|
function parsePTExt(block) {
|
|
255
|
-
//
|
|
261
|
+
// 几乎没有人会使用它。如果你要用,请自行处理解析。
|
|
256
262
|
STREAM.readByte(); // Always 12 这个必须得这样执行一次
|
|
257
263
|
block.ptHeader = STREAM.readBytes(12);
|
|
258
264
|
block.ptData = readSubBlocks();
|
|
@@ -319,8 +325,8 @@ function GIFPlayer(options = {}) {
|
|
|
319
325
|
function parseImg(img) {
|
|
320
326
|
|
|
321
327
|
function deinterlace(pixels, width) {
|
|
322
|
-
//
|
|
323
|
-
//
|
|
328
|
+
// 当然这会破坏隔行扫描的初衷。而且这*可能*
|
|
329
|
+
// 是有史以来效率最低的实现方式。但无论如何……
|
|
324
330
|
let newPixels = new Array(pixels.length);
|
|
325
331
|
const rows = pixels.length / width;
|
|
326
332
|
|
|
@@ -329,7 +335,7 @@ function GIFPlayer(options = {}) {
|
|
|
329
335
|
newPixels.splice.apply(newPixels, [toRow * width, width].concat(fromPixels));
|
|
330
336
|
};
|
|
331
337
|
|
|
332
|
-
//
|
|
338
|
+
// 参见附录 E。
|
|
333
339
|
const offsets = [0, 4, 2, 1],
|
|
334
340
|
steps = [8, 8, 4, 2];
|
|
335
341
|
|