Merge pull request #288 from pimoroni/patch-convert-py

Badger2040: Build .py conversion into convert.py
pull/292/head
Philip Howard 2022-03-10 12:06:26 +00:00 zatwierdzone przez GitHub
commit ab80bdde4b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
1 zmienionych plików z 77 dodań i 13 usunięć

Wyświetl plik

@ -1,15 +1,32 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""
Converts images into a format suitable for display on Badger 2040.
# converts images into a format suitable for display on badger2040. this Optionally resizes images to 296x128 to fit the display.
# includes scaling the image fit the longest edge, cropping down to 296x128
# and reducing to black and white with dither. the data is then output as an Crunches images down to dithered, 1bit colour depth.
# array that can be embedded directly into your c++ code
Outputs either in raw binary format or as a .py file for embedding into MicroPython.
Output to py functionality is borrwed from data_to_py.py, Copyright (c) 2016 Peter Hinch
"""
import io import io
import argparse import argparse
from PIL import Image, ImageEnhance from PIL import Image, ImageEnhance
from pathlib import Path from pathlib import Path
import data_to_py
PY_HEADER = """# Code generated by convert.py.
"""
PY_FOOTER = """_mvdata = memoryview(_data)
def data():
return _mvdata
"""
parser = argparse.ArgumentParser(description='Converts images into the format used by Badger2040.') parser = argparse.ArgumentParser(description='Converts images into the format used by Badger2040.')
parser.add_argument('file', nargs="+", help='input files to convert') parser.add_argument('file', nargs="+", help='input files to convert')
@ -21,18 +38,67 @@ parser.add_argument('--resize', action="store_true", help='force images to 296x1
options = parser.parse_args() options = parser.parse_args()
class ByteWriter(object):
bytes_per_line = 16
def __init__(self, stream, varname):
self.stream = stream
self.stream.write('{} =\\\n'.format(varname))
self.bytecount = 0 # For line breaks
def _eol(self):
self.stream.write("'\\\n")
def _eot(self):
self.stream.write("'\n")
def _bol(self):
self.stream.write("b'")
# Output a single byte
def obyte(self, data):
if not self.bytecount:
self._bol()
self.stream.write('\\x{:02x}'.format(data))
self.bytecount += 1
self.bytecount %= self.bytes_per_line
if not self.bytecount:
self._eol()
# Output from a sequence
def odata(self, bytelist):
for byt in bytelist:
self.obyte(byt)
# ensure a correct final line
def eot(self): # User force EOL if one hasn't occurred
if self.bytecount:
self._eot()
self.stream.write('\n')
def convert_image(img): def convert_image(img):
if options.resize: if options.resize:
img = img.resize((296, 128)) # resize img = img.resize((296, 128)) # resize
try: try:
enhancer = ImageEnhance.Contrast(img) enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0) img = enhancer.enhance(2.0)
except ValueError: except ValueError:
pass pass
img = img.convert("1") # convert to black and white img = img.convert("1") # convert to black and white
return img return img
def write_stream(header, footer, ip_stream, op_stream):
op_stream.write(header)
op_stream.write('\n')
data = ip_stream.read()
bw_data = ByteWriter(op_stream, '_data')
bw_data.odata(data)
bw_data.eot()
op_stream.write(footer)
# create map of images based on input filenames # create map of images based on input filenames
for input_filename in options.file: for input_filename in options.file:
with Image.open(input_filename) as img: with Image.open(input_filename) as img:
@ -59,7 +125,7 @@ for input_filename in options.file:
output_filename = Path(input_filename).with_suffix(".py") output_filename = Path(input_filename).with_suffix(".py")
print(f"Saving to {output_filename}, {w}x{h}") print(f"Saving to {output_filename}, {w}x{h}")
with open(output_filename, "w") as out: with open(output_filename, "w") as out:
data_to_py.write_stream(io.BytesIO(bytes(output_data)), out) write_stream(PY_HEADER, PY_FOOTER, io.BytesIO(bytes(output_data)), out)
else: else:
image_code = '''\ image_code = '''\
static const uint8_t {image_name}[{count}] = {{ static const uint8_t {image_name}[{count}] = {{
@ -68,5 +134,3 @@ static const uint8_t {image_name}[{count}] = {{
'''.format(image_name=image_name, count=len(output_data), byte_data=", ".join(str(b) for b in output_data)) '''.format(image_name=image_name, count=len(output_data), byte_data=", ".join(str(b) for b in output_data))
print(image_code) print(image_code)