← All articles · April 24, 2026 · pixel.hjlabs.in · Powered by image2cpp

E-Paper Display Image Conversion: Waveshare 2.13/4.2/7.5

E-paper is the perfect display for low-power dashboards, ESL tags, conference badges, and Kindle-style readers. But Waveshare's e-paper line has a confusing zoo of resolutions, color modes (B/W, 3-color, 4-color, 7-color), and SPI sub-protocols. This post pins down image conversion for the most common Waveshare panels and shows how to drive them with GxEPD2.

The Waveshare e-paper lineup at a glance

PanelResolutionColorsRefresh
2.13" V3250x122B/W~2s full, ~0.3s partial
2.9"296x128B/W~2s
4.2" V2400x300B/W~4s
4.2" 7-color400x3007-color~16s
5.83"648x480B/W or 3-color~6s / ~16s
7.5" V2800x480B/W~5s
7.5" 3-color800x480B/W/Red~16s

Always check the model revision printed on your panel's flex cable — "V2" and "V3" use different waveform tables and crashing the wrong driver gives you a permanent ghosting nightmare.

The library: GxEPD2

GxEPD2 by ZinggJM is the de-facto Arduino/ESP32 library for Waveshare panels. Install via Library Manager. It supports nearly every Waveshare model with a consistent API.

Wiring (typical)

EPD PinESP32Arduino Uno
VCC3V33V3
GNDGNDGND
DIN (MOSI)2311
CLK (SCK)1813
CS510
DC179
RST168
BUSY47

Image conversion: B/W panels

For black-and-white panels (2.13", 4.2" V2, 7.5" V2), the format is simple: 1-bit horizontal MSB-first, exactly the same as SSD1306 OLED.

  1. Open image2cpp
  2. Canvas size = panel resolution (e.g. 400x300 for 4.2")
  3. Output: "Arduino code, Horizontal, 1 bit per pixel"
  4. Threshold: 128 (or use Floyd–Steinberg dithering for photos)
#include <GxEPD2_BW.h>

GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS*/ 5, /*DC*/ 17, /*RST*/ 16, /*BUSY*/ 4));

const unsigned char myImage [] PROGMEM = {
  // 15,000 bytes for 400x300/8
};

void setup() {
  display.init();
  display.setRotation(1);
  display.setFullWindow();
  display.firstPage();
  do {
    display.fillScreen(GxEPD_WHITE);
    display.drawBitmap(0, 0, myImage, 400, 300, GxEPD_BLACK);
  } while (display.nextPage());
  display.hibernate();  // critical for low power
}

void loop() {}

3-color panels (Black / White / Red)

3-color e-paper has two separate frame buffers: one for black pixels, one for red pixels. White is the absence of both. You convert the image twice in image2cpp:

  1. Pre-process the source PNG: split black ink and red ink into two separate B/W PNGs in GIMP. Black areas of the original become the black plane; red areas become the red plane.
  2. Convert each separately in image2cpp as 1-bit horizontal MSB.
  3. In code, use the 3-color GxEPD2 driver and call drawBitmap twice with different colors.
#include <GxEPD2_3C.h>

GxEPD2_3C<GxEPD2_750c_Z08, GxEPD2_750c_Z08::HEIGHT> display(/*...pins...*/);

const unsigned char blackPlane [] PROGMEM = { /* ... */ };
const unsigned char redPlane   [] PROGMEM = { /* ... */ };

void setup() {
  display.init();
  display.setFullWindow();
  display.firstPage();
  do {
    display.fillScreen(GxEPD_WHITE);
    display.drawBitmap(0, 0, blackPlane, 800, 480, GxEPD_BLACK);
    display.drawBitmap(0, 0, redPlane, 800, 480, GxEPD_RED);
  } while (display.nextPage());
  display.hibernate();
}

7-color panels

The 7-color "ACeP" panels (4.01", 5.65", 7.3", 7.3" Spectra) use 4 bits per pixel encoded as a palette: black, white, red, green, blue, yellow, orange. Convert in image2cpp using the 4-bit palette mode and target the 7-color GxEPD2 driver. Refresh time is brutal (15-20 seconds) so reserve them for static art or weekly-updated dashboards.

Memory math

PanelB/W bytes3-color bytes
2.13" 250x1223,8007,600
4.2" 400x30015,00030,000
7.5" 800x48048,00096,000

The 7.5" 800x480 needs 48KB just for one B/W image. Won't fit on Uno (32KB flash). Use ESP32 or RP2040.

Partial refresh: the killer feature

E-paper's slow full refresh is fine for daily updates, but partial refresh (changing a small region in 0.3s without full ghosting) lets you build clocks and weather dashboards. Convert a small region image (e.g. 80x40 for the time digits) and use:

display.setPartialWindow(x, y, 80, 40);
display.firstPage();
do {
  display.fillScreen(GxEPD_WHITE);
  display.drawBitmap(x, y, timeDigits, 80, 40, GxEPD_BLACK);
} while (display.nextPage());

Power: the whole point of e-paper

An e-paper image stays on screen with zero power. Update once an hour and run for years on coin cells. The trick: call display.hibernate() after every update and put the ESP32 into deep sleep:

display.hibernate();
esp_sleep_enable_timer_wakeup(60ULL * 60 * 1000000);  // 1 hour
esp_deep_sleep_start();

Common pitfalls

Bottom line

Waveshare e-paper + GxEPD2 + image2cpp's 1-bit MSB output gets you to "image on screen" in 50 lines of code. Convert your image now, or browse our Arduino tutorial for fundamentals.

Need a low-power dashboard frame? quotes laser-cut acrylic and wood frames.

Try image2cpp now — free, in browser

Drop in a PNG, JPG or BMP. Get a paste-ready C++ array for Arduino, ESP32 or RP2040. 100% client-side. Learn more about image2cpp or jump straight to the tool.

Open the converter →

More from the blog