Animated GIF export rounding frame durations


I have a sprite where each frame needs to last exactly 67 milliseconds. Saving as ASE retains this, but exporting to GIF floors it to 60. Installer version v1.2.7.3-x64 Windows 7 SP1 64-bit, but I believe this may happen on other platforms as well. I use 64-bit Linux more prominently than Windows, so if I manage to test this on there before someone else does, I’ll let you know.


As a workaround, I would export as a png sequence and take that into a program that can export the gif. Like a video editing program or Photoshop. Basically another program that is flexible enough to do 67 milliseconds/frame


I’ve been exporting PNG sequences and assembling aPNG’s with apngasm. 67 ms was the closest I could get to 5 frames at 60FPS, so simply assembling an aPNG with 5/60 on its relevant frames is much better. The only hitch with that is Aseprite oddly can’t even view them properly, so I have to use something else.


I may be misremembering but I believe the export issue is not a bug with aseprite but rather a limit of animated GIFs.
Animated gifs can only have frame durations in increments of 1/100 of a second (0.01s, 0.02s etc) This means it’s going to round to 60 ms or 70 ms (since 67 ms is 0.067s, too many decimal places for poor old GIFs!)
In fact some browsers/players only play gifs with frame durations of 20 ms (0.02s per frame = 50 fps) or higher (slower than 50fps). Not sure if that’s true any more.

So you can’t EVER have a 60fps gif (which is ~16.67 ms per frame) which means you can never have a gif that cycles at exactly 1/3rd of a second (since that’s 333 ms). You can have it cycle at 330 ms which is pretty close! For an animation of five frames that would be frame timings of 70, 70, 70, 60, 60 ms (in any order, adds to 330ms).

This is unfortunately the GIF format limitations.

I think this should be made clear when exporting to GIF in aseprite as a tooltip so you can see the consequence.


I guess my biggest mistake was the assumption that Aseprite knew what it was talking about when it gave me the option. Why does it even use milliseconds when it can only export animations in centiseconds? I have to write down the frame data somewhere before I export to a series of PNG’s and assemble that into an aPNG with something else, and only then do I get an accurate frame duration for what I’m working with.
I know the ASE format seems to use milliseconds, but why that and not anything else? All of these repeating decimal points on thirds with base-ten makes it almost a necessity to process it as a fraction instead.


The centiseconds limitation is a .gif limitation, not an Aseprite limitation. As @JayW said maybe a warning when exporting to GIF files should be enough.

The duration in milliseconds was just a decision made 17 years ago. What would you prefer?


I would personally prefer numerator and denominator values for a fractional duration, as is used in the aPNG extension. This lets me set the frame’s duration to match a multiple of the target framerate, for example.
Sorry for the harsh tone in the prior message, I think I forgot to proofread it.


In that case I guess a decimal point would make the job. And probably some alternative ways to specify the duration of all frames (e.g. FPS). Related to #496.


In that case I guess a decimal point would make the job.

It’s a tough one because decimal point doesn’t capture most common frame rates (12, 15, 24, 30, 60). All of those are recurring milliseconds per frame and only work as fractions.

I think as your link an FPS setting would be strongest.

The other thing is that this is ONLY relevant for animations played within aseprite (possibly flc, fli files?) unless you later add an export to movie option. None of those frame rates are supported by animated gif (50/25/20/10 fps is though).

I would guess that most of the use of this program is to create spritesheets or png sequences for using in games or other compositing programs anyway.


Personally I’m very happy with that 17 years old decission, so I really hope that if you add other options (FPS for example) you’ll also preserve the option of duration in miliseconds :slight_smile:


A decimal point would miss the point, I’d say. To elaborate on what JayW had said, decimal points don’t actually help at all if you need anything that isn’t just a multiple of a half or a fifth of a second. No base is perfect, which is why I suggested the fractional notation that is used in the aPNG extension. This is the only way to have any frame duration. Not even if you just specify a framerate (1/n) would you be able to create every possible frame duration, it wouldn’t even allow for any duration longer than a single second.
And as JJHaggar has pointed out, you definitely shouldn’t drop millisecond and centisecond frame duration options entirely, you still need to support GIF89a somehow.


I have to think about this issue a little more. Mainly to think about this new possible FPS option and the future plans for a new time-based timeline mode for v1.3. From the point of view of a time-based timeline, the FPS doesn’t make any sense, because layers (cels) are just images that appear in a given period of time (with a well defined start and end).


In regards to FPS vs Duration for frame rate input, I think both are good, but for different situations.

Personally I’d just like to see another value box below that shows FPS, that gets updated when you edit the other box and vice versa.

So if you type in 15 in the FPS box it shows 66.666667 in the Duration box, and if you then type in 100 in the Duration box it changes the FPS to 10. Lets you choose what format to input and quickly displays the converted value in the other. I don’t know how any of this relates to the updated timeline stuff you have planned so this is just in context to the current version. (1.2.8)


Having two text fields that affect each-other can easily encourage people to treat one as a parsed form of the other, when really only one field would ever be valid at any given time. A switch should be easy enough, and contribute much less to interface clutter. I’d only consider the ms value for compatibility’s sake; there’s enough ASE’s and GIF’s floating around to make milliseconds kind of important, but it has no real use beyond that. n/d allows for n/1000 anyway, which is the very definition of ‘milliseconds’. Since ASE is a custom file format, it should be possible to have n/d OR ms duration be per-frame, rather than for the whole file, though it would be little more than a text label in effect.
I want to emphasize my opposition to the idea of an FPS setting. 1/d is still way too restrictive for my needs.


As far as I know, most game engines deal with animations as sequences of frames of given durations, and these durations are usually implemented as floats (if the base unit is seconds) or integers (if the base unit is milliseconds or microseconds). These types all fail to accurately reproduce durations such as 1/30 or 1/60 seconds. So, Aseprite’s use of integer milliseconds makes sense for more than just GIFs.

I suspect the limitation of floats and integers for durations is why aPNG uses the n/d format, it’s the only way to accurately preserve such durations, even if they’re not always accurately reproduced during playback.

Although n/d is the ideal option from a data accuracy standpoint, I think allowing a decimal point and precision down to the microsecond (e.g. 16.667ms) would be the most practical option, as it makes for the simplest UI (just a simple single textbox, like it is currently), is compatible with the existing milliseconds system, and plays well with timelines, while still allowing high precision. 16667/1000000 isn’t 1/60, but it sure is close, and it’s much closer than 17/1000.

If someone wants to get really fancy, it would even be possible to write an aPNG exporter that automatically detects approximate n/(3m) durations and provides the option to automatically convert these to the appropriate n/d (e.g. 16.667 -> 1/60, 958.333 -> 23/24). I bring up n/(3m) specifically because many common framerates are multiples of 3, and other common “easy” numbers generally work just fine as ms or µs (n/1000 or n/1000000).