Complete Beginner-Friendly Guide

How to Display an Image on Arduino OLED

A complete walk-through of wiring an SSD1306 OLED to an Arduino, converting an image to a C++ byte array with image2cpp, and rendering it using Adafruit GFX.

⏱ 15 min read 🔗 Beginner friendly 💻 Tested on Arduino UNO, Nano, ESP32
1

What You Will Need

⚡ Shortcut

You do NOT need an SD card, SPI adapter, or extra hardware. The bitmap lives inside your sketch as PROGMEM data.

2

Wire the OLED (I2C)

Most SSD1306 OLEDs speak I2C and have just 4 pins: VCC, GND, SCL, and SDA. Connect them to your Arduino like this:

OLED PinArduino UNO/NanoESP32ESP8266
VCC5V or 3.3V3.3V3.3V
GNDGNDGNDGND
SDAA4GPIO 21D2 (GPIO 4)
SCLA5GPIO 22D1 (GPIO 5)
ARDUINO UNO SSD1306 OLED +------------+ +-------------+ | 5V |-------------| VCC | | GND |-------------| GND | | A4 |-------------| SDA | | A5 |-------------| SCL | +------------+ +-------------+
⚠ Heads up

Double-check the VCC pin voltage on the back of your OLED module. Some cheap boards only tolerate 3.3V even though they look 5V compatible.

3

Install the Libraries

Open the Arduino IDE and go to Sketch → Include Library → Manage Libraries.... Search for and install these two libraries from Adafruit:

Or, if you prefer the lighter-weight u8g2 library:

4

Convert Your Image to a Byte Array

This is where pixel.hjlabs.in comes in. Instead of manually computing every bit of every row, just drop your image into the converter and let the tool generate perfect PROGMEM code.

  1. Open the Image2CPP Converter
  2. Drag your image into the upload zone
  3. Set canvas size to 128 × 64 (or match your OLED)
  4. Set background to White (pixels that are ON will become black after dithering)
  5. Pick a dithering mode — Atkinson for logos, Floyd-Steinberg for photos
  6. Click Generate Code and copy the output
💡 Pro tip

If you are using the u8g2 library, enable the "Swap bits" checkbox before generating. u8g2 expects bits in MSB-first LSB order.

5

Paste into Your Arduino Sketch

Here is a complete working sketch. Replace the epd_bitmap_myImage array with your own output from the converter:

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

#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
#define SCREEN_ADDR   0x3C  // or 0x3D

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ===== Paste your image2cpp output below =====
const unsigned char epd_bitmap_myImage [] PROGMEM = {
  0x00, 0x00, 0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0,
  // ... rest of your bytes ...
};

void setup() {
  Serial.begin(9600);
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDR)) {
    Serial.println("SSD1306 allocation failed");
    for(;;);
  }
  display.clearDisplay();
  display.drawBitmap(0, 0, epd_bitmap_myImage, 128, 64, SSD1306_WHITE);
  display.display();
}

void loop() {}

Click Upload in the Arduino IDE. In a few seconds, your image should appear on the OLED!

6

Alternative: Using u8g2

If you prefer the smaller, faster u8g2 library:

#include <U8g2lib.h>
#include <Wire.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

const unsigned char myImage [] PROGMEM = {
  // ... your bytes (remember to enable 'Swap bits' in image2cpp) ...
};

void setup() {
  u8g2.begin();
}

void loop() {
  u8g2.clearBuffer();
  u8g2.drawXBMP(0, 0, 128, 64, myImage);
  u8g2.sendBuffer();
  delay(1000);
}
7

Troubleshooting

Screen stays blank

Verify the I2C address — run the i2c_scanner sketch. Most SSD1306 modules are 0x3C, some are 0x3D.

Image appears inverted or mirrored

Open the converter and toggle Invert colors, or enable one of the Flip options. Regenerate and paste the new bytes.

u8g2 shows garbled pixels

You probably forgot to enable Swap bits in the image2cpp converter. u8g2 uses reversed bit order compared to Adafruit GFX.

"SSD1306 allocation failed"

Your Arduino is out of RAM. A full 128×64 framebuffer needs 1 KB — on an Arduino UNO (2 KB SRAM) you may need to trim other variables or switch to u8g2 (which has a smaller buffer mode).

Image is too big / tiny on screen

The output resolution must match your drawBitmap call. If you converted at 64×64, call drawBitmap(32, 0, img, 64, 64, WHITE); to center it.

Ready to convert your first image?

Skip the manual bit twiddling. Drop an image, pick a dithering mode, copy the code.

Open Converter →