PENCIL Pos: -- Brush: 1px 128×64 No selection On: 0 Zoom: 100%

About this tool

OLED Pixel Editor: draw graphics for small displays

Small monochrome OLED screens, like the 0.96-inch SSD1306 found in many Arduino and ESP32 kits, show a grid of pixels that are either on or off. This editor lets you draw on exactly that grid - one pixel at a time or with shapes - and then gives you the bytes to put in your program, or a complete Arduino sketch that shows your drawing on the screen.

Everything happens in your browser, and your canvas is saved in this browser as you work. Open the sections below to learn the tools, how the export works, and how the picture is stored in memory.

Your first bitmap in five minutesFrom an empty canvas to a picture on a real screen
  1. Pick the size of your screen. Choose it from the resolution list at the top. 128×64 is the most common SSD1306 module. The canvas must match the display, or the picture will be cut off or squashed.
  2. Draw. The pencil (P) turns pixels on; the eraser (E) turns them off. Use the brush size buttons to paint 1, 2 or 3 pixels wide.
  3. Add shapes and text. Lines, rectangles, circles, triangles and more are in the left bar. Hold Shift while drawing an ellipse to get a perfect circle.
  4. Check it at real size. Zoom out until the drawing is about as small as the real screen. Detail that looks fine when zoomed in is often unreadable at 0.96 inches.
  5. Export. Choose Arduino Sketch for a ready-to-upload .ino file, or C Array for just the bytes to paste into your own code.

Changing the resolution clears the canvas (the editor asks first). Pick the size before you start drawing.

Every tool and shortcutDrawing, shapes, selection and navigation
KeyToolWhat it does
PPencilTurns pixels on, at the chosen brush size
EEraserTurns pixels off
FFlood fillFills a closed area, like a paint bucket
LLineA straight line between two points
RRectangleOutline or filled box
CCircleEllipse; hold Shift for a perfect circle
TTriangleFilled or outline triangle
DDiamondFilled or outline diamond
SSelectPick a rectangle to move, copy, cut, crop or transform
ShortcutAction
Ctrl + ZUndo (up to 80 steps)
Ctrl + Y or Ctrl + Shift + ZRedo
Ctrl + C / X / VCopy, cut and paste a selection
Delete or BackspaceClear the selected pixels
Arrow keysNudge a selection 1 pixel; with Shift, 8 pixels
EscCancel or deselect
Scroll wheelZoom in and out around the pointer
Middle-drag, or Ctrl + dragMove around the canvas
PinchZoom on a phone or tablet

The toolbar also flips, rotates and inverts either the selection or, with nothing selected, the whole canvas.

From the editor to a real screenThe export formats, and running the Arduino sketch
ExportUse it when
Arduino Sketch (.ino)You want a complete program that shows the picture on an SSD1306
C Array (.h)You already have a program and only need the picture's bytes
PNGYou want an image for a document, a slide or a web page
CSVYou want to save your work and open it again later, or process the pixels yourself

Running the sketch on an Arduino or ESP32

  1. In the Arduino IDE, open Library Manager and install Adafruit SSD1306. Accept its dependency, Adafruit GFX.
  2. Wire the display for I2C: GND to ground, VCC to the supply your module is rated for, SDA to the board's SDA pin and SCL to its SCL pin. On an Uno those are A4 and A5.
  3. Open the exported .ino file and upload it.

These are the key lines of the sketch it writes for a 128×64 canvas; ... stands for your picture's bytes:

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C

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

const unsigned char myBitmap[] PROGMEM = {
  ...
};

display.drawBitmap(0, 0, myBitmap, 128, 64, SSD1306_WHITE);

The first four lines describe the screen. display is the object that talks to it over I2C (&Wire). myBitmap holds your picture, and drawBitmap() copies it to the top-left corner, (0, 0).

If the screen stays blank, the address is the usual suspect. Most 128×64 modules answer at 0x3C; some are set to 0x3D. Change SCREEN_ADDRESS and upload again. Modules with an SH1106 controller need the Adafruit SH110X library instead.

How your picture is stored in bytesRows, bits and hex - the part most tutorials skip

Each pixel is one bit: 1 for on, 0 for off. The export packs eight pixels into each byte, row by row from the top, and within a byte the leftmost pixel is the highest bit.

So a row that starts on, off, on, on, off, off, off, off - 10110000 - becomes the byte 0xB0. A row of eight lit pixels is 0xFF. This is the order the Adafruit GFX drawBitmap() function expects.

Some libraries read bits the other way round. U8g2's drawXBM() uses the XBM format, in which the leftmost pixel is the lowest bit, so the same eight pixels would have to be 0x0D. If you use a different library, check which order it wants before you blame the drawing.

Each row takes a whole number of bytes, so the size of a picture is (width ÷ 8, rounded up) × height:

DisplayBytes per rowBytes per picture
128 × 64161024
128 × 3216512
64 × 488384
72 × 409360
96 × 1612192
100 × 1613208 (the last 4 bits of each row are unused)
Will it fit? Flash and RAM on a small boardWhy PROGMEM matters on an Arduino Uno

An Arduino Uno has 32,256 bytes of flash for your program and only 2,048 bytes of RAM. That RAM is already busy: the Adafruit SSD1306 library keeps a copy of the whole screen in it, and for a 128×64 display that copy alone is 1024 bytes - half of the Uno's RAM. A 128×32 display needs 512 bytes.

That is why the exported array is marked PROGMEM. It tells the compiler to leave the picture in flash, where there is far more room, instead of copying it into RAM at start-up. drawBitmap() knows to read it from there.

Flash still runs out if you store many pictures. If you set aside 20 KB (20,480 bytes) for graphics, that holds 20 full 128×64 pictures, or 40 at 128×32. Boards like the ESP32 have megabytes of flash, so this limit mostly matters on the small AVR boards.

Designing for a tiny one-colour screenWhat reads well at 128×64
  • Use shapes, not shading. A pixel is on or off, so smooth gradients are impossible. Strong outlines and solid areas read better than fine texture.
  • Mind the diagonals. A one-pixel diagonal line looks like a staircase. Lines at 45°, or two pixels thick, look cleaner.
  • Text needs about 5×7 pixels a letter. Anything smaller becomes hard to read. At 128 pixels wide that is about 21 characters per line with a one-pixel gap.
  • Leave a margin. Many modules have a thin dark border, and pixels on the very edge can be hard to see.
  • Prefer dark backgrounds. Each lit OLED pixel produces its own light, so a mostly white screen uses more power. Pixels that stay lit for months can also fade unevenly (burn-in), so dim or change a screen that shows the same image all day.
Frequently asked questions

Is my drawing saved?

The canvas is autosaved in this browser, so it is still there if you reload the page. It does not follow you to another computer; export a CSV to keep a copy you can open anywhere.

Can I start from a photo?

Yes. Use the Image to Pixels converter, then send the best result to this editor to tidy it up.

How do I make an animation?

Draw a frame, add it to the animation with the stage button, change the drawing, and stage again. The Animation Studio then puts the frames in order and exports them together.

What is the largest canvas?

1024 × 1024 pixels, using the Custom option. There are also presets for common displays.