Free · runs in your browser

Image to byte array converter online

Turn a PNG, JPG, GIF or SVG into a byte array you can paste into code. Get an Arduino PROGMEM bitmap for an OLED, a U8g2 XBM, a MicroPython bytearray, an RGB565 array for a colour TFT, or the raw file bytes as C, Python, Java, C#, hex or Base64.

No sign-up and no upload. The image stays on your computer.
Features

One converter for every kind of image byte array

I built this because I kept switching between three tools: one for OLED bitmaps, one for Base64, and one for colour screens. Now it's one page.

Any image in

PNG, JPG, GIF (first frame), WEBP, BMP and SVG. Drag it in, pick a file, or paste a screenshot with Ctrl+V.

OLED screen presets

128×64, 128×32, 72×40, 64×48, 96×16, 128×128 for SH1107, 240×240 for small TFTs, or any custom size up to 1024 pixels.

Clean black and white

Threshold, brightness and contrast sliders, invert, and Floyd–Steinberg, Atkinson or Bayer dithering for photos.

Live pixel preview

A crisp, enlarged preview of every pixel, plus an OLED-style view in white, blue or yellow.

Arduino formats

Adafruit GFX drawBitmap, U8g2 drawXBMP and SSD1306 page order, with PROGMEM and width and height defines.

MicroPython and TFT

framebuf MONO_HLSB and MONO_VLSB bytearrays, and RGB565 uint16_t arrays for TFT_eSPI.

Raw file bytes

The original file as a C array, Python bytes, Java or C# byte[], a hex string, Base64 or a data URI.

Full sketches

Tick one box and get a complete Arduino or MicroPython program for SSD1306, SH1106 or SH1107 that you can upload as it is.

How to use it

Convert an image to a byte array in four steps

Load your image

Drop a PNG, JPG, GIF, WEBP, BMP or SVG on the converter, or paste one with Ctrl+V.

Set size and threshold

Pick your screen size, such as 128x64, then move the threshold slider or turn on dithering until the preview looks right.

Choose the output format

Pick Adafruit GFX drawBitmap, U8g2 drawXBMP, SSD1306 page order, MicroPython framebuf, RGB565 or raw file bytes.

Copy and upload

Copy the array or the full sketch, paste it into the Arduino IDE or Thonny, and upload it to your board.

How bytes are packed

What "image to byte array" really means

A microcontroller can't open a PNG. It has no image decoder and usually no file system, so the picture has to live inside your sketch as numbers. That list of numbers is the byte array. How the numbers are laid out depends on the screen and the library, and getting the layout wrong is the reason most converted images look like static.

On a monochrome OLED such as the SSD1306 or SH1106, every pixel is either on or off. That's one bit, so one byte holds eight pixels. The converter first turns your image into pure black and white with a threshold: any pixel brighter than the threshold becomes a lit pixel. Then it packs the bits into bytes.

Size: why 128×64 is always 1,024 bytes

128 × 64 = 8,192 pixels. Eight pixels per byte gives 8,192 ÷ 8 = 1,024 bytes. A 128×32 bar display is 512 bytes, and a 72×40 screen is 360 bytes. When a row isn't a multiple of eight, it's padded: a 10-pixel-wide image still takes two bytes per row. If your array is a different length from what you expect, the canvas size is wrong.

Horizontal order (Adafruit GFX, image2cpp)

Adafruit's drawBitmap() reads the image row by row. Each byte is eight pixels across, and the leftmost pixel is the highest bit (bit 7). An 8×8 hollow square is eight bytes:

// 8x8 outline, horizontal, MSB = left pixel
const unsigned char box[] PROGMEM = {
  0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF
};
display.drawBitmap(60, 28, box, 8, 8, SSD1306_WHITE);

The top and bottom rows are all on (0xFF). The middle rows only have the two edge pixels on, which is 10000001 in binary, or 0x81. MicroPython's framebuf.MONO_HLSB uses the same layout.

XBM order (U8g2)

U8g2's drawXBMP() also reads rows, but the leftmost pixel is the lowest bit (bit 0). The hollow square happens to look the same, but a single pixel in the top-left corner is 0x80 for Adafruit and 0x01 for XBM. Feed an Adafruit array to U8g2 and every group of eight pixels comes out mirrored.

Vertical page order (SSD1306 native)

Inside the SSD1306 the screen memory is split into pages that are eight rows tall. Each byte is a column of eight pixels, with the top pixel in bit 0. A 128×64 screen has eight pages of 128 bytes. The Adafruit library keeps its buffer in this order too, so a full-screen frame in page order can be copied straight into display.getBuffer(). MicroPython calls this layout MONO_VLSB, and it's what the ssd1306 driver uses internally.

SH1106 has 132 columns

SH1106 modules look identical to SSD1306 ones, but the chip has 132 columns of memory and the glass shows the middle 128. If you write raw page data starting at column 0, the picture shifts two pixels and the right edge wraps. Libraries that support SH1106, such as U8g2 and Adafruit SH110X, add the offset for you. That's why the converter's sketch option uses those libraries when you pick SH1106.

PROGMEM and memory

An Arduino Uno has 32 KB of flash but only 2 KB of RAM. A single 1,024-byte frame would eat half the RAM, so the array is marked PROGMEM and stays in flash. ESP32, ESP8266 and RP2040 boards have far more memory, and PROGMEM is harmless there. The converter shows the byte count and warns you when an image won't fit on an Uno.

Output formats

Which format should you pick?

Image byte array formats and where to use them
FormatUse it withByte layout
Adafruit GFX drawBitmapAdafruit_SSD1306, Adafruit_SH110X, any Adafruit GFX displayRows, 8 pixels per byte, left pixel = bit 7
U8g2 drawXBMPU8g2 and U8glib on SSD1306, SH1106, SH1107 and moreRows, 8 pixels per byte, left pixel = bit 0
SSD1306 page orderFull-screen frames copied into the display bufferColumns of 8 rows, top pixel = bit 0
MicroPython MONO_HLSBframebuf.FrameBuffer and oled.blit()Same as Adafruit
MicroPython MONO_VLSBframebuf.FrameBuffer, ssd1306 driverSame as SSD1306 page order
RGB565TFT_eSPI pushImage(), ST7735, ST7789, ILI9341One 16-bit word per pixel: 5 bits red, 6 green, 5 blue
Raw file bytesC, Python, Java, C#, web APIs, embedding filesThe original PNG or JPG file, unchanged

Converting an animated GIF or a video? A single bitmap converter only takes one frame. The OLED Animation Maker converts every frame and writes the playback loop, and the GIF to OLED guide walks through it.

Common mistakes

Why your converted image looks wrong

Stripes every eight pixels

Page-order data drawn with drawBitmap(). Switch the output to Adafruit GFX and convert again.

Mirrored in small blocks

An Adafruit array drawn with U8g2's drawXBMP(). Pick the U8g2 XBM format instead.

Black and white swapped

Your artwork is dark on a white background. Tick Invert, or draw with SSD1306_BLACK on a filled screen. Don't do both.

Blank screen

The threshold is too high or too low, so every pixel is off. Watch the preview and move the slider. Also try I2C address 0x3D.

Image shifted two pixels

It's an SH1106 module running SSD1306 code. Use the SH1106 option in the sketch.

Board resets when drawing

The array is in RAM on an Uno. Keep PROGMEM ticked and don't copy the frame into a RAM buffer.

Photo turns into a blob

Photos have too many mid-tones for a hard threshold. Raise the contrast and use Floyd–Steinberg or Atkinson dithering.

Width and height are wrong

The numbers in drawBitmap() must match the converted size. Use the generated defines so they can't drift.

Want to check the result before you flash? Paste your frames into the online OLED simulator. For a longer walk-through with image2cpp settings, read image to byte array for Arduino OLED.

Convert your image now

Drop in a picture, check the preview, and copy the bytes. It takes about a minute.

Open the converter
Questions

Image to byte array FAQ

What is an image byte array?

It is your picture written as a list of numbers in code. For a monochrome OLED each bit is one pixel, so one byte holds eight pixels. For a colour screen each pixel is usually two bytes in RGB565. For a file upload or an API it can also mean the original PNG or JPG bytes, unchanged.

Why is a 128x64 bitmap always 1024 bytes?

128 times 64 is 8,192 pixels. Each pixel is one bit, and a byte holds eight bits, so 8,192 divided by 8 is 1,024 bytes. A 128x32 bitmap is 512 bytes.

Which format do I pick for Adafruit SSD1306?

Pick Adafruit GFX drawBitmap. It writes horizontal bytes with the leftmost pixel in the highest bit, which is what display.drawBitmap expects.

Which format do I pick for U8g2?

Pick U8g2 drawXBMP. U8g2 reads XBM bitmaps, which are horizontal bytes with the leftmost pixel in the lowest bit. An Adafruit array drawn with drawXBMP looks mirrored inside every group of eight pixels.

My image shows up as stripes or noise. What went wrong?

The byte order does not match the drawing function. Vertical page-order data drawn with drawBitmap gives stripes, and an Adafruit array drawn with drawXBMP looks scrambled. Convert again with the format that matches your library.

Can I convert an image to a byte array for Python, Java or C#?

Yes. Choose Raw file bytes. The converter writes the original file as a Python bytes object, a Java or C# byte array, a C array, a hex string, Base64 or a data URI.

Is this an image2cpp alternative?

Yes. It covers the same Adafruit and horizontal formats as image2cpp and adds U8g2 XBM, MicroPython framebuf, RGB565, raw file bytes and complete sketches. For animated GIFs, use the OLED Animation Maker, which converts every frame and writes the playback loop.

Is my image uploaded anywhere?

No. The conversion runs in your browser with JavaScript, so the image never leaves your computer.

Related searches: image to byte array · image to byte array online · image to byte · image to c array · png to c array · jpg to c array · bmp to c array · bitmap converter · image2cpp alternative · image to hex · image to base64 · arduino bitmap · oled bitmap · PROGMEM bitmap · ssd1306 bitmap · sh1106 bitmap · u8g2 xbm converter · micropython framebuf image · rgb565 converter · image to bytes python · image to byte array c# · image to byte array java