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

Convert PNG to C Array for Arduino: Free image2cpp 2026 Guide

If you have an Arduino, ESP32, or RP2040 wired to an OLED, TFT or e-paper display, you cannot just fopen("logo.png"). You need the image baked into your firmware as a C++ byte array. This guide walks the entire workflow in 2026 — from a PNG on your desktop to pixels on your panel — using image2cpp, the free in-browser converter.

Why a C array (and not just an SD card load)?

Three reasons makers and embedded engineers ship images as const arrays in flash:

The format you need

The exact byte layout depends on your display:

DisplayFormatBits / pixel
SSD1306, SH1106 OLED (mono)1-bit horizontal MSB1
U8g2 (XBM)1-bit horizontal LSB (XBM)1
ILI9341, ST7735 TFTRGB565 big-endian16
Waveshare e-paper (B/W)1-bit horizontal MSB1
Waveshare e-paper (3-color)two 1-bit planes (B + R)2 effective
LVGL true colorRGB565 / RGB888 / ARGB888816-32

Picking the wrong format produces garbled output — the most common newbie bug. image2cpp exposes every option with a live preview so you can verify before pasting into your sketch.

Step 1 — Prepare your PNG

Resize the source PNG to your display's native resolution before conversion. A 4K logo squished to 128x64 looks worse than one you manually downsampled in GIMP or Photoshop with a sharpen pass.

For monochrome displays, also crank contrast and consider Floyd–Steinberg dithering. The tool can do this for you, but a good source image always wins.

Step 2 — Convert with image2cpp

Open pixel.hjlabs.in/converter. The flow:

  1. Drag the PNG into the upload zone
  2. Set canvas size (e.g. 128x64)
  3. Pick threshold or dithering mode
  4. Choose output format (matches your display from the table above)
  5. Copy the generated array

Step 3 — Drop into your Arduino sketch

Here is a complete working sketch for a 128x64 SSD1306 with a custom logo:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// 'logo', 128x64px — output of image2cpp
const unsigned char PROGMEM logo [] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  // ... 1024 bytes total for 128x64 mono ...
};

void setup() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for(;;);  // halt if init fails
  }
  display.clearDisplay();
  display.drawBitmap(0, 0, logo, 128, 64, SSD1306_WHITE);
  display.display();
}

void loop() {}

Step 4 — PROGMEM-safe array declaration

Always declare the array as const unsigned char PROGMEM on AVR boards (Uno, Nano, Mega). Without PROGMEM the compiler stuffs the array into SRAM and your sketch crashes the moment SRAM fills up — which is fast, since an Uno only has 2KB.

On ESP32, ESP8266 and ARM boards (RP2040, STM32), PROGMEM is an alias that has no effect — flash is read directly. But keeping it in the source preserves portability across platforms.

Common errors and fixes

Sizing the image to fit your flash

Quick math:

Beyond static images: animations

For a sprite or animation, generate one C array per frame, store all of them in PROGMEM, then iterate with millis()-based timing. We covered this in detail in our Arduino OLED tutorial and a dedicated post on frame-by-frame OLED animation.

Why image2cpp over alternatives?

The original javl/image2cpp on GitHub is great but ad-supported and unmaintained. pixel.hjlabs.in is a fork with a cleaner UI, batch upload, more output formats (LVGL, Waveshare 3-color e-paper), and zero ads. Everything still runs in the browser — your image never uploads to a server.

Bottom line

The 2026 workflow: prepare a PNG at native resolution, convert with image2cpp, paste into a const PROGMEM array, and call drawBitmap or pushImage. Open the converter now and ship pixels in five minutes.

Related from hjLabs.in: generate matching favicons and OG images for your project's GitHub README; if your firmware emits JSON over serial, the JSON formatter at fmt.hjlabs.in is handy for debugging.

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