Guide · JSON & Data

How to Convert a Bitmap Image to a Byte Array

Updated 2026-08-08 · 4 min read

Small displays do not load PNGs. They blit a packed buffer. The everyday job is: take a 128×64 glyph, emit a C or Rust array, paste it into a header. Do that in the browser so an unreleased logo does not need a cloud encoder.

Bitmap to Array on DevOkk.com runs locally. No account. If the image might show customer data or a token on a debug screen, do not drop it on a random converter. Browser-local is the safer default.

Why firmware still wants a C array

Arduino, ESP32, and similar targets keep icons in flash as uint8_t tables. The driver expects 1 bpp packed rows, or a grayscale buffer, with a documented bit order. A PNG in the repo is the source. The array is the artifact the compiler sees.

JSON appears when you generate assets in a pipeline:

{
  "name": "wifi_ok",
  "width": 16,
  "height": 16,
  "bpp": 1,
  "data": [0x00, 0x18, 0x24, 0x18]
}

You can build that object after you have the bytes. This page is how you get data. The reverse preview is Array to Image.

This is not a web image CDN. It is not SVG to PNG. It is pixels → numbers for a framebuffer.

Bit depth, dithering, and bit order

1 bpp. One bit per pixel. High-contrast icons. Most SSD1306 and SH1106 work. Size a source image to the panel (128×64, 128×32) before you convert. Scaling after packing is misery.

2 / 4 / 8 bpp. Use these when the hardware has grayscale or you are packing a buffer you will interpret yourself. 8 bpp is simple (one byte, one pixel) and large.

MSB vs LSB. The driver datasheet wins. If the preview looks striped or mirrored in 8-pixel bands, you flipped the bit order.

Dithering. Off for text, logos, and UI. Floyd-Steinberg when a photograph must live on 1 bpp and you accept speckle. Dithering changes bytes. Preview both. Do not dither a 1-bit icon that was already clean.

Inversion. Some panels treat 1 as dark. If the glyph is a negative of the PNG, invert in the tool or in firmware, not by uploading to a second site.

Match the settings you will use later in Array to Image. Write them in a comment above the array (// 128x64 1bpp msb).

A 128×64 icon into source

You have wifi.png at 128×64, black glyph on white. Open Bitmap to Array. Set 1 bpp, no dither, the bit order your SSD1306 library documents. Copy the C array into wifi.h.

Then open Array to Image, paste the same array, same parameters. If the preview is not wifi.png, stop. Fix bpp or bit order. Flashing first is how you debug on hardware for an hour.

If you need JSON instead of C, wrap the numbers:

{"width":128,"height":64,"bpp":1,"pixels":[/* pasted decimals or hex */]}

Keep that JSON in a fixture if a simulator consumes it. Minify later if you want; the values matter, not the whitespace. Do not paste a production device token into the same file.

Second case: a 16×16 status glyph for a sprite sheet. Same process, smaller dimensions. Do not convert a 2000-pixel photograph to 1 bpp and expect a readable icon. Draw the icon at native size.

Preview the bytes before you flash

The loop is the product:

  1. Convert PNG → array with known settings.
  2. Preview array → pixels with the same settings.
  3. Compile only when step 2 matches.

If you skip the preview, every firmware bug looks like a display bug.

When the source image is a screenshot of an admin UI, treat it like a JSON export: it may contain PII. Crop to the glyph. Better, redraw the glyph.

Related size math (what 128×64×1 bpp actually costs in bytes) lives in How to Convert Bytes, Bits, KB, MB, GB. That article will not pack a bitmap. This one will not teach IEC prefixes.

What this is not

It is not a replacement for lvgl image converters if you are already in that stack and need their format. It is not a JPEG encoder. It is not a way to hide an image - a byte array is the pixels. It will not recover a vector from a raster.

Very large images can strain the tab. Firmware assets are small. If you need a 4K buffer, use a script.

Broken uploads (truncated PNG) should fail. Do not retry on an unknown website.

Lock bpp on a dummy glyph first

Open Bitmap to Array with a dummy glyph. Lock bpp and bit order. Preview the result in Array to Image. Then convert the real icon if it does not contain secrets. The companion how-to is How to Turn a Byte Array Into an Image.

Frequently asked questions

Does Bitmap to Array require an account?

No. Add the image, pick bit depth and bit order, copy the C or Rust array, close the tab.

Does the tool upload my icon?

Bitmap to Array is designed to process the image in your browser. The pixels are not sent to complete the conversion.

Should I convert a screenshot that shows customer data?

If the image might contain PII or unreleased UI, do not upload it to a random website. A browser-local converter is the safer default. Prefer a dummy icon when you are only testing settings.

Which bit depth should I pick?

1 bpp for most monochrome OLED and e-ink icons. 2 or 4 bpp for limited grayscale. 8 bpp when you have the RAM for a byte per pixel. Match the display driver, not a generic 'best quality' guess.

When do I enable dithering?

Use none for logos and UI glyphs. Use Floyd-Steinberg when you are forcing a photo or gradient onto a 1-bpp panel and can accept speckle. Dithering is not a substitute for the right bpp.

How do I know the array is correct?

Preview it with Array to Image using the same width, height, bpp, and bit order. If the preview does not match the source icon, do not flash the board yet.

More reading that links back to the same tools and workflows.