Marcio T
4 years ago
committed by
Scott Lahteine
19 changed files with 396 additions and 61 deletions
@ -0,0 +1,47 @@ |
|||||
|
#!/usr/bin/python |
||||
|
|
||||
|
# Written By Marcio Teixeira 2021 - SynDaver Labs, Inc. |
||||
|
# |
||||
|
# This program is free software: you can redistribute it and/or modify |
||||
|
# it under the terms of the GNU General Public License as published by |
||||
|
# the Free Software Foundation, either version 3 of the License, or |
||||
|
# (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# To view a copy of the GNU General Public License, go to the following |
||||
|
# location: <https://www.gnu.org/licenses/>. |
||||
|
|
||||
|
from __future__ import print_function |
||||
|
import argparse |
||||
|
import textwrap |
||||
|
import os |
||||
|
import zlib |
||||
|
|
||||
|
def deflate(data): |
||||
|
return zlib.compress(data) |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
parser = argparse.ArgumentParser(description='Converts a file into a packed C array for use as data') |
||||
|
parser.add_argument("input") |
||||
|
parser.add_argument("-d", "--deflate", action="store_true", help="Packs the data using the deflate algorithm") |
||||
|
args = parser.parse_args() |
||||
|
|
||||
|
varname = os.path.splitext(os.path.basename(args.input))[0]; |
||||
|
|
||||
|
with open(args.input, "rb") as in_file: |
||||
|
data = in_file.read() |
||||
|
if args.deflate: |
||||
|
data = deflate(data) |
||||
|
data = bytearray(data) |
||||
|
data = list(map(lambda a: "0x" + format(a, '02x'), data)) |
||||
|
nElements = len(data) |
||||
|
data = ', '.join(data) |
||||
|
data = textwrap.fill(data, 75, initial_indent = ' ', subsequent_indent = ' ') |
||||
|
|
||||
|
print("const unsigned char " + varname + "[" + format(nElements) + "] PROGMEM = {") |
||||
|
print(data) |
||||
|
print("};") |
@ -0,0 +1,108 @@ |
|||||
|
#!/usr/bin/python |
||||
|
|
||||
|
# Written By Marcio Teixeira 2019 - Aleph Objects, Inc. |
||||
|
# |
||||
|
# This program is free software: you can redistribute it and/or modify |
||||
|
# it under the terms of the GNU General Public License as published by |
||||
|
# the Free Software Foundation, either version 3 of the License, or |
||||
|
# (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# To view a copy of the GNU General Public License, go to the following |
||||
|
# location: <https://www.gnu.org/licenses/>. |
||||
|
|
||||
|
from __future__ import print_function |
||||
|
from PIL import Image |
||||
|
import argparse |
||||
|
import textwrap |
||||
|
|
||||
|
def pack_rle(data): |
||||
|
"""Use run-length encoding to pack the bytes""" |
||||
|
rle = [] |
||||
|
value = data[0] |
||||
|
count = 0 |
||||
|
for i in data: |
||||
|
if i != value or count == 255: |
||||
|
rle.append(count) |
||||
|
rle.append(value) |
||||
|
value = i |
||||
|
count = 1 |
||||
|
else: |
||||
|
count += 1 |
||||
|
rle.append(count) |
||||
|
rle.append(value) |
||||
|
return rle |
||||
|
|
||||
|
class WriteSource: |
||||
|
def __init__(self, lines_in_blocks): |
||||
|
self.blocks = [] |
||||
|
self.values = [] |
||||
|
self.block_size = lines_in_blocks |
||||
|
self.rows = 0 |
||||
|
|
||||
|
def add_pixel(self, value): |
||||
|
self.values.append(value) |
||||
|
|
||||
|
def convert_to_4bpp(self, data, chunk_size = 0): |
||||
|
# Invert the image |
||||
|
data = list(map(lambda i: 255 - i, data)) |
||||
|
# Quanitize 8-bit values into 4-bits |
||||
|
data = list(map(lambda i: i >> 4, data)) |
||||
|
# Make sure there is an even number of elements |
||||
|
if (len(data) & 1) == 1: |
||||
|
data.append(0) |
||||
|
# Combine each two adjacent values into one |
||||
|
i = iter(data) |
||||
|
data = list(map(lambda a, b: a << 4 | b, i ,i)) |
||||
|
# Pack the data |
||||
|
data = pack_rle(data) |
||||
|
# Convert values into hex strings |
||||
|
return list(map(lambda a: "0x" + format(a, '02x'), data)) |
||||
|
|
||||
|
def end_row(self, y): |
||||
|
# Pad each row into even number of values |
||||
|
if len(self.values) & 1: |
||||
|
self.values.append(0) |
||||
|
|
||||
|
self.rows += 1 |
||||
|
if self.block_size and (self.rows % self.block_size) == 0: |
||||
|
self.blocks.append(self.values) |
||||
|
self.values = [] |
||||
|
|
||||
|
def write(self): |
||||
|
if len(self.values): |
||||
|
self.blocks.append(self.values) |
||||
|
|
||||
|
block_strs = []; |
||||
|
for b in self.blocks: |
||||
|
data = self.convert_to_4bpp(b) |
||||
|
data = ', '.join(data) |
||||
|
data = textwrap.fill(data, 75, initial_indent = ' ', subsequent_indent = ' ') |
||||
|
block_strs.append(data) |
||||
|
|
||||
|
print("const unsigned char font[] PROGMEM = {") |
||||
|
for i, b in enumerate(block_strs): |
||||
|
if i: |
||||
|
print(',') |
||||
|
print('\n /* {} */'.format(i)) |
||||
|
print(b, end='') |
||||
|
print("\n};") |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
parser = argparse.ArgumentParser(description='Converts a grayscale bitmap into a 16-level RLE packed C array for use as font data') |
||||
|
parser.add_argument("input") |
||||
|
parser.add_argument('--char_height', help='Adds a separator every so many lines', type=int) |
||||
|
args = parser.parse_args() |
||||
|
|
||||
|
writer = WriteSource(args.char_height) |
||||
|
|
||||
|
img = Image.open(args.input).convert('L') |
||||
|
for y in range(img.height): |
||||
|
for x in range(img.width): |
||||
|
writer.add_pixel(img.getpixel((x,y))) |
||||
|
writer.end_row(y) |
||||
|
writer.write() |
@ -0,0 +1,113 @@ |
|||||
|
#!/usr/bin/python |
||||
|
|
||||
|
# Written By Marcio Teixeira 2021 - SynDaver Labs, Inc. |
||||
|
# |
||||
|
# This program is free software: you can redistribute it and/or modify |
||||
|
# it under the terms of the GNU General Public License as published by |
||||
|
# the Free Software Foundation, either version 3 of the License, or |
||||
|
# (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# To view a copy of the GNU General Public License, go to the following |
||||
|
# location: <https://www.gnu.org/licenses/>. |
||||
|
|
||||
|
from __future__ import print_function |
||||
|
from PIL import Image |
||||
|
import argparse |
||||
|
import textwrap |
||||
|
import os |
||||
|
import sys |
||||
|
import zlib |
||||
|
|
||||
|
class WriteSource: |
||||
|
def __init__(self, mode): |
||||
|
self.values = [] |
||||
|
self.mode = mode |
||||
|
self.offset = 8 |
||||
|
self.byte = 0 |
||||
|
|
||||
|
def finish_byte(self): |
||||
|
if self.offset != 8: |
||||
|
self.values.append(self.byte) |
||||
|
self.offset = 8 |
||||
|
self.byte = 0 |
||||
|
|
||||
|
def add_bits_to_byte(self, value, size = 1): |
||||
|
self.offset -= size |
||||
|
self.byte = self.byte | value << self.offset |
||||
|
if self.offset == 0: |
||||
|
self.finish_byte() |
||||
|
|
||||
|
def append_rgb565(self, color): |
||||
|
value = ((color[0] & 0xF8) << 8) + ((color[1] & 0xFC) << 3) + ((color[2] & 0xF8) >> 3) |
||||
|
self.values.append((value & 0x00FF) >> 0); |
||||
|
self.values.append((value & 0xFF00) >> 8); |
||||
|
|
||||
|
def append_rgb332(self, color): |
||||
|
value = (color[0] & 0xE0) + ((color[1] & 0xE0) >> 3) + ((color[2] & 0xC0) >> 6) |
||||
|
self.values.append(value); |
||||
|
|
||||
|
def append_grayscale(self, color, bits): |
||||
|
luminance = int(0.2126 * color[0] + 0.7152 * color[1] + 0.0722 * color[2]) |
||||
|
self.add_bits_to_byte(luminance >> (8 - bits), bits) |
||||
|
|
||||
|
def deflate(self, data): |
||||
|
return zlib.compress(data) |
||||
|
|
||||
|
def add_pixel(self, color): |
||||
|
if self.mode == "l1": |
||||
|
self.append_grayscale(color, 1) |
||||
|
elif self.mode == "l2": |
||||
|
self.append_grayscale(color, 2) |
||||
|
elif self.mode == "l4": |
||||
|
self.append_grayscale(color, 4) |
||||
|
elif self.mode == "l8": |
||||
|
self.append_grayscale(color, 8) |
||||
|
elif self.mode == "rgb565": |
||||
|
self.append_rgb565(color) |
||||
|
elif self.mode == "rgb332": |
||||
|
self.append_rgb332(color) |
||||
|
|
||||
|
def end_row(self, y): |
||||
|
if self.mode in ["l1", "l2", "l3"]: |
||||
|
self.finish_byte() |
||||
|
|
||||
|
def write(self, varname, deflate): |
||||
|
print("Length of uncompressed data: ", len(self.values), file=sys.stderr) |
||||
|
data = bytes(bytearray(self.values)) |
||||
|
if deflate: |
||||
|
data = self.deflate(data) |
||||
|
print("Length of data after compression: ", len(data), file=sys.stderr) |
||||
|
data = bytearray(data) |
||||
|
data = list(map(lambda a: "0x" + format(a, '02x'), data)) |
||||
|
nElements = len(data) |
||||
|
data = ', '.join(data) |
||||
|
data = textwrap.fill(data, 75, initial_indent = ' ', subsequent_indent = ' ') |
||||
|
|
||||
|
print("const unsigned char " + varname + "[" + format(nElements) + "] PROGMEM = {") |
||||
|
print(data) |
||||
|
print("};") |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
parser = argparse.ArgumentParser(description='Converts a bitmap into a C array') |
||||
|
parser.add_argument("input") |
||||
|
parser.add_argument("-d", "--deflate", action="store_true", help="Packs the data using the deflate algorithm") |
||||
|
parser.add_argument("-m", "--mode", default="l1", help="Mode, can be l1, l2, l4, l8, rgb332 or rgb565") |
||||
|
args = parser.parse_args() |
||||
|
|
||||
|
varname = os.path.splitext(os.path.basename(args.input))[0]; |
||||
|
|
||||
|
writer = WriteSource(args.mode) |
||||
|
|
||||
|
img = Image.open(args.input) |
||||
|
print("Image height: ", img.height, file=sys.stderr) |
||||
|
print("Image width: ", img.width, file=sys.stderr) |
||||
|
for y in range(img.height): |
||||
|
for x in range(img.width): |
||||
|
writer.add_pixel(img.getpixel((x,y))) |
||||
|
writer.end_row(y) |
||||
|
writer.write(varname, args.deflate) |
Loading…
Reference in new issue