• Stars
    star
    363
  • Rank 117,374 (Top 3 %)
  • Language
    C
  • License
    Apache License 2.0
  • Created over 4 years ago
  • Updated 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An optimized GIF decoder suitable for microcontrollers and PCs

AnimatedGIF

Copyright (c) 2020 BitBank Software, Inc.
Written by Larry Bank
[email protected]

I optimize other people's code for a living. This library is a good example of the kind of work I do for my commercial clients; it contains many unique and clever optimizations that allows it to perform better than anything else available. I'm happy to contribute optimized libraries to the open source community in addition to working on commercial projects. Whatever platform you're using, I can make significant improvements to your native code. Please contact me so that I can show you how.

AnimatedGIF

I started working with image and video files around 1989 and soon turned my interest into a Document Imaging product based on my own imaging library. Over the years I added support for more and more formats until I had supported all of the standard ones, including DICOM. I sold my Document Imaging business in 1997, but still found uses for my imaging code in other projects such as retro gaming. I recently went looking to see if there was a good GIF player for Arduino and only found Adafruit's library. Unfortunately it only runs on their ATSAMD51 boards. I thought it would be possible to use my old code to create a universal GIF player that could run on any MCU/SoC with at least 24K of RAM, so I started modifying my old GIF code for this purpose. The focus of this project is speed and to use as little RAM as possible, so there are some limitations.

Limitations

To save memory, the code limits the maximum image width to 320 pixels. This is just a constant defined in AnimatedGIF.h, so you can set it larger if you like. Animated GIF images have a lot of options to save space when encoding the changes from frame to frame. Many of the tools which generate animated GIFs don't make use of every option and that's helpful because the frame disposal options are not supported in the library code. They can be implemented in your drawing callback if you want. The reason they're not provided with this code is because one of the image disposal options requires you to keep an entire copy of the previous frame and this would prevent it from working on low memory MCUs. If would also require dynamic memory allocation which is another area I avoided with this code.

Designed for Speed

My work is always focused on code optimization, so this project is no different. I've profiled this code and optimized it for 32-bit CPUs. I discovered while testing it that seeking on micro SD cards (on Arduino) is very very slow. I had to use a little extra RAM to buffer incoming data to avoid seeking. The code does need to seek, but it's done very rarely. I also wrote code to buffer and de-chunk some of the incoming LZW data to avoid checking for chunk boundaries in the inner decode loop. There are a number of clever optimizations that should allow this to run faster than any existing GIF solutions on Arduino boards. The speed gained from my decoder will be lost if it takes too long to display the pixels. For this reason, the GIFDRAW callback passes an RGB565 palette in the byte order of your choosing and the example sketches uses functions to write entire lines of pixels to the SPI TFT displays in a single shot. If you implement your own GIFDRAW callback and have to pass 1 pixel at a time to whatever display device you're using, this will cause a major slowdown in the display of the frames.

A note about performance

The chart above shows the total time to decode an 8-frame sequence included in the test_images folder. The decoding speed of your particular image depends on the complexity (how much compressed data) and if/how transparent pixels are used. Small runs of transparent pixels will interfere with the performance of displaying the image on an SPI LCD. This particular image doesn't use transparency, so the time is purely for decoding the data.

Features:

  • Supports any MCU with at least 24K of RAM (Cortex-M0+ is the simplest I've tested).
  • Optimized for speed; the main limitation will be how fast you can copy the pixels to the display. You can use SPI+DMA to help.
  • GIF image data can come from memory (FLASH/RAM), SDCard or any media you provide.
  • GIF files can be any length, (e.g. hundreds of megabytes)
  • Simple C++ class and callback design allows you to easily add GIF support to any application.
  • The C code doing the heavy lifting is completely portable and has no external dependencies.
  • Does not use dynamic memory (malloc/free/new/delete), so it's easy to build it for a minimal bare metal system.

Acquiring GIF files to play:

You'll notice that the images provided in the test_images folder have been turned into C code. Each byte is now in the form 0xAB so that it can be compiled into your program and stored in FLASH memory alongside your other code. You can use a command I wrote called image_to_c (https://github.com/bitbank2/image_to_c) to convert a binary file into this type of text. If you use another tool, make sure to add a const modifier in front of the GIF data array to ensure that it gets written to FLASH and not RAM by your build environment.

The Callback functions:

One of the reasons that this is apparently the first universal GIF library for Arduino is because the lack of available RAM and myriad display options would make it difficult to support all MCUs and displays properly. I decided that to solve this issue, I would isolate the GIF decoding from the display and file I/O with callback functions. This allows the core code to run on any system, but you need to help it a little. At a minimum, your code must provide a function to draw (or store) each scan line of image. If you're playing a GIF file from memory, this is the only function you need to provide. In the examples folder there are multiple sketches to show how this is done on various display libraries. For reading from SD cards, 4 other functions must be provided: open, close, read, seek. There is an example for implementing these in the examples folder as well.

Note:

If you're using the ESP32 or ESP8266 and playing GIF images stored in RAM, you'll need to provide the 4 file callback functions or modify the existing ones because RAM and FLASH are in different address spaces (Harvard architecture). The code assumes the source of the GIF data is in FLASH and uses memcpy_P() instead of memcpy() to access it.

The API:

Please consult the Wiki for detailed info about each method exposed by the AnimatedGIF class.


If you find this code useful, please consider sending a donation or becoming a Github sponsor.

paypal

More Repositories

1

JPEGDEC

An optimized JPEG decoder suitable for microcontrollers and PCs.
C
399
star
2

Thermal_Printer

Arduino library to draw text and graphics on BLE thermal printers
C
373
star
3

BitBang_I2C

A software I2C implementation to run on any GPIO pins on any system
C++
240
star
4

image_to_c

Convert image files into C arrays of uint8_t for compiling into your project
C
198
star
5

OneBitDisplay

A full featured Arduino display library for 1-bit per pixel OLED, LCD and e-paper displays
C
195
star
6

ss_oled

Simple and small library to control 1-bpp OLED displays (Linux + Arduino)
C++
188
star
7

PNGdec

An optimized PNG decoder suitable for microcontrollers and PCs
C
180
star
8

SPI_LCD

A simple C library for directly communicating with SPI-connected LCD displays
C
112
star
9

bb_spi_lcd

SPI LCD/OLED library which can be built for Arduino and Linux
C++
91
star
10

SmartResponseXE

Arduino library with LCD, Keyboard and SPI Flash support for the SMART Response XE classroom communicator
C++
89
star
11

SLIC

Simple lossless imaging codec
C++
80
star
12

oled_96

A simple C library (Linux + Arduino) for drawing text and graphics on SSD1306/SH1106 OLED displays
C
79
star
13

ArmbianIO

A C (+ Python and Java) library for simplifying access to I2C, SPI and GPIO on boards supported by Armbian
C
78
star
14

Multi_OLED

Control multiple OLED displays on one or more I2C buses simultaneously
C++
76
star
15

Print2BLE

MacOS app which allows drag and drop of images to BLE thermal printers
Objective-C
72
star
16

CYD_Projects

A collection of Arduino sketches for the "Cheap Yellow Display" board(s)
C
58
star
17

JPEGENC

Arduino JPEG encoder
C++
55
star
18

VL53L0X

A simple C library to read the distance values from the VL53L0X time of flight sensor
C
54
star
19

unzipLIB

An embedded-friendly library for decompressing files from zip archives
C
51
star
20

oled_turbo

An experiment to push the limits of the SSD1306 through bit banging on Arduinos
C++
45
star
21

PNGenc

An embedded-friendly PNG encoder
C
39
star
22

Multi_BitBang

A software I2C implementation to create multiple I2C buses using GPIO lines
C++
38
star
23

giflib-turbo

A faster drop-in replacement for giflib. It uses more RAM, but you get more speed.
C
37
star
24

SMART_bootloader

Send sketches wirelessly from the Arduino IDE to your SMART Response XE
C
35
star
25

BB-CP

A faster replacement for FBTFT + FBCP
C
31
star
26

LCD1602

A C library (Linux + Arduino) to control 2 line x 16 character I2C LCD displays
C
28
star
27

ssd1327

SSD1327 and SSD1322 OLED display library for Arduino+Linux
C++
26
star
28

oled_animator

C code for converting animated GIF images into a form to run on MCUs and SSD1306 OLED displays
C
26
star
29

Pocket_CO2

A CH32V003 low cost pocket CO2 sensor
C
24
star
30

BLE_Keyboard

An HID keyboard sketch for the Arduino Nano 33 BLE
C++
23
star
31

TIFF_G4

A set of highly optimized functions for decoding and displaying 1-bpp CCITT G4 images
C
22
star
32

I2C_Detector

Scan I2C buses and identify devices which respond.
C++
22
star
33

MAX7219

A C library for controlling any number of Maxim LED matrix controllers
C
21
star
34

bb_captouch

An ESP32/Arduino library to talk to CST820, FT6x36 and GT911 capacitive touch sensors (auto-detects)
C++
21
star
35

Pi_Pico_C_Projects

A collection of C code for the Raspberry Pi Pico
C
20
star
36

uc1701

A C library (Linux + Arduino) to control the UC1701/ST7565/ST7920 128x64 monochrome LCD
C
20
star
37

sg_free

The open source version of SmartGear - a multi-system game emulator
C
19
star
38

epd_image

Prepare image data for writing directly to e-paper displays
C++
18
star
39

bbgfx

BitBank Graphics Library - optimized primitives for RGB565 surfaces on ARMv5
C
17
star
40

Nano_33_Gamepad

A sketch to connect BLE HID gamepads to the Arduino Nano 33 BLE
C++
15
star
41

sense_hat_unchained

A C library to work with the Sense Hat on non-RPI hardware
C
15
star
42

tm1637

A C library for controlling Titan Micro Electronic's 7-segment LED controller
C
13
star
43

esp32_gamepad

Arduino library to connect a SteelSeries:Free gamepad to your ESP32 microcontroller
C++
13
star
44

BLE_2_EPaper

A collection of projects to send images over BLE to e-paper displays
C
12
star
45

KiCad_Projects

A place to share all of my PCB projects
12
star
46

gcc_perf

Test ARM/X86 C/SIMD/ASM perf on 32-bit and 64-bit Linux to see machine/compiler differences
C
12
star
47

bb_truetype

An incomplete, but fast + useful truetype font renderer for embedded devices
C++
11
star
48

Animated_Sand

Arduino demo for SSD1306 I2C display + MPU-6050 accelerometer.
C++
11
star
49

G4Enc

Optimized CCITT G4 encoder for embedded and larger systems
C++
10
star
50

FastIO

A fast substitute for Arduino digital pin functions on AVR MCUs
C++
10
star
51

bin_to_c

A simple Linux command line tool for turning binary files into C source code (array of unsigned chars)
C
9
star
52

gif_play

Play animated GIF images directly on a Linux framebuffer or SPI LCD
C
9
star
53

ESP_NOW_Weather

An e-paper weather project which uses a client/server approach to save battery life
C
9
star
54

bb_epaper

A frustration-free library for working with all 24-pin eink panels
C
8
star
55

NeoPixel

A simple NeoPixel (WS2812B) sketch for generating long light patterns with low RAM usage
C++
8
star
56

TwoBitDisplay

An Arduino library to control 2-bit (4 gray level) LCD displays
C++
8
star
57

RemoteDisplay

An Arduino library to control local or remote (BLE/I2C/UART/WiFi) displays with optional button input
C++
8
star
58

CH32V_Experiments

A place to share code and projects related to the WCH CH32V RISC-V processors
C
8
star
59

CCS811

A simple C library for working with the CCS811 air quality sensor
C
8
star
60

ESLImageTransfer

An Android native app to transfer images to the hacked ESLs
Java
7
star
61

gnu_asm

A C command line tool to convert Microsoft ASM files to GAS (GNU assembler) format
C
7
star
62

hx1230

A C library (Linux + Arduino) to control hx1230 monochrome LCDs
C++
7
star
63

bme280

A simple C library (Linux + Arduino) to read the calibrated temperature/pressure/humidity values from a Bosch BME280 I2C sensor
C
6
star
64

CH32V003_Sensor_Platform

Firmware for a small PCB with LCD which allows easy plug-n-play field-testing of some I2C sensors
C
6
star
65

zlib_turbo

Optimized zlib inflate (+gzip) library for embedded
C++
6
star
66

SmartGear_ESP32

multi-game emulator for the ESP32
C++
5
star
67

ir_receiver

C code to receive NEC codes from a GPIO connected to a IR demodulator
C
5
star
68

LED_Clock

A low cost PCB project (w/firmware) for a dark-room-friendly digital clock
C
5
star
69

CH32V_Color_LCD

A set of functions to control Sitronix color LCDs on CH32V RISC-V MCUs
C
5
star
70

rtc_eeprom

C code to talk to the DS3231 and AT24C32 (usually sold together)
C++
5
star
71

zeemouse

Use 'undocumented' bluetooth game controllers to control your mouse and/or generate keypresses from buttons and stick movements
C
5
star
72

bb_uc1701

Arduino ST7565/UC1701 128x64 LCD display library
C++
5
star
73

CO2_USB_033

A portable CO2 monitor based on the CH32X033 MCU
C
5
star
74

W600FastIO

Optimized GPIO pin functions for the WinnerMicro W600 SoC
C++
4
star
75

arduinoVNC

A VNC client for Arduino
C++
4
star
76

max44009

A simple C library to initialize and read the ambient light value
C
3
star
77

bb_rtc

An Arduino RealTime Clock library which auto-detects DS3231, RV-3032 and PCF8563
C++
3
star
78

oled_sprites

A sprite and tile system for the ATtiny85 & SSD1306 (or more powerful MCU)
C++
3
star
79

imageinfo

A lightweight (aka fast) tool for identifying and displaying the relevant info for image files.
C
3
star
80

accelerometers

A C library to read the accelerometer and gyroscope values from a collection of popular sensors
C
3
star
81

nokia5110

A simple C library (Linux + Arduino) to talk to Nokia 5110 LCD displays
C
3
star
82

nrf24_test_rig

An Arduino sketch for nRF24 range testing using a Pro Mini, 64x32 OLED and 2 buttons
C++
3
star
83

Nano_33_BeetleC

Control the M5Stack Beetle-C car over BLE with an Arduino Nano 33 BLE
C++
3
star
84

weather_mon

A sample weather monitoring program which records the output to a CSV file
C
3
star
85

galactic_unicorn_test

A simple Arduino project to display time + temp + humidity + CO2
C++
3
star
86

rtc_setter

An Arduino sketch to set the local time (corrected for DST) to your DS3231 RTC
C++
3
star
87

bb_hx1230

Arduino library to control HX1230 / STE2007 96x68 LCD displays
C++
3
star
88

FT6236G

An Arduino library for FocalTech FT6x36 capacitive touch controllers
C++
3
star
89

ISBIC

Incredibly Simple Bitonal Image Compression
C
3
star
90

Fusion_360_Projects

A place to share 3D projects
3
star
91

bb_temperature

A multi-device temperature/humidity/pressure sensor library with auto-detection.
C++
3
star
92

bb_scd41

Sensiron SCD4x Arduino library
C++
2
star
93

framebuffer

Experiments with using the Linux framebuffer directly (mostly on Raspberry Pi)
C
2
star
94

min_search_arm

Arm NEON demo to search an unsorted list of integers for the minimum value
C
2
star
95

NXP_Test

Experimental code for the OKDO E1 (NXP LPC55S69)
C
2
star
96

bb_ltr390

visible/UV light sensor Arduino library
C++
2
star
97

armbian_oled

A C library for SSD1306 displays (I2C+SPI) which uses my ArmbianIO library
C
2
star
98

pi_car

A bluetooth gamepad controlled 4wd car with a Rasberry Pi Zero as its brain
C
1
star
99

oled_example

Sample code to talk to a SSD1306 OLED display utilizing my oled_96 library
C
1
star
100

bb-hole

A DNS black hole for filtering out ads/dangerous sites
C
1
star