Skip to content

Commit 6f3309a

Browse files
committed
fix: solve the problem of being unable to distinguish between no loop and infinite loop.
1 parent 5f186a3 commit 6f3309a

File tree

2 files changed

+53
-40
lines changed

2 files changed

+53
-40
lines changed

README.md

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,57 @@
11
# gify
2+
23
JavaScript API for decoding/parsing information from animated GIFs using ArrayBuffers.
34

45
## Why?
6+
57
Once I saw [vinepeek](http://www.vpeeker.com/), I immediately wanted to build a similar site for animated GIFs. The only problem was, there was no way to quickly determine the duration of an animated GIF, which varies in different browsers. Thus, gify was born over a weekend.
68

79
## Requirements
10+
811
gify requires [jDataView](https://github.com/vjeux/jDataView) for reading binary files. Please pull the latest from their repository.
912

1013
## Methods
11-
* **isAnimated**(sourceArrayBuffer) (bool)
12-
* **getInfo**(sourceArrayBuffer) (gifInfo)
14+
15+
- **isAnimated**(sourceArrayBuffer) (bool)
16+
- **getInfo**(sourceArrayBuffer) (gifInfo)
1317

1418
## info Properties
15-
* **valid** (bool) - Determines if the GIF is valid.
16-
* **animated** (bool) - Determines if the GIF is animated.
17-
* **globalPalette** (bool) - Determines if the GIF has a global color palette.
18-
* **globalPaletteSize** (int) - Size of the global color palette.
19-
* **globalPaletteColorsRGB** ([r,g,b]) - An array of objects containing the R, G, B values of the color palette. ([Beppe](https://github.com/Beppe))
20-
* **height** (int) - Canvas height.
21-
* **width** (int) - Canvas width.
22-
* **loopCount** (int) - Total number of times the GIF will loop. 0 represents infitine.
23-
* **images** ([images]) - Array of images contained in the GIF.
24-
* **isBrowserDuration** (bool) - If any of the delay times are lower than the [minimum value](http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility), this value will be set to true.
25-
* **duration** (int) - Actual duration calculated from the delay time for each image. If isBrowserDuration is false, you should use this value.
26-
* **durationIE** (int) - Duration for Internet Explorer (16fps)
27-
* **durationSafari** (int) - Duration for Safari in milliseconds (50fps)
28-
* **durationFirefox** (int) - Duration for Firefox in milliseconds (50fps)
29-
* **durationChrome** (int) - Duration for Chrome in milliseconds (50fps)
30-
* **durationOpera** (int) - Duration for Opera in milliseconds (50fps)
19+
20+
- **valid** (bool) - Determines if the GIF is valid.
21+
- **animated** (bool) - Determines if the GIF is animated.
22+
- **globalPalette** (bool) - Determines if the GIF has a global color palette.
23+
- **globalPaletteSize** (int) - Size of the global color palette.
24+
- **globalPaletteColorsRGB** ([r,g,b]) - An array of objects containing the R, G, B values of the color palette. ([Beppe](https://github.com/Beppe))
25+
- **height** (int) - Canvas height.
26+
- **width** (int) - Canvas width.
27+
- **loopCount** (int) - Total number of times the GIF will loop. `0` represents infitine. `-1` represents display once.
28+
- **images** ([images]) - Array of images contained in the GIF.
29+
- **isBrowserDuration** (bool) - If any of the delay times are lower than the [minimum value](http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility), this value will be set to true.
30+
- **duration** (int) - Actual duration calculated from the delay time for each image. If isBrowserDuration is false, you should use this value.
31+
- **durationIE** (int) - Duration for Internet Explorer (16fps)
32+
- **durationSafari** (int) - Duration for Safari in milliseconds (50fps)
33+
- **durationFirefox** (int) - Duration for Firefox in milliseconds (50fps)
34+
- **durationChrome** (int) - Duration for Chrome in milliseconds (50fps)
35+
- **durationOpera** (int) - Duration for Opera in milliseconds (50fps)
3136

3237
## image Properties
33-
* **identifier** (string) - Image identifier (frame number or embeded string).
34-
* **top** (int) - Image top position (Y).
35-
* **left** (int) - Image left position (X).
36-
* **height** (int) - Image height.
37-
* **width** (int) - Image width.
38-
* **localPalette** (bool) - Image has a local color palette.
39-
* **localPaletteSize** (int) - Size of the local color palette.
40-
* **interlace** (bool) - Image is/is not interlaced.
41-
* **delay** (int) - Delay time in milliseconds.
42-
* **text** (string) - frame text. aka Plain Text Extension.
43-
* **comments** ([comments]) - Array of comment strings.
44-
* **disposal** (int) - Disposal method. (0-7). See [this](http://www.w3.org/Graphics/GIF/spec-gif89a.txt) for more details.
38+
39+
- **identifier** (string) - Image identifier (frame number or embeded string).
40+
- **top** (int) - Image top position (Y).
41+
- **left** (int) - Image left position (X).
42+
- **height** (int) - Image height.
43+
- **width** (int) - Image width.
44+
- **localPalette** (bool) - Image has a local color palette.
45+
- **localPaletteSize** (int) - Size of the local color palette.
46+
- **interlace** (bool) - Image is/is not interlaced.
47+
- **delay** (int) - Delay time in milliseconds.
48+
- **text** (string) - frame text. aka Plain Text Extension.
49+
- **comments** ([comments]) - Array of comment strings.
50+
- **disposal** (int) - Disposal method. (0-7). See [this](http://www.w3.org/Graphics/GIF/spec-gif89a.txt) for more details.
4551

4652
### Example
47-
``` json
53+
54+
```json
4855
{
4956
"valid": true,
5057
"globalPalette": true,
@@ -139,8 +146,10 @@ gify requires [jDataView](https://github.com/vjeux/jDataView) for reading binary
139146
```
140147

141148
## Resources
142-
* [What's In A GIF - Bit by Byte](http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp) - Hands down the best write up on GIFs I've found.
143-
* [GIF98](http://www.w3.org/Graphics/GIF/spec-gif89a.txt) - GIF98 RFC.
144-
* [Animated GIF Frame Rate by Browser](http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility) - An awesome breakdown of how each browser renders animated GIFs. Thanks to Jeremiah Johnson for doing the hard work.
145-
* [GIF Format](http://www.onicos.com/staff/iz/formats/gif.html) - GIF blocks.
146-
* [Hexfiend](http://ridiculousfish.com/hexfiend/) - Awesome open source HEX editor (OSX)
149+
150+
- [What's In A GIF - Bit by Byte](http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp) - Hands down the best write up on GIFs I've found.
151+
- [GIF98](http://www.w3.org/Graphics/GIF/spec-gif89a.txt) - GIF98 RFC.
152+
- [Animated GIF Frame Rate by Browser](http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility) - An awesome breakdown of how each browser renders animated GIFs. Thanks to Jeremiah Johnson for doing the hard work.
153+
- [GIF Format](http://www.onicos.com/staff/iz/formats/gif.html) - GIF blocks.
154+
- [Hexfiend](http://ridiculousfish.com/hexfiend/) - Awesome open source HEX editor (OSX)
155+
- [Netscape Looping Application Extension (GIF Unofficial Specification)](http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension) - About Loop Count.

gify.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ var gify = (function () {
7878
globalPalette: false,
7979
globalPaletteSize: 0,
8080
globalPaletteColorsRGB: [],
81-
loopCount: 0,
81+
loopCount: -1, // `-1` means no loop
8282
height: 0,
8383
width: 0,
8484
animated: false,
@@ -170,9 +170,13 @@ var gify = (function () {
170170
var subBlock = readSubBlock(view, pos, true);
171171
switch (type) {
172172
case 0xff: // APPLICATION EXTENSION
173-
/* since multiple application extension blocks can
174-
occur, we need to make sure we're only setting
175-
the loop count when the identifer is NETSCAPE */
173+
/**
174+
* Since multiple application extension blocks can occur,
175+
* we need to make sure we're only setting the loop count when the identifer is NETSCAPE.
176+
*
177+
* If GIF exported by Photoshop without loop, the Application Extension does not contain the NETSCAPE identifier, only the XMP Data identifier.
178+
* If GIF loops forever or loops n times (n > 0), the NETSCAPE identifier must be present in the Application Extension.
179+
*/
176180
var identifier = view.getString(8, pos + 1);
177181
if (identifier === 'NETSCAPE') {
178182
info.loopCount = view.getUint8(pos + 14, true);

0 commit comments

Comments
 (0)