2022-01-27 13:07:58 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
# converts images into a format suitable for display on badger2040. this
|
|
|
|
# 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
|
|
|
|
# array that can be embedded directly into your c++ code
|
|
|
|
|
2022-03-04 11:06:42 +00:00
|
|
|
import io
|
2022-02-24 09:23:52 +00:00
|
|
|
import argparse
|
2022-01-27 13:07:58 +00:00
|
|
|
from PIL import Image, ImageEnhance
|
|
|
|
from pathlib import Path
|
2022-03-04 11:06:42 +00:00
|
|
|
import data_to_py
|
2022-01-27 13:07:58 +00:00
|
|
|
|
2022-02-24 09:23:52 +00:00
|
|
|
parser = argparse.ArgumentParser(description='Converts images into the format used by Badger2040.')
|
2022-01-27 13:07:58 +00:00
|
|
|
parser.add_argument('file', nargs="+", help='input files to convert')
|
2022-03-04 11:06:42 +00:00
|
|
|
parser.add_argument('--out_dir', type=Path, default=None, help='output directory')
|
2022-02-24 09:23:52 +00:00
|
|
|
parser.add_argument('--binary', action="store_true", help='output binary file for MicroPython')
|
2022-03-04 11:06:42 +00:00
|
|
|
parser.add_argument('--py', action="store_true", help='output .py file for MicroPython embedding')
|
2022-02-24 11:41:37 +00:00
|
|
|
parser.add_argument('--resize', action="store_true", help='force images to 296x128 pixels')
|
2022-02-24 09:23:52 +00:00
|
|
|
|
|
|
|
options = parser.parse_args()
|
2022-01-27 13:07:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
def convert_image(img):
|
2022-02-24 11:41:37 +00:00
|
|
|
if options.resize:
|
|
|
|
img = img.resize((296, 128)) # resize
|
2022-03-09 23:24:36 +00:00
|
|
|
try:
|
|
|
|
enhancer = ImageEnhance.Contrast(img)
|
|
|
|
img = enhancer.enhance(2.0)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
2022-02-24 09:23:52 +00:00
|
|
|
img = img.convert("1") # convert to black and white
|
|
|
|
return img
|
2022-01-27 13:07:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
# create map of images based on input filenames
|
|
|
|
for input_filename in options.file:
|
2022-02-24 09:23:52 +00:00
|
|
|
with Image.open(input_filename) as img:
|
|
|
|
img = convert_image(img)
|
2022-01-27 13:07:58 +00:00
|
|
|
|
2022-02-24 09:23:52 +00:00
|
|
|
image_name = Path(input_filename).stem
|
2022-01-27 13:07:58 +00:00
|
|
|
|
2022-02-24 09:23:52 +00:00
|
|
|
w, h = img.size
|
2022-01-27 13:07:58 +00:00
|
|
|
|
2022-02-24 09:23:52 +00:00
|
|
|
output_data = [~b & 0xff for b in list(img.tobytes())]
|
2022-01-27 13:07:58 +00:00
|
|
|
|
2022-02-24 09:23:52 +00:00
|
|
|
if options.binary:
|
2022-03-04 11:06:42 +00:00
|
|
|
if options.out_dir is not None:
|
|
|
|
output_filename = (options.out_dir / image_name).with_suffix(".bin")
|
|
|
|
else:
|
|
|
|
output_filename = Path(input_filename).with_suffix(".bin")
|
2022-02-24 11:41:37 +00:00
|
|
|
print(f"Saving to {output_filename}, {w}x{h}")
|
2022-02-24 09:23:52 +00:00
|
|
|
with open(output_filename, "wb") as out:
|
|
|
|
out.write(bytearray(output_data))
|
2022-03-04 11:06:42 +00:00
|
|
|
elif options.py:
|
|
|
|
if options.out_dir is not None:
|
|
|
|
output_filename = (options.out_dir / image_name).with_suffix(".py")
|
|
|
|
else:
|
|
|
|
output_filename = Path(input_filename).with_suffix(".py")
|
|
|
|
print(f"Saving to {output_filename}, {w}x{h}")
|
|
|
|
with open(output_filename, "w") as out:
|
|
|
|
data_to_py.write_stream(io.BytesIO(bytes(output_data)), out)
|
2022-02-24 09:23:52 +00:00
|
|
|
else:
|
|
|
|
image_code = '''\
|
2022-01-27 13:07:58 +00:00
|
|
|
static const uint8_t {image_name}[{count}] = {{
|
2022-02-24 09:23:52 +00:00
|
|
|
{byte_data}
|
2022-01-27 13:07:58 +00:00
|
|
|
}};
|
2022-02-24 09:23:52 +00:00
|
|
|
'''.format(image_name=image_name, count=len(output_data), byte_data=", ".join(str(b) for b in output_data))
|
2022-01-27 13:07:58 +00:00
|
|
|
|
2022-02-24 09:23:52 +00:00
|
|
|
print(image_code)
|
2022-01-27 13:07:58 +00:00
|
|
|
|
|
|
|
|