ElectronicZoologyfield notes from the garage
Display • ESP32

How to cycle images on
the GC9A01 with
batch conversion

Display: GC9A01 - 240x240 round IPS TFT
Board: ESP32 Dev Board (38-pin)
Tools: Python + Pillow, Arduino IDE
GC9A01 Display Series — Step 3 of 3 — Cycling images
✓ Confirmed Working
This guide continues from How to display custom images on the GC9A01 → - make sure your display is working with one image before starting here.

What You Need

Software & Files

Batch Convert

If all your images are in one folder, convert them all at once with a shell loop. Each .h file is named after its source image automatically.

Copy and paste into terminal

for f in ~/Downloads/myimages/*.png; do name=$(basename "$f" .png); python3 ~/image_to_rgb565.py "$f" "$name"; done

Replace ~/Downloads/myimages/ with the path to your images folder.

The .h files land in the same folder as your images. Move them all into your Arduino sketch folder alongside the .ino file.

Flash Memory

Each 240x240 image takes 115KB of flash. The ESP32 default partition gives the app 1MB total - shared with the compiled sketch and libraries. With multiple images you will likely hit that limit.

Change the partition scheme

In Arduino IDE go to Tools → Partition Scheme → Huge APP (3MB No OTA / 1MB SPIFFS) before compiling. That gives the app 3MB, comfortably fitting around 25 images.

ImagesFlash usedPartition needed
1-4up to ~460KBDefault (1MB) - ok
5+500KB+Huge APP (3MB)
~25~2.9MBHuge APP (3MB) - limit

The Sketch

All your edits are in one block at the top - add your #include lines and update the images[] array. NUM_IMAGES counts itself automatically. Everything below that block stays untouched. Swap interval is in milliseconds - 5000 = 5 seconds.

/*
 * We stand on the shoulders of giants when we build
 * with knowledge gained from others' efforts.
 * That doesn't make us giants. Be humble.
 * Create with care. Open source is the way.
 *
 * GC9A01 Cycling Multiple Images
 * -------------------------------
 * Cycles through multiple custom RGB565 images on a GC9A01
 * 240x240 round IPS TFT display via SPI using Arduino_GFX_Library.
 * Images are pre-converted from PNG using image_to_rgb565.py.
 *
 * Board:   ESP32 Dev Board (38-pin)
 * Library: Arduino_GFX_Library by Moon On Our Nation
 *
 * Partition: Tools -> Partition Scheme -> Huge APP (3MB No OTA)
 *
 * Wiring:
 *   VCC -> 3.3V or 5V   GND -> GND
 *   SCL -> GPIO 18       SDA -> GPIO 23
 *   DC  -> GPIO 27       CS  -> GPIO 5
 *   RST -> GPIO 4
 *
 * Open source - MIT Licence
 * Full guide:
 * https://electroniczoology.com/guides/how-to-cycle-images-gc9a01-esp32
 *
 * Electronic Zoology - field notes from the garage
 */

#include <Arduino_GFX_Library.h>

// ---- your images - edit here ----
#include "face1.h"
#include "face2.h"
#include "face3.h"

const uint16_t* images[] = { face1, face2, face3 };
#define NUM_IMAGES (sizeof(images) / sizeof(images[0]))  // auto-counts
// ----------------------------------

#define SWAP_MS 5000        // swap interval in milliseconds

#define TFT_DC  27
#define TFT_CS   5
#define TFT_RST  4

Arduino_DataBus *bus = new Arduino_HWSPI(TFT_DC, TFT_CS);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, TFT_RST, 0, true);
uint8_t idx = 0;
unsigned long lastSwap = 0;

void setup() {
  Serial.begin(115200);
  gfx->begin();
  gfx->fillScreen(0x0000);
  gfx->draw16bitRGBBitmap(0, 0, (uint16_t*)images[0], 240, 240);
  lastSwap = millis();
}

void loop() {
  if (millis() - lastSwap >= SWAP_MS) {
    lastSwap = millis();
    idx = (idx + 1) % NUM_IMAGES;
    gfx->draw16bitRGBBitmap(0, 0, (uint16_t*)images[idx], 240, 240);
  }
}

Troubleshooting

Compile error - sketch too large / not enough flash

  • Go to Tools → Partition Scheme → Huge APP (3MB No OTA / 1MB SPIFFS) and recompile
  • Each image is 115KB - check how many you have included and whether it exceeds the flash partition size

Only the first image shows - display stops cycling

  • Check NUM_IMAGES matches the number of entries in your images[] array
  • Check SWAP_MS - if set very high it may just look like it's not cycling
  • Open Serial Monitor - a crash on draw will stop the loop silently

Wrong colours on one or more images

  • Rerun the converter on that image and replace the .h file
  • Make sure each image was exported as RGB (not RGBA) - flatten in GIMP before converting

Compile error - variable already defined

  • Each .h file must have a unique variable name - check all your headers don't share a name
  • Rename by rerunning the converter with a different varname argument
Start from the beginning? Head back to How to wire the GC9A01 round display with ESP32 →
Have a smaller round display? See How to use the GC9D01 160x160 round TFT with ESP32 - a different chip with a different driver.
Need a simpler display for status readouts? See How to use the SSD1306 OLED display with ESP32 - two wires, no colour, very low power.