Files
pico-examples/i2c/ssd1306_i2c/img_to_array.py
James Hughes aa9a72b494 Refactor the oled_i2c example (#217)
This PR does a number of things:

1. Renames the oled_i2c example to sssd1306_i2c to match other example folder
   names that use the device name
2. Merge code from another ssd1306 exmaple that was sitting in another PR
3. Add a few more demo parts to the code for extra fun.
4. Couple of bug fixes that were reported in original code to fix handling different
   display sizes, so code now works for 32 and 64 pixel height displays by changing
   a define at top of code.
2022-11-25 10:38:11 -06:00

82 lines
2.1 KiB
Python
Executable File

#!/usr/bin/env python3
# Converts a grayscale image into a format able to be
# displayed by the SSD1306 driver in horizontal addressing mode
# usage: python3 img_to_array.py <logo.bmp>
# depends on the Pillow library
# `python3 -m pip install --upgrade Pillow`
from PIL import Image
import sys
from pathlib import Path
OLED_HEIGHT = 32
OLED_WIDTH = 128
OLED_PAGE_HEIGHT = 8
if len(sys.argv) < 2:
print("No image path provided.")
sys.exit()
img_path = sys.argv[1]
try:
im = Image.open(img_path)
except OSError:
raise Exception("Oops! The image could not be opened.")
img_width = im.size[0]
img_height = im.size[1]
if img_width > OLED_WIDTH or img_height > OLED_HEIGHT:
print(f'Your image is f{img_width} pixels wide and {img_height} pixels high, but...')
raise Exception(f"OLED display only {OLED_WIDTH} pixels wide and {OLED_HEIGHT} pixels high!")
if not (im.mode == "1" or im.mode == "L"):
raise Exception("Image must be grayscale only")
# black or white
out = im.convert("1")
img_name = Path(im.filename).stem
# `pixels` is a flattened array with the top left pixel at index 0
# and bottom right pixel at the width*height-1
pixels = list(out.getdata())
# swap white for black and swap (255, 0) for (1, 0)
pixels = [0 if x == 255 else 1 for x in pixels]
# our goal is to divide the image into 8-pixel high pages
# and turn a pixel column into one byte, eg for one page:
# 0 1 0 ....
# 1 0 0
# 1 1 1
# 0 0 1
# 1 1 0
# 0 1 0
# 1 1 1
# 0 0 1 ....
# we get 0x6A, 0xAE, 0x33 ... and so on
# as `pixels` is flattened, each bit in a column is IMG_WIDTH apart from the next
buffer = []
for i in range(img_height // OLED_PAGE_HEIGHT):
start_index = i*img_width*OLED_PAGE_HEIGHT
for j in range(img_width):
out_byte = 0
for k in range(OLED_PAGE_HEIGHT):
out_byte |= pixels[k*img_width + start_index + j] << k
buffer.append(f'{out_byte:#04x}')
buffer = ", ".join(buffer)
buffer_hex = f'static uint8_t {img_name}[] = {{{buffer}}}\n'
with open(f'{img_name}.h', 'wt') as file:
file.write(f'#define IMG_WIDTH {img_width}\n')
file.write(f'#define IMG_HEIGHT {img_height}\n\n')
file.write(buffer_hex)