Simple C++ one-header library for the creation of animated GIFs from image data.

Overview

gif-h

This one-header library offers a simple, very limited way to create animated GIFs directly in code. Those looking for particular cleverness are likely to be disappointed; it's pretty much a straight-ahead implementation of the GIF format with optional Floyd-Steinberg dithering. (It does at least use delta encoding - only the changed portions of each frame are saved.)

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.

Only RGBA8 is currently supported as an input format. (The alpha is ignored.)

Email me : ctangora -at- gmail -dot- com

Usage:

Create a GifWriter struct.

Pass the struct to GifBegin() to initialize values and write the file header.

Pass frames of the animation to GifWriteFrame().

Finally, call GifEnd() to close the file handle and free memory.

#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;
}
Issues
  • Resulting GIFs only have one frame

    Resulting GIFs only have one frame

    Hello! I have been trying to use gif.h for GIF recording in my application. Long story short, it works, with one flaw. The first frame is the only one kept. Here is a sample result:
    Result

    The code I used is available here:

    QImage &startImg = frames[0];
    GifWriter writer;
    GifBegin(&writer, tmpDir.absoluteFilePath("resulting.gif").toLocal8Bit().constData(), startImg.width(),
    startImg.height(), d);
    int i = 0;
    for (QImage &a : frames) {
        QByteArray alpha8((char *)a.bits(), a.byteCount());
        GifWriteFrame(&writer, (uint8_t *)alpha8.data(), a.width(), a.height(), d);
    }
    GifEnd(&writer);
    

    Thanks in advance!

    opened by ArsenArsen 14
  • Help required OpenCV Mat provided to GifWriteFrame

    Help required OpenCV Mat provided to GifWriteFrame

    Any help would be appreciated. I am trying to convert a video to GIF using OpenCV. Gif output is weird.

    Here is the code

    
        cv::Mat frame;
    
        GifWriter writer;
    
        bool success = video.read(frame);
    
        GifBegin(&writer, destFile.c_str(), frame.size().width, frame.size().height, 20);
    
        uint frameCounter = 0;
    
        while(success && frameCounter<=15){
    
            success = video.read(frame);
    
            GifWriteFrame(&writer,frame.data, frame.size().width, frame.size().height, 20);
    
            frameCounter++;
    
        }
    
        GifEnd(&writer);
    
        video.release();
    
    

    Thanks somegif

    opened by maxpaynestory 3
  • Any change of getting a C99 version of the library?

    Any change of getting a C99 version of the library?

    Hi, I would like to use gif-h on raylib to add simple .gif export functionality. That would be very useful for students to show and share their small games. Right now raylib offers automatic screenshot generation just pressing F12, some animated image would be great.

    I tried it, exporting every 10 frames, and it works ok (maybe a bit slow...) but raylib is C99 and to include gif-h it requires to be compiled as C++, it's not a big deal but it should be C99 to be included in the library.

    Also, would it be possible to adapt library to header-only style like STB libraries, I mean with GIF_IMPLEMENTATION define?

    opened by raysan5 3
  • Fix off-by-one error with treeSplitElt[] and treeSplit[].

    Fix off-by-one error with treeSplitElt[] and treeSplit[].

    According to calculation logic of treeRoot in GifGetClosestPaletteColor(), max treeRoot value may be 255, so sizes of treeSplitElt[] and treeSplit[] in struct GifPalette should be 256, and not 255. Currently there may be an out-of-bounds error when accessing pPal->treeSplitElt[treeRoot] in GifGetClosestPaletteColor() and other places too. Proposed patch fixes this.

    opened by oleg-derevenetz 2
  • Qt project: multiple definition of `XXX`

    Qt project: multiple definition of `XXX`

    error: multiple definition of `GifIMax(int, int)'
    error: multiple definition of `GifIMin(int, int)'
    error: multiple definition of `GifIAbs(int)'
    ......
    
    opened by sonichy 2
  • Is there a simple place to flip vertically

    Is there a simple place to flip vertically

    I'm generating a gif from an OpenGL application, which has a bottom-left based coordinate system, which means my gifs all come out upside down.

    Whilst it's straightforward enough to flip the buffer myself before passing it to GifWriteFrame it seems like it would be massively more efficient for the encoder to just know to read the pixels "backwards" so to speak - is there a simple place I could change this to be able to pass a "flip vertically" flag through the whole code?

    opened by benjymous 1
  • Memory Error

    Memory Error

    it is possible that treeRoot in GifGetClosestPaletteColor becomes 255. Put an assert(treeRoot < 255) into line 110 if you want to validate that statement. In line 113, treeRoot is used as index into GifPalette::treeSplitElt, which is a statically allocated array of size 255. This, of course, yields to a buffer overflow.

    Most of the time it goes well, it did crash yet. But it's a bug and it cost me 2 days to spot (no offense). I guess it can be fixed easily by changing the size of the two GifPalette::treeSplit*-arrays to 256 (maybe the 255 is a typo?)

    (I'm working on a PR)

    opened by pasbi 0
  • Undefined behaviour: Syscall param write(buf) points to uninitialised byte(s)

    Undefined behaviour: Syscall param write(buf) points to uninitialised byte(s)

    The following simple program creates a GIF composed of two completely white frames. But Valgrind's Memcheck complains about an uninitialized memory in GifBegin().

    #include "gif.h"
    
    static const int width = 200;
    static const int height = 200;
    
    static uint8_t image[width * height * 4];
    
    int main(int argc, char* argv[])
    {
      const char* filename = "mytest.gif";
      if (argc > 1) {
        filename = argv[1];
      }
    
      GifWriter writer;
      GifBegin(&writer, filename, width, height, 100);
    
      for (int i = 0; i < sizeof image; i += 4) {
        image[i] = image[i + 1] = image[i + 2] = 255;
        image[i + 3] = 0;  // not necessary
      }
      GifWriteFrame(&writer, image, width, height, 100);
      GifWriteFrame(&writer, image, width, height, 100);
    
      GifEnd(&writer);
      return 0;
    }
    
    [email protected]:~/src/gif-h$ valgrind ./a.out 
    ==98249== Memcheck, a memory error detector
    ==98249== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==98249== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
    ==98249== Command: ./a.out
    ==98249== 
    ==98249== Syscall param write(buf) points to uninitialised byte(s)
    ==98249==    at 0x49809B7: write (write.c:26)
    ==98249==    by 0x48F7E6C: [email protected]@GLIBC_2.2.5 (fileops.c:1181)
    ==98249==    by 0x48F9970: new_do_write (fileops.c:449)
    ==98249==    by 0x48F9970: _IO_new_do_write (fileops.c:426)
    ==98249==    by 0x48F9970: [email protected]@GLIBC_2.2.5 (fileops.c:423)
    ==98249==    by 0x48F8F67: [email protected]@GLIBC_2.2.5 (fileops.c:136)
    ==98249==    by 0x48EBE0E: [email protected]@GLIBC_2.2.5 (iofclose.c:53)
    ==98249==    by 0x10B744: GifEnd(GifWriter*) (gif.h:827)
    ==98249==    by 0x10B8D1: main (mytest.c:25)
    ==98249==  Address 0x4abb837 is 1,175 bytes inside a block of size 4,096 alloc'd
    ==98249==    at 0x4843839: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==98249==    by 0x48EBC23: _IO_file_doallocate (filedoalloc.c:101)
    ==98249==    by 0x48FAC6F: _IO_doallocbuf (genops.c:347)
    ==98249==    by 0x48F9EFF: [email protected]@GLIBC_2.2.5 (fileops.c:745)
    ==98249==    by 0x48F8694: _IO_new_file_xsputn (fileops.c:1244)
    ==98249==    by 0x48F8694: [email protected]@GLIBC_2.2.5 (fileops.c:1197)
    ==98249==    by 0x48ED066: fwrite (iofwrite.c:39)
    ==98249==    by 0x10B342: GifBegin(GifWriter*, char const*, unsigned int, unsigned int, unsigned int, int, bool) (gif.h:754)
    ==98249==    by 0x10B7DD: main (mytest.c:16)
    ==98249== 
    ==98249== 
    ==98249== HEAP SUMMARY:
    ==98249==     in use at exit: 0 bytes in 0 blocks
    ==98249==   total heap usage: 7 allocs, 7 frees, 4,678,872 bytes allocated
    ==98249== 
    ==98249== All heap blocks were freed -- no leaks are possible
    ==98249== 
    ==98249== Use --track-origins=yes to see where uninitialised values come from
    ==98249== For lists of detected and suppressed errors, rerun with: -s
    ==98249== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    
    opened by mymedia2 0
  • docs: fix simple typo, palete -> palette

    docs: fix simple typo, palete -> palette

    There is a small typo in gif.h.

    Should read palette rather than palete.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 0
  • Here's a c++ implementation of your code to share

    Here's a c++ implementation of your code to share

    Hi Charlie,

    I've implemented a c++ class based on this project, gif-h.

    You can find it here. Feel free to link to it, etc.; I have of course linked my project to yours.

    Also, credit is given here.

    Thanks so much for your work. Much appreciated!

    opened by fyngyrz 3
  • fix bug with diff calculation (compress even more) + transparency support + ability to specify palette

    fix bug with diff calculation (compress even more) + transparency support + ability to specify palette

    This introduces ability to make images with transparent background if alpha channel is specified. Also, fixes problems with diff calculation and now files compressed even more. Also, this introduces ability to specify palette (I used it for making constant palette for all the frames.)

    opened by Evil-Spirit 6
Owner
Charlie Tangora
Charlie Tangora
ADOP: Approximate Differentiable One-Pixel Point Rendering

ADOP: Approximate Differentiable One-Pixel Point Rendering

Darius Rückert 1.8k Jun 24, 2022
Ncnn version demo of [CVPR21] LightTrack: Finding Lightweight Neural Network for Object Tracking via One-Shot Architecture Search

LightTrack: Finding Lightweight Neural Networks for Object Tracking via One-Shot Architecture Search (ncnn) The official implementation by pytorch: ht

null 18 Jun 13, 2022
Collection of Fluid Structure Interaction codes, used for one of my PhD courses

Continuum mechanics and fluid-structure interaction problems mathematical modeling and numerical approximation Fluid-structure interaction (FSI) refer

Luca Heltai 2 Jan 23, 2022
a generic C++ library for image analysis

VIGRA Computer Vision Library Copyright 1998-2013 by Ullrich Koethe This file is part of the VIGRA computer vision library. You may use,

Ullrich Koethe 368 Jun 25, 2022
A easy-to-use image processing library accelerated with CUDA on GPU.

gpucv Have you used OpenCV on your CPU, and wanted to run it on GPU. Did you try installing OpenCV and get frustrated with its installation. Fret not

shrikumaran pb 4 Aug 14, 2021
Tiny OpenEXR image loader/saver library

Tiny OpenEXR image library. tinyexr is a small, single header-only library to load and save OpenEXR (.exr) images. tinyexr is written in portable C++

Syoyo Fujita 507 Jun 23, 2022
Video, Image and GIF upscale/enlarge(Super-Resolution) and Video frame interpolation. Achieved with Waifu2x, SRMD, RealSR, Anime4K, RIFE, CAIN, DAIN and ACNet.

Video, Image and GIF upscale/enlarge(Super-Resolution) and Video frame interpolation. Achieved with Waifu2x, SRMD, RealSR, Anime4K, RIFE, CAIN, DAIN and ACNet.

Aaron Feng 7k Jun 27, 2022
Super Mario Remake using C++, SFML, and Image Processing which was a project for Structure Programming Course, 1st Year

Super Mario Remake We use : C++ in OOP concepts SFML for game animations and sound effects. Image processing (Tensorflow and openCV) to add additional

Omar Elshopky 5 Jun 19, 2022
The code implemented in ROS projects a point cloud obtained by a Velodyne VLP16 3D-Lidar sensor on an image from an RGB camera.

PointCloud on Image The code implemented in ROS projects a point cloud obtained by a Velodyne VLP16 3D-Lidar sensor on an image from an RGB camera. Th

Edison Velasco Sánchez 4 Apr 21, 2022
NVIDIA Texture Tools samples for compression, image processing, and decompression.

NVTT 3 Samples This repository contains a number of samples showing how to use NVTT 3, a GPU-accelerated texture compression and image processing libr

NVIDIA DesignWorks Samples 31 Jun 13, 2022
NVIDIA Image Scaling SDK

NVIDIA Image Scaling SDK v1.0 The MIT License(MIT) Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. Permission is hereby grante

NVIDIA GameWorks 346 Jun 23, 2022
Using image classification with ConvMixer

Japanese Handwriting Classification with Fragment Shaders NOTE: This was built and tested with Unity 2019.4.31f1 using built-in render pipeline, there

null 8 Feb 21, 2022
NCNN implementation of Real-ESRGAN. Real-ESRGAN aims at developing Practical Algorithms for General Image Restoration.

Real-ESRGAN ncnn Vulkan This project is the ncnn implementation of Real-ESRGAN. Real-ESRGAN ncnn Vulkan heavily borrows from realsr-ncnn-vulkan. Many

Xintao 219 Jun 22, 2022
DeepI2P - Image-to-Point Cloud Registration via Deep Classification. CVPR 2021

#DeepI2P: Image-to-Point Cloud Registration via Deep Classification Summary Video PyTorch implementation for our CVPR 2021 paper DeepI2P. DeepI2P solv

Li Jiaxin 121 Jun 14, 2022
Insight Toolkit (ITK) is an open-source, cross-platform toolkit for N-dimensional scientific image processing, segmentation, and registration

ITK: The Insight Toolkit C++ Python Linux macOS Windows Linux (Code coverage) Links Homepage Download Discussion Software Guide Help Examples Issue tr

Insight Software Consortium 1k Jun 26, 2022
High dynamic range (HDR) image comparison tool for graphics people. With an emphasis on OpenEXR images.

tev — The EXR Viewer A high dynamic range (HDR) image comparison tool for graphics people. tev allows viewing images through various tonemapping opera

Thomas Müller 647 Jun 21, 2022
An open source iOS framework for GPU-based image and video processing

GPUImage Brad Larson http://www.sunsetlakesoftware.com @bradlarson [email protected] Overview The GPUImage framework is a BSD-licensed iO

Brad Larson 20k Jul 1, 2022
the implementations of 'Parzen-Window Based Normalized Mutual Information for Medical Image Registration'

ImageRegistration_NormalisedMutualInformation 代码复现论文《Parzen-Window Based Normalized Mutual Information for Medical Image Registration》 利用归一化互信息对医学图像进行

gtc1072 3 Apr 4, 2022
ncnn demo of DocTr: Document Image Transformer for Geometric Unwarping and Illumination Correction

DocTr-ncnn ncnn demo of DocTr: Document Image Transformer for Geometric Unwarping and Illumination Correction model support: 1.Document Segmentation 2

FeiGeChuanShu 21 Jul 1, 2022