@cjser/sindresorhus__gifkit 0.1.0-cjser.2
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/dist-cjser/index.cjs +2168 -0
- package/index.d.ts +838 -0
- package/index.js +118 -0
- package/license +9 -0
- package/package.json +83 -0
- package/readme.md +294 -0
- package/source/byte-stream.js +141 -0
- package/source/constants.js +36 -0
- package/source/decode.js +453 -0
- package/source/encode.js +536 -0
- package/source/loop-count.js +72 -0
- package/source/lzw.js +322 -0
- package/source/quantize.js +185 -0
- package/source/render.js +470 -0
- package/source/validate.js +485 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,838 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention -- GIF block type names mirror the spec's own casing */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
GIF color table data as flat RGB bytes, flat byte arrays, or RGB triplets.
|
|
5
|
+
*/
|
|
6
|
+
export type ColorTable = Uint8Array | number[] | Array<[number, number, number]>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
Extension payload data as ASCII text or bytes.
|
|
10
|
+
*/
|
|
11
|
+
export type ExtensionPayload = string | Uint8Array | number[];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
Fixed-size GIF byte field as text or exact bytes.
|
|
15
|
+
*/
|
|
16
|
+
export type FixedByteField = string | Uint8Array | number[];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
GIF file version.
|
|
20
|
+
*/
|
|
21
|
+
export type GIFVersion = '87a' | '89a';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
Total animation plays. Finite values must be integers from `1` to `65_536`. Use `'forever'` for infinite playback. Omit the property when no GIF loop extension is present.
|
|
25
|
+
*/
|
|
26
|
+
export type GIFPlayCount = number | 'forever';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
GIF frame disposal behavior.
|
|
30
|
+
*/
|
|
31
|
+
export type DisposalMethod = 'unspecified' | 'keep' | 'restoreBackground' | 'restorePrevious';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
Graphic Control Extension metadata for transparency, delay, and disposal.
|
|
35
|
+
*/
|
|
36
|
+
export type GraphicControlExtension = {
|
|
37
|
+
/**
|
|
38
|
+
Advanced GIF compositing metadata exposed so structured GIF data can be preserved or re-encoded. It controls what happens to the current frame’s pixels before the next frame is drawn: `'unspecified'` leaves the choice to the decoder, `'keep'` keeps the pixels, `'restoreBackground'` clears them to the background, and `'restorePrevious'` restores the previous canvas. Rendered pixels already have this applied, so most users do not need to read or set it.
|
|
39
|
+
*/
|
|
40
|
+
disposalMethod?: DisposalMethod;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
Frame delay in seconds.
|
|
44
|
+
*/
|
|
45
|
+
delay?: number;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
Palette index to treat as transparent. Omit it for no transparent color.
|
|
49
|
+
*/
|
|
50
|
+
transparentColorIndex?: number | undefined;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
A block holding arbitrary text with no effect on rendering.
|
|
55
|
+
*/
|
|
56
|
+
export type CommentExtensionBlock = {
|
|
57
|
+
/**
|
|
58
|
+
Block discriminator.
|
|
59
|
+
*/
|
|
60
|
+
type: 'commentExtension';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
Raw comment payload as ASCII text or bytes.
|
|
64
|
+
*/
|
|
65
|
+
data?: ExtensionPayload;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
Application Extension block, including Netscape play count metadata when present.
|
|
70
|
+
*/
|
|
71
|
+
export type AppExtensionBlock = {
|
|
72
|
+
/**
|
|
73
|
+
Block discriminator.
|
|
74
|
+
*/
|
|
75
|
+
type: 'applicationExtension';
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
8-byte GIF application identifier.
|
|
79
|
+
*/
|
|
80
|
+
identifier: string;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
3-byte authentication code as text or exact bytes.
|
|
84
|
+
*/
|
|
85
|
+
authenticationCode: FixedByteField;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
Raw application payload as ASCII text or bytes.
|
|
89
|
+
*/
|
|
90
|
+
data?: ExtensionPayload;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
Whether this block is the Netscape looping extension when decoded.
|
|
94
|
+
*/
|
|
95
|
+
isNetscapeLoopingExtension?: boolean;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
Total animation plays from a Netscape looping extension. `'forever'` means infinite playback. When encoding an explicit Netscape application extension block, finite values must be from `2` to `65_536` because `1` is represented by omitting the loop extension.
|
|
99
|
+
*/
|
|
100
|
+
playCount?: GIFPlayCount;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
type ImageBlockBase = {
|
|
104
|
+
/**
|
|
105
|
+
Graphic control metadata scoped to this image block.
|
|
106
|
+
*/
|
|
107
|
+
graphicControlExtension?: GraphicControlExtension | undefined;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
Image left offset in logical-screen pixels. Defaults to `0` when encoding.
|
|
111
|
+
*/
|
|
112
|
+
left?: number;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
Image top offset in logical-screen pixels. Defaults to `0` when encoding.
|
|
116
|
+
*/
|
|
117
|
+
top?: number;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
Image width in pixels.
|
|
121
|
+
*/
|
|
122
|
+
width: number;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
Image height in pixels.
|
|
126
|
+
*/
|
|
127
|
+
height: number;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
Indexed image block. `pixels` is one palette index per pixel and uses this image's `colorTable` or the GIF `globalColorTable`.
|
|
132
|
+
*/
|
|
133
|
+
export type ImageBlock = ImageBlockBase & {
|
|
134
|
+
/**
|
|
135
|
+
Block discriminator.
|
|
136
|
+
*/
|
|
137
|
+
type: 'image';
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
Whether indexed pixels are stored in GIF interlaced order.
|
|
141
|
+
*/
|
|
142
|
+
isInterlaced?: boolean;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
Color table for this image block.
|
|
146
|
+
*/
|
|
147
|
+
colorTable?: ColorTable | undefined;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
LZW minimum code size read from decoded GIF image data. `encodeGIF` infers this value and does not accept it as input.
|
|
151
|
+
*/
|
|
152
|
+
minimumCodeSize?: number;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
One palette index per pixel.
|
|
156
|
+
*/
|
|
157
|
+
pixels: Uint8Array | number[];
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
RGBA image block. Use this when you have flat RGBA bytes and want gifkit to build the indexed pixels and color table.
|
|
162
|
+
*/
|
|
163
|
+
export type RGBAImage = ImageBlockBase & {
|
|
164
|
+
/**
|
|
165
|
+
Block discriminator.
|
|
166
|
+
*/
|
|
167
|
+
type: 'rgbaImage';
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
Flat RGBA bytes: `[red, green, blue, alpha, ...]`. Used to build a local color table when the image fits GIF’s 256-color model.
|
|
171
|
+
*/
|
|
172
|
+
pixels: Uint8Array | Uint8ClampedArray | number[];
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
RGB value stored in the palette entry used for transparent RGBA pixels.
|
|
176
|
+
*/
|
|
177
|
+
transparentColor?: [number, number, number];
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
Image block accepted by `encodeGIF`. The encoder infers GIF LZW details like `minimumCodeSize`.
|
|
182
|
+
*/
|
|
183
|
+
export type EncodableImageBlock = Omit<ImageBlock, 'minimumCodeSize'> & {
|
|
184
|
+
/**
|
|
185
|
+
Not accepted by `encodeGIF`; the encoder infers it from the active color table.
|
|
186
|
+
*/
|
|
187
|
+
minimumCodeSize?: never;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
A block whose extension label gifkit doesn't interpret, preserved as raw bytes.
|
|
192
|
+
*/
|
|
193
|
+
export type UnknownExtensionBlock = {
|
|
194
|
+
/**
|
|
195
|
+
Block discriminator.
|
|
196
|
+
*/
|
|
197
|
+
type: 'unknownExtension';
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
Raw extension label byte.
|
|
201
|
+
*/
|
|
202
|
+
extensionLabel: number;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
Fixed data bytes that followed the extension label.
|
|
206
|
+
*/
|
|
207
|
+
fixedData: Uint8Array;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
Raw data sub-block payload.
|
|
211
|
+
*/
|
|
212
|
+
data: Uint8Array;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
Any structured GIF block.
|
|
217
|
+
*/
|
|
218
|
+
export type GIFBlock = CommentExtensionBlock | AppExtensionBlock | ImageBlock | UnknownExtensionBlock;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
Structured block accepted by `encodeGIF`.
|
|
222
|
+
*/
|
|
223
|
+
export type EncodableGIFBlock = CommentExtensionBlock | AppExtensionBlock | EncodableImageBlock | RGBAImage;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
Structured GIF object with logical-screen metadata, extension blocks, image blocks, color tables, and decoded indexed pixels.
|
|
227
|
+
*/
|
|
228
|
+
export type GIF = {
|
|
229
|
+
/**
|
|
230
|
+
Optional object discriminator.
|
|
231
|
+
*/
|
|
232
|
+
type?: 'gif';
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
Decoded GIF version.
|
|
236
|
+
*/
|
|
237
|
+
version?: GIFVersion;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
Logical screen width in pixels.
|
|
241
|
+
*/
|
|
242
|
+
width: number;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
Logical screen height in pixels.
|
|
246
|
+
*/
|
|
247
|
+
height: number;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
Global color table index used as the logical-screen background color.
|
|
251
|
+
*/
|
|
252
|
+
backgroundColorIndex?: number;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
Global color table shared by image blocks.
|
|
256
|
+
*/
|
|
257
|
+
globalColorTable?: ColorTable | undefined;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
Total animation plays. `'forever'` means infinite playback. Omitted when no loop extension was present.
|
|
261
|
+
*/
|
|
262
|
+
playCount?: GIFPlayCount | undefined;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
Structured GIF blocks in file order.
|
|
266
|
+
*/
|
|
267
|
+
blocks?: GIFBlock[];
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
Image blocks extracted for convenience.
|
|
271
|
+
*/
|
|
272
|
+
imageBlocks?: ImageBlock[];
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
Structured GIF object accepted by `encodeGIF`.
|
|
277
|
+
*/
|
|
278
|
+
export type EncodableGIF = Omit<GIF, 'version' | 'playCount' | 'blocks' | 'imageBlocks'> & {
|
|
279
|
+
/**
|
|
280
|
+
Total animation plays. Finite values must be integers from `1` to `65_536`. Use `'forever'` for infinite playback. Omit it to omit the loop extension. `playCount: 1` also omits the loop extension because that matches default GIF playback.
|
|
281
|
+
*/
|
|
282
|
+
playCount?: GIFPlayCount | undefined;
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
Structured encodable GIF blocks in file order.
|
|
286
|
+
*/
|
|
287
|
+
blocks?: EncodableGIFBlock[];
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
Options for `decodeGIF()` and `decodeAnimatedGIF()`.
|
|
292
|
+
*/
|
|
293
|
+
export type DecodeOptions = {
|
|
294
|
+
/**
|
|
295
|
+
Default: `true`. Reject reserved bits, malformed extension sequencing, and trailing bytes.
|
|
296
|
+
*/
|
|
297
|
+
strict?: boolean;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
How to render the GIF logical-screen background.
|
|
302
|
+
*/
|
|
303
|
+
export type RenderBackground = 'transparent' | 'gif';
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
Options for `renderGIFFrames()`, `renderGIFFrameSequence()`, and `decodeAnimatedGIF()`.
|
|
307
|
+
*/
|
|
308
|
+
export type RenderOptions = {
|
|
309
|
+
/**
|
|
310
|
+
Default: `true`. Reject malformed render data like color indexes outside the active color table.
|
|
311
|
+
*/
|
|
312
|
+
strict?: boolean;
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
Default: `'gif'` for `renderGIFFrames()` and `'transparent'` for `decodeAnimatedGIF()`. Use `'gif'` to render the logical-screen background color, or `'transparent'` to render it as transparent.
|
|
316
|
+
*/
|
|
317
|
+
background?: RenderBackground;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
Options for `renderGIFFrameSequence()`.
|
|
322
|
+
*/
|
|
323
|
+
export type GIFFrameSequenceOptions = RenderOptions & {
|
|
324
|
+
/**
|
|
325
|
+
Default: `true`. Repeat according to GIF `playCount` metadata. Missing metadata means one pass, a finite number means that many total passes, and `'forever'` means infinite playback. Set to `false` to render exactly one pass.
|
|
326
|
+
*/
|
|
327
|
+
repeat?: boolean;
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
Optional abort signal. When aborted, iteration ends.
|
|
331
|
+
*/
|
|
332
|
+
signal?: AbortSignal;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
Rendered full logical-screen RGBA frame.
|
|
337
|
+
*/
|
|
338
|
+
export type RenderedFrame = {
|
|
339
|
+
/**
|
|
340
|
+
Frame left offset in logical-screen pixels.
|
|
341
|
+
*/
|
|
342
|
+
left: number;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
Frame top offset in logical-screen pixels.
|
|
346
|
+
*/
|
|
347
|
+
top: number;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
Frame width in pixels.
|
|
351
|
+
*/
|
|
352
|
+
width: number;
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
Frame height in pixels.
|
|
356
|
+
*/
|
|
357
|
+
height: number;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
Frame delay in seconds.
|
|
361
|
+
*/
|
|
362
|
+
delay: number;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
Advanced GIF compositing metadata kept so rendered frames can still be related back to the original GIF structure. `'unspecified'` leaves the choice to the decoder, `'keep'` keeps the pixels, `'restoreBackground'` clears them to the background, and `'restorePrevious'` restores the previous canvas before the next frame is drawn. gifkit already applies this when producing `pixels`, so use it only if you need to inspect or preserve the original animation metadata.
|
|
366
|
+
*/
|
|
367
|
+
disposalMethod: DisposalMethod;
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
Rendered full logical-screen RGBA pixels.
|
|
371
|
+
*/
|
|
372
|
+
pixels: Uint8ClampedArray;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
Rendered full logical-screen RGBA frame yielded by `renderGIFFrameSequence()`.
|
|
377
|
+
*/
|
|
378
|
+
export type RenderedGIFFrame = RenderedFrame & {
|
|
379
|
+
/**
|
|
380
|
+
Zero-based image-frame index within the current pass.
|
|
381
|
+
*/
|
|
382
|
+
index: number;
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
Zero-based repetition index for this frame.
|
|
386
|
+
*/
|
|
387
|
+
loopIndex: number;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
Rendered GIF frames.
|
|
392
|
+
*/
|
|
393
|
+
export type RenderedGIF = {
|
|
394
|
+
/**
|
|
395
|
+
Logical screen width in pixels.
|
|
396
|
+
*/
|
|
397
|
+
width: number;
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
Logical screen height in pixels.
|
|
401
|
+
*/
|
|
402
|
+
height: number;
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
Total animation plays. `'forever'` means infinite playback. Omitted when no loop extension was present.
|
|
406
|
+
*/
|
|
407
|
+
playCount?: GIFPlayCount;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
Rendered full logical-screen frames.
|
|
411
|
+
*/
|
|
412
|
+
frames: RenderedFrame[];
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
Decoded animated GIF frame as full-frame RGBA pixels with delay in seconds.
|
|
417
|
+
*/
|
|
418
|
+
export type DecodedAnimatedGIFFrame = {
|
|
419
|
+
/**
|
|
420
|
+
Rendered full-frame RGBA pixels.
|
|
421
|
+
*/
|
|
422
|
+
pixels: Uint8ClampedArray;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
Frame delay in seconds.
|
|
426
|
+
*/
|
|
427
|
+
delay: number;
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
Decoded animated GIF with rendered full-frame RGBA frames. `playCount` is `'forever'` for infinite playback and omitted when no loop extension was present.
|
|
432
|
+
*/
|
|
433
|
+
export type DecodedAnimatedGIF = {
|
|
434
|
+
/**
|
|
435
|
+
Logical screen width in pixels.
|
|
436
|
+
*/
|
|
437
|
+
width: number;
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
Logical screen height in pixels.
|
|
441
|
+
*/
|
|
442
|
+
height: number;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
Total animation plays. `'forever'` means infinite playback. Omitted when no loop extension was present.
|
|
446
|
+
*/
|
|
447
|
+
playCount?: GIFPlayCount;
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
Rendered full-frame RGBA frames.
|
|
451
|
+
*/
|
|
452
|
+
frames: DecodedAnimatedGIFFrame[];
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
Flat RGBA bytes for one animated GIF frame: `[red, green, blue, alpha, ...]`.
|
|
457
|
+
*/
|
|
458
|
+
export type AnimatedGIFPixels = Uint8Array | Uint8ClampedArray;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
RGBA pixels for one animated GIF frame.
|
|
462
|
+
*/
|
|
463
|
+
export type AnimatedGIFFrame = AnimatedGIFPixels | {
|
|
464
|
+
/**
|
|
465
|
+
Flat RGBA bytes: `[red, green, blue, alpha, ...]`.
|
|
466
|
+
*/
|
|
467
|
+
pixels: Uint8Array | Uint8ClampedArray | number[];
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
Unavailable in the uniform-`fps` frame form.
|
|
471
|
+
*/
|
|
472
|
+
delay?: never;
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
RGBA pixels for one animated GIF frame with a per-frame delay in seconds.
|
|
477
|
+
*/
|
|
478
|
+
export type AnimatedGIFFrameWithDelay = {
|
|
479
|
+
/**
|
|
480
|
+
Flat RGBA bytes: `[red, green, blue, alpha, ...]`.
|
|
481
|
+
*/
|
|
482
|
+
pixels: Uint8Array | Uint8ClampedArray | number[];
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
Per-frame delay in seconds.
|
|
486
|
+
*/
|
|
487
|
+
delay: number;
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
Options for `encodeAnimatedGIF`. `playCount: 'forever'` means infinite playback. Omit it to omit the loop extension. `quality` defaults to `0.8`; quantization is per-frame and does not dither. Use `1` to keep exact colors.
|
|
492
|
+
*/
|
|
493
|
+
export type EncodeAnimatedGIFOptions = {
|
|
494
|
+
/**
|
|
495
|
+
Frame width in pixels.
|
|
496
|
+
*/
|
|
497
|
+
width: number;
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
Frame height in pixels.
|
|
501
|
+
*/
|
|
502
|
+
height: number;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
Total animation plays. Finite values must be integers from `1` to `65_536`. Use `'forever'` for infinite playback. Omit it to omit the loop extension.
|
|
506
|
+
*/
|
|
507
|
+
playCount?: GIFPlayCount | undefined;
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
Default: `0.8`. `0...1`, where lower values quantize each frame more aggressively. Use `1` only when every frame already has at most 256 exact colors.
|
|
511
|
+
*/
|
|
512
|
+
quality?: number;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
Options for `encodeAnimatedGIF` with uniform frame timing.
|
|
517
|
+
*/
|
|
518
|
+
export type EncodeAnimatedGIFOptionsWithFPS = EncodeAnimatedGIFOptions & {
|
|
519
|
+
/**
|
|
520
|
+
Frames per second for uniform timing. GIF stores delays in 0.01 second increments, so timing is rounded.
|
|
521
|
+
*/
|
|
522
|
+
fps: number;
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
Options for `encodeAnimatedGIF` with per-frame timing.
|
|
527
|
+
*/
|
|
528
|
+
export type EncodeAnimatedGIFOptionsWithFrameDelays = EncodeAnimatedGIFOptions & {
|
|
529
|
+
/**
|
|
530
|
+
Unavailable when each frame provides its own `delay`.
|
|
531
|
+
*/
|
|
532
|
+
fps?: undefined;
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
Options for `indexedImage`.
|
|
537
|
+
*/
|
|
538
|
+
export type IndexedImageOptions = {
|
|
539
|
+
/**
|
|
540
|
+
Default: `[0, 0, 0]`. RGB value stored in the palette entry used for transparent pixels.
|
|
541
|
+
*/
|
|
542
|
+
transparentColor?: [number, number, number];
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
Indexed pixels and a GIF color table converted from RGBA input without quantizing or dithering.
|
|
547
|
+
*/
|
|
548
|
+
export type IndexedImage = {
|
|
549
|
+
/**
|
|
550
|
+
One palette index per pixel.
|
|
551
|
+
*/
|
|
552
|
+
pixels: Uint8Array;
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
GIF color table as flat RGB bytes.
|
|
556
|
+
*/
|
|
557
|
+
colorTable: Uint8Array;
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
Palette index used for transparency, or `undefined` when the image has no transparent pixels.
|
|
561
|
+
*/
|
|
562
|
+
transparentColorIndex: number | undefined;
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
Decodes a `Uint8Array` containing a GIF file and returns a structured GIF object with logical-screen metadata, extension blocks, image blocks, color tables, and decoded indexed pixels.
|
|
567
|
+
|
|
568
|
+
Options:
|
|
569
|
+
|
|
570
|
+
- `strict` - Default: `true`. Reject reserved bits, malformed extension sequencing, and trailing bytes. Use `false` for best-effort decoding.
|
|
571
|
+
|
|
572
|
+
Decoding enforces internal pixel, block-count, data sub-block-count, and data payload byte limits to avoid resource exhaustion.
|
|
573
|
+
|
|
574
|
+
gifkit focuses on GIF features that are useful in modern JavaScript workflows. It intentionally does not expose the GIF user-input flag, pixel aspect ratio byte, color-resolution metadata, color-table sort flags, or Plain Text Extension rendering/encoding. These are legacy display-era features, are rarely present in real GIFs, and are easy to misunderstand. Unknown extensions, including Plain Text Extensions, are preserved as `unknownExtension` blocks.
|
|
575
|
+
|
|
576
|
+
@example
|
|
577
|
+
```
|
|
578
|
+
import {decodeGIF, encodeGIF, renderGIFFrames} from '@cjser/sindresorhus__gifkit';
|
|
579
|
+
|
|
580
|
+
const bytes = encodeGIF({
|
|
581
|
+
width: 2,
|
|
582
|
+
height: 2,
|
|
583
|
+
globalColorTable: [
|
|
584
|
+
[0, 0, 0],
|
|
585
|
+
[255, 255, 255],
|
|
586
|
+
],
|
|
587
|
+
blocks: [{
|
|
588
|
+
type: 'image',
|
|
589
|
+
width: 2,
|
|
590
|
+
height: 2,
|
|
591
|
+
pixels: [0, 1, 1, 0],
|
|
592
|
+
}],
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
const gif = decodeGIF(bytes);
|
|
596
|
+
const rendered = renderGIFFrames(gif);
|
|
597
|
+
|
|
598
|
+
console.log(gif.version);
|
|
599
|
+
console.log(rendered.frames[0].pixels);
|
|
600
|
+
```
|
|
601
|
+
*/
|
|
602
|
+
export function decodeGIF(inputBytes: Uint8Array, options?: DecodeOptions): GIF;
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
Encodes a structured GIF object to a `Uint8Array`. Use `image` blocks when you already have indexed pixels and a palette. Use `rgbaImage` blocks when you have flat RGBA bytes that fit GIF’s 256-color model.
|
|
606
|
+
|
|
607
|
+
The `gif` object has this shape:
|
|
608
|
+
|
|
609
|
+
- `width` / `height` - Required. Logical screen size.
|
|
610
|
+
- `globalColorTable` - Optional. Global palette as flat RGB bytes (`[red, green, blue, ...]`), a `Uint8Array`, or RGB triplets (`[[red, green, blue], ...]`).
|
|
611
|
+
- `backgroundColorIndex` - Optional. Palette index used as the logical-screen background color. Requires `globalColorTable`.
|
|
612
|
+
- `playCount` - Total animation plays. Finite values must be integers from `1` to `65_536`. Use `'forever'` for infinite playback. Omit it to omit the loop extension. `playCount: 1` also omits the loop extension because that matches default GIF playback.
|
|
613
|
+
- `blocks` - Structured GIF blocks in file order.
|
|
614
|
+
|
|
615
|
+
Encoded GIFs are always written as GIF89a.
|
|
616
|
+
|
|
617
|
+
Block types:
|
|
618
|
+
|
|
619
|
+
- Indexed image block: `{type: 'image', width, height, pixels, colorTable?}`. `pixels` is one palette index per pixel and uses the image `colorTable` or GIF `globalColorTable`. `left` and `top` are optional image offsets and default to `0`. Advanced fields include `isInterlaced`.
|
|
620
|
+
- RGBA image block: `{type: 'rgbaImage', width, height, pixels}`. `pixels` is flat RGBA bytes: `[red, green, blue, alpha, ...]`. gifkit builds a color table from the pixels, so this only works when the image has at most 256 colors and alpha values are fully transparent or fully opaque. `transparentColor` is the RGB palette value stored for transparent pixels.
|
|
621
|
+
- Graphic control metadata for an image block: `graphicControlExtension: {disposalMethod?, delay?, transparentColorIndex?}`. `delay` is in seconds. `transparentColorIndex` is a palette index, or `undefined` for no transparent color. `disposalMethod` is exposed so structured GIF data can be preserved or re-encoded. It controls what happens to the current frame’s pixels before the next frame is drawn: `'unspecified'` leaves the choice to the decoder, `'keep'` keeps the pixels, `'restoreBackground'` clears them to the background, and `'restorePrevious'` restores the previous canvas. Rendered pixels already have this applied, so most users do not need to read or set it.
|
|
622
|
+
- Comment extension: `{type: 'commentExtension', data}`. Strings must be ASCII.
|
|
623
|
+
- Application extension: `{type: 'applicationExtension', identifier, authenticationCode, data?}`. `authenticationCode` accepts a 3-byte string or byte array. Decoded Netscape loop extensions also expose `isNetscapeLoopingExtension` and `playCount`. When encoding an explicit Netscape application extension block, finite `playCount` values must be from `2` to `65_536` because `1` is represented by omitting the loop extension.
|
|
624
|
+
|
|
625
|
+
Encoding enforces internal pixel, block-count, encode work cost, data payload byte, and total encoded byte limits to avoid resource exhaustion.
|
|
626
|
+
|
|
627
|
+
Extension payload strings must contain only ASCII characters. Use `Uint8Array` for binary extension data.
|
|
628
|
+
|
|
629
|
+
@example
|
|
630
|
+
```
|
|
631
|
+
import {decodeGIF, encodeGIF, renderGIFFrames} from '@cjser/sindresorhus__gifkit';
|
|
632
|
+
|
|
633
|
+
const bytes = encodeGIF({
|
|
634
|
+
width: 2,
|
|
635
|
+
height: 2,
|
|
636
|
+
globalColorTable: [
|
|
637
|
+
[0, 0, 0],
|
|
638
|
+
[255, 255, 255],
|
|
639
|
+
],
|
|
640
|
+
blocks: [{
|
|
641
|
+
type: 'image',
|
|
642
|
+
width: 2,
|
|
643
|
+
height: 2,
|
|
644
|
+
pixels: [0, 1, 1, 0],
|
|
645
|
+
}],
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
const gif = decodeGIF(bytes);
|
|
649
|
+
const rendered = renderGIFFrames(gif);
|
|
650
|
+
|
|
651
|
+
console.log(gif.version);
|
|
652
|
+
console.log(rendered.frames[0].pixels);
|
|
653
|
+
```
|
|
654
|
+
*/
|
|
655
|
+
export function encodeGIF(gif: EncodableGIF): Uint8Array;
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
Decodes an animated GIF to rendered full-frame RGBA frames. Frame `delay` values are in seconds. Uses a transparent background by default.
|
|
659
|
+
|
|
660
|
+
Returns:
|
|
661
|
+
|
|
662
|
+
- `width` / `height` - Logical screen size.
|
|
663
|
+
- `playCount` - Total animation plays. `'forever'` means infinite playback. Omitted when no loop extension was present.
|
|
664
|
+
- `frames` - Rendered full-frame RGBA frames.
|
|
665
|
+
- `frames[].pixels` - `Uint8ClampedArray` of flat RGBA bytes: `[red, green, blue, alpha, ...]`.
|
|
666
|
+
- `frames[].delay` - Frame delay in seconds. GIF stores delays in 0.01 second increments.
|
|
667
|
+
|
|
668
|
+
Options:
|
|
669
|
+
|
|
670
|
+
- `background` - Default: `'transparent'`. Use `'gif'` to render the logical-screen background color.
|
|
671
|
+
- `strict` - Default: `true`. Reject malformed decode data and render data like color indexes outside the active color table. Use `false` for best-effort decoding and rendering.
|
|
672
|
+
|
|
673
|
+
@example
|
|
674
|
+
```
|
|
675
|
+
import {decodeAnimatedGIF} from '@cjser/sindresorhus__gifkit';
|
|
676
|
+
|
|
677
|
+
const animation = decodeAnimatedGIF(bytes);
|
|
678
|
+
|
|
679
|
+
console.log(animation.width);
|
|
680
|
+
console.log(animation.frames[0].pixels);
|
|
681
|
+
console.log(animation.frames[0].delay);
|
|
682
|
+
```
|
|
683
|
+
*/
|
|
684
|
+
export function decodeAnimatedGIF(inputBytes: Uint8Array, options?: DecodeOptions & RenderOptions): DecodedAnimatedGIF;
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
Encodes RGBA frames as an animated GIF. Use `fps` for uniform timing, or frame objects with `delay` in seconds when frames need different durations. GIF stores delays in 0.01 second increments, so timing is rounded. `quality` is `0...1`; the default quantizes each frame to fit GIF’s 256-color palette without dithering. Use `1` only when every frame already has at most 256 exact colors.
|
|
688
|
+
|
|
689
|
+
Options:
|
|
690
|
+
|
|
691
|
+
- `width` / `height` - Required. Frame size.
|
|
692
|
+
- `fps` - Frames per second for uniform timing. Cannot be combined with per-frame `delay`. GIF stores delays in 0.01 second increments, so timing is rounded to the nearest increment.
|
|
693
|
+
- `playCount` - Total animation plays. Finite values must be integers from `1` to `65_536`. Use `'forever'` for infinite playback. Omit it to omit the loop extension. `playCount: 1` also omits the loop extension because that matches default GIF playback.
|
|
694
|
+
- `quality` - Default: `0.8`. `0...1`, where lower values quantize each frame more aggressively to fit GIF’s 256-color palette. Quantization is per-frame and does not dither. For photos and screenshots, keep the default or lower it. Use `1` only when every frame already has at most 256 exact colors.
|
|
695
|
+
|
|
696
|
+
Frames can be `Uint8Array` or `Uint8ClampedArray` RGBA pixels. Pixels are flat RGBA bytes: `[red, green, blue, alpha, ...]`.
|
|
697
|
+
|
|
698
|
+
For per-frame timing, use frame objects with `pixels` and `delay` in seconds. Delays are rounded to GIF’s 0.01 second increments:
|
|
699
|
+
|
|
700
|
+
@example
|
|
701
|
+
```
|
|
702
|
+
import {encodeAnimatedGIF} from '@cjser/sindresorhus__gifkit';
|
|
703
|
+
|
|
704
|
+
const bytes = encodeAnimatedGIF(frames, {
|
|
705
|
+
width: 640,
|
|
706
|
+
height: 480,
|
|
707
|
+
fps: 14,
|
|
708
|
+
playCount: 5,
|
|
709
|
+
quality: 0.7,
|
|
710
|
+
});
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
@example
|
|
714
|
+
```
|
|
715
|
+
import {encodeAnimatedGIF} from '@cjser/sindresorhus__gifkit';
|
|
716
|
+
|
|
717
|
+
const bytes = encodeAnimatedGIF([
|
|
718
|
+
{pixels: frame1, delay: 0.1},
|
|
719
|
+
{pixels: frame2, delay: 0.2},
|
|
720
|
+
], {
|
|
721
|
+
width: 640,
|
|
722
|
+
height: 480,
|
|
723
|
+
playCount: 5,
|
|
724
|
+
quality: 0.7,
|
|
725
|
+
});
|
|
726
|
+
```
|
|
727
|
+
*/
|
|
728
|
+
export function encodeAnimatedGIF(frames: AnimatedGIFFrame[], options: EncodeAnimatedGIFOptionsWithFPS): Uint8Array;
|
|
729
|
+
export function encodeAnimatedGIF(frames: AnimatedGIFFrameWithDelay[], options: EncodeAnimatedGIFOptionsWithFrameDelays): Uint8Array;
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
Renders image blocks as an iterable sequence of full logical-screen RGBA frames while applying transparency and disposal methods. Use this for playback or large GIFs where materializing every rendered frame would be wasteful.
|
|
733
|
+
|
|
734
|
+
Options:
|
|
735
|
+
|
|
736
|
+
- `background` - Default: `'gif'`. Use `'transparent'` to render the logical-screen background as transparent.
|
|
737
|
+
- `strict` - Default: `true`. Reject malformed render data like color indexes outside the active color table.
|
|
738
|
+
- `repeat` - Default: `true`. Repeat according to GIF `playCount` metadata. Missing metadata means one pass, a finite number means that many total passes, and `'forever'` means infinite playback. Set to `false` to render exactly one pass.
|
|
739
|
+
- `signal` - Optional abort signal. When aborted, iteration ends.
|
|
740
|
+
|
|
741
|
+
Yields:
|
|
742
|
+
|
|
743
|
+
- `left` / `top` - Frame source offset in logical-screen pixels.
|
|
744
|
+
- `width` / `height` - Frame source size.
|
|
745
|
+
- `delay` - Frame delay in seconds.
|
|
746
|
+
- `disposalMethod` - Advanced GIF compositing metadata kept so rendered frames can still be related back to the original GIF structure.
|
|
747
|
+
- `pixels` - `Uint8ClampedArray` of rendered full logical-screen RGBA bytes.
|
|
748
|
+
- `index` - Zero-based image-frame index within the current pass.
|
|
749
|
+
- `loopIndex` - Zero-based repetition index for this frame.
|
|
750
|
+
|
|
751
|
+
@example
|
|
752
|
+
```
|
|
753
|
+
import {decodeGIF, renderGIFFrameSequence} from '@cjser/sindresorhus__gifkit';
|
|
754
|
+
|
|
755
|
+
const gif = decodeGIF(bytes, {strict: false});
|
|
756
|
+
|
|
757
|
+
for (const frame of renderGIFFrameSequence(gif, {strict: false})) {
|
|
758
|
+
console.log(frame.pixels);
|
|
759
|
+
console.log(frame.delay);
|
|
760
|
+
}
|
|
761
|
+
```
|
|
762
|
+
*/
|
|
763
|
+
export function renderGIFFrameSequence(gif: GIF, options?: GIFFrameSequenceOptions): IterableIterator<RenderedGIFFrame>;
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
Renders image blocks to full logical-screen RGBA frames while applying transparency and disposal methods. Most users should use `decodeAnimatedGIF()` instead; use this when you need decoded GIF structure and rendered pixels.
|
|
767
|
+
|
|
768
|
+
Options:
|
|
769
|
+
|
|
770
|
+
- `background` - Default: `'gif'`. Use `'transparent'` to render the logical-screen background as transparent.
|
|
771
|
+
- `strict` - Default: `true`. Reject malformed render data like color indexes outside the active color table.
|
|
772
|
+
|
|
773
|
+
Returns:
|
|
774
|
+
|
|
775
|
+
- `width` / `height` - Logical screen size.
|
|
776
|
+
- `playCount` - Total animation plays. `'forever'` means infinite playback. Omitted when no loop extension was present.
|
|
777
|
+
- `frames` - Rendered full logical-screen RGBA frames.
|
|
778
|
+
- `frames[].left` / `frames[].top` - Frame source offset in logical-screen pixels.
|
|
779
|
+
- `frames[].width` / `frames[].height` - Frame source size.
|
|
780
|
+
- `frames[].delay` - Frame delay in seconds.
|
|
781
|
+
- `frames[].disposalMethod` - Advanced GIF compositing metadata kept so rendered frames can still be related back to the original GIF structure. `'unspecified'` leaves the choice to the decoder, `'keep'` keeps the pixels, `'restoreBackground'` clears them to the background, and `'restorePrevious'` restores the previous canvas before the next frame is drawn. gifkit already applies this when producing `frames[].pixels`, so use it only if you need to inspect or preserve the original animation metadata.
|
|
782
|
+
- `frames[].pixels` - `Uint8ClampedArray` of rendered full logical-screen RGBA bytes.
|
|
783
|
+
|
|
784
|
+
Rendering enforces internal logical-screen, rendered-output, render block-count, and image-block pixel limits to avoid huge allocations.
|
|
785
|
+
|
|
786
|
+
@example
|
|
787
|
+
```
|
|
788
|
+
import {decodeGIF, encodeGIF, renderGIFFrames} from '@cjser/sindresorhus__gifkit';
|
|
789
|
+
|
|
790
|
+
const bytes = encodeGIF({
|
|
791
|
+
width: 2,
|
|
792
|
+
height: 2,
|
|
793
|
+
globalColorTable: [
|
|
794
|
+
[0, 0, 0],
|
|
795
|
+
[255, 255, 255],
|
|
796
|
+
],
|
|
797
|
+
blocks: [{
|
|
798
|
+
type: 'image',
|
|
799
|
+
width: 2,
|
|
800
|
+
height: 2,
|
|
801
|
+
pixels: [0, 1, 1, 0],
|
|
802
|
+
}],
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
const gif = decodeGIF(bytes);
|
|
806
|
+
const rendered = renderGIFFrames(gif);
|
|
807
|
+
|
|
808
|
+
console.log(gif.version);
|
|
809
|
+
console.log(rendered.frames[0].pixels);
|
|
810
|
+
```
|
|
811
|
+
*/
|
|
812
|
+
export function renderGIFFrames(gif: GIF, options?: RenderOptions): RenderedGIF;
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
Use this when you have raw RGBA pixels, for example from a canvas or image decoder, and want the `pixels` and `colorTable` needed for an image block. It only works when the pixels already fit GIF’s palette model.
|
|
816
|
+
|
|
817
|
+
Converts RGBA pixels to GIF indexed pixels and a power-of-two color table without quantizing or dithering. Each unique opaque RGB color becomes a palette entry. All fully transparent pixels share one palette entry and set `transparentColorIndex`.
|
|
818
|
+
|
|
819
|
+
Throws if the image exceeds the internal pixel limit, uses more than 256 palette entries, or uses partial alpha. GIF only supports fully transparent or fully opaque pixels.
|
|
820
|
+
|
|
821
|
+
Options:
|
|
822
|
+
|
|
823
|
+
- `transparentColor` - Default: `[0, 0, 0]`. RGB value stored in the palette entry used for transparent pixels.
|
|
824
|
+
|
|
825
|
+
@example
|
|
826
|
+
```
|
|
827
|
+
import {indexedImage} from '@cjser/sindresorhus__gifkit';
|
|
828
|
+
|
|
829
|
+
const image = indexedImage(new Uint8ClampedArray([
|
|
830
|
+
255, 0, 0, 255,
|
|
831
|
+
0, 0, 0, 0,
|
|
832
|
+
]));
|
|
833
|
+
|
|
834
|
+
console.log(image.pixels);
|
|
835
|
+
console.log(image.colorTable);
|
|
836
|
+
```
|
|
837
|
+
*/
|
|
838
|
+
export function indexedImage(pixels: Uint8Array | Uint8ClampedArray, options?: IndexedImageOptions): IndexedImage;
|