gif-h writes animated GIFs from C++ in three calls and one header
Simple C++ one-header library for the creation of animated GIFs from image data.
At a glance
- What is it?
- gif-h is a single-header C++ library for producing animated GIF files directly in code, with delta encoding so only changed regions are stored and optional Floyd-Steinberg dithering on the way out. It is deliberately limited, only RGBA8 input with the alpha ignored, and the resulting files are often quite large, which the documentation says outright.
- Who is it for?
- Adopt gif-h if you need a program to emit an animated GIF as a side effect, such as a build step that renders a preview or a tool that dumps a short animation, and you want to avoid pulling in an image library. Do not adopt it for output quality work, because the documentation is clear that it is a straight-ahead implementation, that the resulting files are often quite large, and that the alpha channel is ignored.
- Can I use it commercially?
- Yes. Unlicense is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 34 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One header, three calls, and no dependency
gif-h is a one-header library for the creation of animated GIFs from image data, and the whole interface fits in a struct and three functions.
The usage sequence is: create a GifWriter struct, pass the struct to GifBegin() to initialize values and write the file header, pass frames of the animation to GifWriteFrame(), and finally call GifEnd() to close the file handle and free memory.
That is the entire API surface as described, and it is the reason the library can be described as one-header. There is no build step to speak of, no library to link, no configuration. You include the header and the calls are there.
The framing in the repository description is simple: a simple C++ one-header library for the creation of animated GIFs from image data. And the honest part of the documentation is right at the top. Those looking for particular cleverness are likely to be disappointed, since it is pretty much a straight-ahead implementation of the GIF format with optional Floyd-Steinberg dithering.
The one thing it does do beyond the most naive approach is delta encoding, which only saves the changed portions of each frame.
The demo is the whole tutorial
The example in the documentation is a complete program, and it is short enough to be the entire guide.
#include <vector>
#include <cstdint>
#include <gif.h>
int main()
{
int width = 100;
int height = 200;
std::vector<uint8_t> black(width * height * 4, 0);
std::vector<uint8_t> white(width * height * 4, 255);
auto fileName = "bwgif.gif";
int delay = 100;
GifWriter g;
GifBegin(&g, fileName, width, height, delay);
GifWriteFrame(&g, black.data(), width, height, delay);
GifWriteFrame(&g, white.data(), width, height, delay);
GifEnd(&g);
return 0;
}Everything worth knowing about the API is in those lines. The frame data is a plain contiguous buffer of uint8_t, sized as width times height times four, which is the RGBA8 layout. The buffer is passed with a pointer to its first element, so the library does not care where the pixels came from: a vector, a malloc'd block or a decoded image.
The frame dimensions are passed on every call rather than remembered from GifBegin, which keeps the writer stateless about the frame size and lets the caller vary it if it wants to.
The delay is passed both to GifBegin and to GifWriteFrame, in hundredths of a second, so the frame timing is set per frame rather than fixed once for the animation. In this example the same value of 100 is used for both the header and each frame, which is how a constant frame rate is expressed.
The frames here are deliberately the simplest possible: one all-black and one all-white, so the demo produces a two-frame animation with a hard cut between them.
Delta encoding, and why the files are still large
The GIF format stores each frame as an image, and a naive writer would write the whole image every time. gif-h does not, and the documentation calls this out as the one thing beyond the plain approach: it does at least use delta encoding, so only the changed portions of each frame are saved.
That is worth a lot when the animation is mostly static, which is the common case for a UI recording or a generated plot that changes in one region. In the demo, the second frame is entirely different from the first, so delta encoding has nothing to work with there, but in a real animation with a moving element on a fixed background it is the difference between a file that scales and one that does not.
Even so, the documentation sets the expectation plainly: so resulting files are often quite large. The hope is that it will be handy nonetheless as a quick and easily-integrated way for programs to spit out animations.
So the trade is stated rather than hidden. You get a trivial integration and a working file, and you give up file size. Whether that is acceptable depends on where the GIF goes: a preview in a web page, a bug report attachment or a chat message is a different requirement from a deliverable animation.
The library does not mention palette quantisation, and the fact that the input is RGBA8 rather than a palette is the reason the output is heavy. Converting a truecolour buffer to the limited colour set a GIF supports is the expensive part, and that is not what this implementation does.
RGBA8 only, and the alpha that goes nowhere
Only RGBA8 is currently supported as an input format, and the alpha is ignored.
That single sentence defines the scope of the library. The buffer is four bytes per pixel, and the fourth byte is read and discarded. There is no transparency in the output, and there is no way to express a partially transparent frame.
For the common case, which is an opaque animation, this is fine and it is a reasonable simplification. The four bytes per pixel still have to be supplied even though the alpha is not used, which is a small waste but keeps the layout simple and matches the way images are usually stored.
It does mean the library cannot be dropped into a pipeline that already handles transparency, such as a UI recorder that captures an alpha channel. In that case you would have to composite the frames against something first, and the result would be a GIF with a background baked in.
The dithering option sits in the same category of a deliberate limit. Floyd-Steinberg dithering is offered as an option, and it is the standard approach for approximating colours that a GIF palette cannot represent, at the cost of a noisier image. Since the implementation writes truecolour data rather than building a palette, the dithering is what keeps the appearance of a smooth gradient acceptable.
The repository is small to match the library: a LICENSE, a README, the gif.h header itself, a gif-h-demo.cpp demo file, and a .github and .vscode directory. There is no build system, no test suite directory and no package manifest, which is consistent with a project whose entire distribution mechanism is one file you copy into your source tree.
The public domain, and a library maintained on the side
The licence is the Unlicense, which is the most permissive option available for software, and that is a sensible fit for a single-header library that people are expected to vendor directly into their own source tree.
The Unlicense places the code in the public domain with a fallback licence, which means there is no attribution requirement and no copyleft obligation. A project that wants to embed a GIF writer in a commercial application does not have to negotiate anything.
The repository is not archived, and the last push was on 2026-09-18, so the header is still being touched. There are no GitHub releases, which is unsurprising for a library that is consumed by copying gif.h into a project rather than by installing a package.
The primary language is listed as C, though the demo and the API are C++ and the header is included as gif.h, which is the usual convention for a C-compatible interface.
The maintainer gives a direct email address, with the characters spelled out around the at sign, which is the way contact details were often written in documentation of this vintage. For a library this small, that is a reasonable way to be reachable, and it is a reminder that when a project has no issue tracker workflow, the maintainer is the escalation path.
The practical summary is that this is a tool for a narrow job, done in one file, with the limitations stated up front rather than discovered later.
Editorial conclusion
Adopt gif-h if you need a program to emit an animated GIF as a side effect, such as a build step that renders a preview or a tool that dumps a short animation, and you want to avoid pulling in an image library. Do not adopt it for output quality work, because the documentation is clear that it is a straight-ahead implementation, that the resulting files are often quite large, and that the alpha channel is ignored. Before you use it, check two things: that your frames are RGBA8 buffers, since that is the only supported input format, and that the file size does not matter much, because delta encoding reduces the repeated regions but not the cost of the frames that genuinely change.
Frequently asked questions
How do I create an animated GIF with gif-h?
Create a GifWriter struct, call GifBegin to initialise it and write the file header, call GifWriteFrame for each frame of the animation, and call GifEnd at the end to close the file handle and free memory. The demo in the README shows the whole sequence for a two-frame animation.
What pixel format does gif-h accept?
Only RGBA8 is currently supported as an input format, and the alpha is ignored. Frame data is passed as a contiguous buffer of uint8_t sized as width times height times four, with the dimensions given on each frame call.
How does gif-h keep the file size down?
It uses delta encoding, so only the changed portions of each frame are saved rather than the whole image. The documentation is still clear that resulting files are often quite large, since the implementation is a straight-ahead one without palette quantisation.
Is gif-h suitable for images with transparency?
No. The alpha channel of the RGBA8 input is read and ignored, so the output has no transparency. A pipeline that needs transparency would have to composite the frames against a background before writing them.
What licence is gif-h released under?
The Unlicense, which places the code in the public domain with a fallback licence, so there is no attribution requirement and no copyleft obligation. The repository is not archived and the last push was on 2026-09-18, with no GitHub releases published.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/charlietangora-gif-h)Was this useful?