6-color e-paper dithering
Six-color panels show black, white, yellow, red, blue and green. Mixing these six inks with dithering covers a wide range of photo colors, which is why they are popular for digital photo frames.
Palette and color codes
The code is the value DitherInk writes for each pixel in .bin, .h, .png and .bmp files. The preview color is the brightened color used for matching and on-screen previews. The index color is the pure color stored in the PNG and BMP palette.
| Color | Code | Preview color | Index color (PNG/BMP) |
|---|---|---|---|
| Black | 0 | #19191e | #000000 |
| White | 1 | #ffffff | #ffffff |
| Yellow | 2 | #f5eb28 | #ffff00 |
| Red | 3 | #b92d28 | #ff0000 |
| Blue | 5 | #2d55c3 | #0000ff |
| Green | 6 | #41874b | #00ff00 |
Frame buffer format
4 bits per pixel (color_4bpp). 2 pixels per byte, the high nibble is the left pixel. The value is the color code. Rows are stored top to bottom and each row is padded to a whole byte.
Supported sizes
| Size | Resolution | .bin size |
|---|---|---|
| 4" | 600×400 | 120,000 bytes (117.2 KB) |
| 7.3" | 800×480 | 192,000 bytes (187.5 KB) |
| 13.3" | 1600×1200 | 960,000 bytes (937.5 KB) |
Tips
Real panel colors are darker and less saturated than screen colors. DitherInk matches against a brightened palette so light areas stay light, and Auto mode boosts muted colors before dithering.
Example code (7.3" 800×480)
Arduino / ESP-IDF with the .h file
#include "my_image.h" // downloaded from DitherInk
// MY_IMAGE_WIDTH x MY_IMAGE_HEIGHT = 800 x 480, color_4bpp
// Color codes: black=0, white=1, yellow=2, red=3, blue=5, green=6
// The buffer is already in the panel's native orientation.
void showImage() {
epd_write_frame(my_image, MY_IMAGE_SIZE); // your driver's full-frame write
epd_refresh();
}Replace epd_write_frame and epd_refresh with the functions your display driver provides. Most drivers have a function that takes a full frame buffer.
ESP32 loading the .bin file from flash
#include <LittleFS.h>
constexpr size_t FRAME_BYTES = 192000;
// Large buffer: allocate in PSRAM on ESP32 boards that have it.
uint8_t* frame = (uint8_t*)ps_malloc(FRAME_BYTES);
bool loadFrame(const char* path) {
File f = LittleFS.open(path, "r");
if (!f || f.size() != FRAME_BYTES) return false; // wrong size = wrong panel settings
f.read(frame, FRAME_BYTES);
f.close();
return true;
}Python (Raspberry Pi) reading the .bin file
import numpy as np
data = np.fromfile("my_image.bin", dtype=np.uint8)
assert data.size == 192000
codes = np.stack([data >> 4, data & 0x0F], axis=-1).reshape(480, -1)[:, :800]