Skip to content

Instantly share code, notes, and snippets.

@pkamp3
Created May 25, 2017 08:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pkamp3/d114d89d45939ab20fb83706868f37fb to your computer and use it in GitHub Desktop.
Save pkamp3/d114d89d45939ab20fb83706868f37fb to your computer and use it in GitHub Desktop.
Fonts and string creator for Hackpack v3
"""
Convert IMAGE based fonts to uint16_t.
Code to convert BITMAP or IMAGE based fonts to fonts
for use on the 2017 SIGNAL Hackpack. Characters must be in the form of 4x4
pixels. Please pad smaller fonts to 4x4 pixel blocks.
By convention, it should be in ASCII order and start with the 'space'
character: http://www.asciitable.com/ (see the example png)
Install PIL or PILLOW (perhaps 'pip install pillow'?) and run with:
> python bitmap2bytemap.py -i <inputimg> -f <fontname>
Arduboy TinyFont (BSD licensed) has been embedded so you can see the format.
Here's an example command line run:
> python bitmap2bytemap.py -i tinyfont.png -f tinyfont
LICENSE: MIT
"""
from PIL import Image
from optparse import OptionParser
import sys
# Set the atomic unit length. We'll be using uint16_t
# so we have it set to 16 by default.
UNIT_LENGTH = 16
def main(argv=None):
"""
Parse command line options and dump to a header file.
"""
parser = OptionParser()
parser.add_option('-i', action="store", dest="inputfile")
parser.add_option('-f', action="store", dest="fontname")
parser.add_option('-d', action="store", dest="dumpfile")
parser.add_option(
"-p",
action="store_true",
dest="preview",
default=False
)
(opts, args) = parser.parse_args()
if opts.inputfile is not None:
inputfile = opts.inputfile
else:
print ("Use the -i option and pass an inputfile")
return 1
if opts.fontname is not None:
fontname = opts.fontname
else:
print ("Use the -f option and pass a fontname for the struct")
return 3
im = Image.open(inputfile)
im = im.convert('RGB')
pixels = im.load()
with open(fontname + ".py", 'w+') as f:
f.write(
'"""Binary Dump of {}*{} image {}"""'.format(
im.size[0],
im.size[1],
inputfile
)
)
struct_name = "\n\n{} = []\n".format(fontname)
f.write(struct_name)
f.write("\n# Pad ASCII 32 Characters\n")
for i in range(32):
f.write("{}.append(0b0000000000000000)\n".format(fontname))
f.write("\n# Begin standard Display ASCII\n")
color_unit = []
for y in range(0, im.size[1]):
for x in range(0, im.size[0]):
r, g, b = im.getpixel((x, y))
if ((r + g + b) // 3) > 20:
color_unit.append('0')
pixels[x, y] = (255, 255, 255)
else:
color_unit.append('1')
pixels[x, y] = (0, 0, 0)
if len(color_unit) == UNIT_LENGTH:
color_string = "".join(color_unit)
color_unit = []
line_string = "{}.append(0b{})\n".format(fontname,
color_string)
f.write(line_string)
if opts.dumpfile is not None:
im.save(opts.dumpfile)
if opts.preview:
im.show()
if __name__ == "__main__":
sys.exit(main())
"""
Convert your string to a custom message on the Hackpackv3.
We support changing colors, fonts, and the message itself. The only mandatory
inputs are the message (-m) and outputfile (-o):
python font_creator_hackpack.py -m "WELCOME TO SIGNAL" -o header.h
You can switch fonts with -f:
python font_creator_hackpack.py -m "FONT" -o out.h -f nano_michaelangel
Switch color with -c, but ONLY USE 6 DIGIT HEX e.g. '222222':
font_creator_hackpack.py -o header.h -m "BEST COLOR" -c "F22F46"
Paste the result to the 'uint32_t custom_animation_lut[][16]' in the Hackpack's
.ino file, and be sure to change the delay. We have found that capital letters
and a delay starting around 500 - 700 ms looks best, but experiment!
There are two built in fonts, 'tinyfont' (default) and 'nano_michaelangel'
Tinyfont: https://github.com/yinkou/Arduboy-TinyFont by linkou
(License BSD: https://github.com/yinkou/Arduboy-TinyFont/blob/master/LICENSE )
NanoFont 3x4: https://github.com/Michaelangel007/nanofont3x4 by
Michaelangel007
( License CC0: https://github.com/Michaelangel007/nanofont3x4/blob/master/LICENSE)
LICENSE: MIT
"""
from __future__ import print_function
from optparse import OptionParser
import sys
# Include your Python fonts here
from tinyfont import *
from nano_michaelangel import *
font_dict = {}
font_dict['tinyfont'] = tinyfont
font_dict['nano_michaelangel'] = nano_michaelangel
# Global - verbose for debugging script.
verbose = False
def main(argv=None):
"""
Parse command line options and dump to a header file.
Paste it on top of the custom animation lut in the Hackpack - AND BE
SURE TO CHANGE THE DELAY: you should try at least 500 - 700 ms
to see what is easiest to read.
"""
parser = OptionParser()
parser.add_option('-m', action="store", dest="message")
parser.add_option('-o', action="store", dest="outputfile")
parser.add_option('-f', action="store", dest="font")
parser.add_option('-c', action="store", dest="color")
parser.add_option('-v', action="store_true", dest="verbose")
(opts, args) = parser.parse_args()
if opts.outputfile is not None:
outputfile = opts.outputfile
else:
print ("Use the -o option and pass an outputfile")
return 1
if opts.message is not None:
message = opts.message
else:
print ("Use the -m option and pass a message (in quotes)")
return 2
color = '222222' if not opts.color else opts.color
font = 'tinyfont' if not opts.font else opts.font
global verbose
verbose = True if opts.verbose else False
with open(outputfile, 'w+') as f:
f.write("uint32_t custom_animation_lut[][16] = { \n")
for i, c in enumerate(message):
line_end = "," if i != (len(message) - 1) else ""
if verbose:
print (c, ord(c))
print (font_dict[font][ord(c)] >> 15 & 1, end='')
print (font_dict[font][ord(c)] >> 14 & 1, end='')
print (font_dict[font][ord(c)] >> 13 & 1, end='')
print (font_dict[font][ord(c)] >> 12 & 1)
print (font_dict[font][ord(c)] >> 11 & 1, end='')
print (font_dict[font][ord(c)] >> 10 & 1, end='')
print (font_dict[font][ord(c)] >> 9 & 1, end='')
print (font_dict[font][ord(c)] >> 8 & 1)
print (font_dict[font][ord(c)] >> 7 & 1, end='')
print (font_dict[font][ord(c)] >> 6 & 1, end='')
print (font_dict[font][ord(c)] >> 5 & 1, end='')
print (font_dict[font][ord(c)] >> 4 & 1)
print (font_dict[font][ord(c)] >> 3 & 1, end='')
print (font_dict[font][ord(c)] >> 2 & 1, end='')
print (font_dict[font][ord(c)] >> 1 & 1, end='')
print (font_dict[font][ord(c)] >> 0 & 1)
f.write("\t{ ")
for j in range(15, -1, -1):
flourish = "," if j != 0 else ""
f.write(
font_bool_to_color(
font_dict[font][ord(c)],
color,
j
) + flourish
)
f.write(" }" + line_end + "\n")
f.write("};")
return
def font_bool_to_color(font_word, color, idx):
"""Return either the color choice or a blank pixel."""
return ('0x' + color) if font_word >> idx & 1 else '0x000000'
if __name__ == "__main__":
sys.exit(main())
""""Binary Dump of 4*384 image tinyfont.png"""
nano_michaelangel = []
# Pad ASCII 32 Characters
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x0000)
# Begin standard Display ASCII
nano_michaelangel.append(0x0000)
nano_michaelangel.append(0x4400) # !
nano_michaelangel.append(0xAA00) # "
nano_michaelangel.append(0xAEE0) # #
nano_michaelangel.append(0x64C4) # $
nano_michaelangel.append(0xCE60) # %
nano_michaelangel.append(0x4C60) # &
nano_michaelangel.append(0x4000) # '
nano_michaelangel.append(0x4840) # (
nano_michaelangel.append(0x4240) # )
nano_michaelangel.append(0x6600) # *
nano_michaelangel.append(0x4E40) # +
nano_michaelangel.append(0x0088) # ,
nano_michaelangel.append(0x0E00) # -
nano_michaelangel.append(0x0080) # .
nano_michaelangel.append(0x2480) # /
nano_michaelangel.append(0x4A40) # 0
nano_michaelangel.append(0x8440) # 1
nano_michaelangel.append(0xC460) # 2
nano_michaelangel.append(0xE6E0) # 3
nano_michaelangel.append(0xAE20) # 4
nano_michaelangel.append(0x64C0) # 5
nano_michaelangel.append(0x8EE0) # 6
nano_michaelangel.append(0xE220) # 7
nano_michaelangel.append(0x6EC0) # 8
nano_michaelangel.append(0xEE20) # 9
nano_michaelangel.append(0x4040) # :
nano_michaelangel.append(0x0448) # ;
nano_michaelangel.append(0x4840) # <
nano_michaelangel.append(0xE0E0) # =
nano_michaelangel.append(0x4240) # >
nano_michaelangel.append(0x6240) # ?
nano_michaelangel.append(0xCC20) # @
nano_michaelangel.append(0x4EA0) # A
nano_michaelangel.append(0xCEE0) # B
nano_michaelangel.append(0x6860) # C
nano_michaelangel.append(0xCAC0) # D
nano_michaelangel.append(0xECE0) # E
nano_michaelangel.append(0xEC80) # F
nano_michaelangel.append(0xCAE0) # G
nano_michaelangel.append(0xAEA0) # H
nano_michaelangel.append(0x4440) # I
nano_michaelangel.append(0x22C0) # J
nano_michaelangel.append(0xACA0) # K
nano_michaelangel.append(0x88E0) # L
nano_michaelangel.append(0xEEA0) # M
nano_michaelangel.append(0xEAA0) # N
nano_michaelangel.append(0xEAE0) # O
nano_michaelangel.append(0xEE80) # P
nano_michaelangel.append(0xEAC0) # Q
nano_michaelangel.append(0xCEA0) # R
nano_michaelangel.append(0x64C0) # S
nano_michaelangel.append(0xE440) # T
nano_michaelangel.append(0xAAE0) # U
nano_michaelangel.append(0xAA40) # V
nano_michaelangel.append(0xAEE0) # W
nano_michaelangel.append(0xA4A0) # X
nano_michaelangel.append(0xA440) # Y
nano_michaelangel.append(0xE4E0) # Z
nano_michaelangel.append(0xC8C0) # [
nano_michaelangel.append(0x8420) # \
nano_michaelangel.append(0x6260) # ]
nano_michaelangel.append(0x4A00) # ^
nano_michaelangel.append(0x00E0) # _
nano_michaelangel.append(0x8400) # `
nano_michaelangel.append(0x04C0) # a
nano_michaelangel.append(0x8CC0) # b
nano_michaelangel.append(0x0CC0) # c
nano_michaelangel.append(0x4CC0) # d
nano_michaelangel.append(0x08C0) # e
nano_michaelangel.append(0x2440) # f
nano_michaelangel.append(0x0CCC) # g
nano_michaelangel.append(0x8CC0) # h
nano_michaelangel.append(0x0440) # i
nano_michaelangel.append(0x0448) # j
nano_michaelangel.append(0x8CA0) # k
nano_michaelangel.append(0x4420) # l
nano_michaelangel.append(0x0CE0) # m
nano_michaelangel.append(0x0CA0) # n
nano_michaelangel.append(0x0CC0) # o
nano_michaelangel.append(0x0CC8) # p
nano_michaelangel.append(0x0CC4) # q
nano_michaelangel.append(0x0C80) # r
nano_michaelangel.append(0x0480) # s
nano_michaelangel.append(0x4C60) # t
nano_michaelangel.append(0x0AE0) # u
nano_michaelangel.append(0x0A40) # v
nano_michaelangel.append(0x0E60) # w
nano_michaelangel.append(0x0CC0) # x
nano_michaelangel.append(0x0AE2) # y
nano_michaelangel.append(0x0840) # z
nano_michaelangel.append(0x6C60) # {
nano_michaelangel.append(0x4444) # |
nano_michaelangel.append(0xC6C0) # }
nano_michaelangel.append(0x6C00) # ~
nano_michaelangel.append(0xFFFF) #
"""Binary Dump of 4*384 image tinyfont.png"""
tinyfont = []
# Pad ASCII 32 Characters
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0000000000000000)
# Begin standard Display ASCII
tinyfont.append(0b0000000000000000)
tinyfont.append(0b0100010000000100)
tinyfont.append(0b1010000000000000)
tinyfont.append(0b0101111001111010)
tinyfont.append(0b0100111011100100)
tinyfont.append(0b1001001001001001)
tinyfont.append(0b1110101011111101)
tinyfont.append(0b0100000000000000)
tinyfont.append(0b0010010001000010)
tinyfont.append(0b0100001000100100)
tinyfont.append(0b0000101001001010)
tinyfont.append(0b0000010011100100)
tinyfont.append(0b0000000001001000)
tinyfont.append(0b0000000011100000)
tinyfont.append(0b0000000000000100)
tinyfont.append(0b0010010001001000)
tinyfont.append(0b1111101110011111)
tinyfont.append(0b0110001000100111)
tinyfont.append(0b1111001001001111)
tinyfont.append(0b1111011100011111)
tinyfont.append(0b1001100111110001)
tinyfont.append(0b1111100011110111)
tinyfont.append(0b1000111110011111)
tinyfont.append(0b1111000100010001)
tinyfont.append(0b1111100111111111)
tinyfont.append(0b1111100111110001)
tinyfont.append(0b0000010000000100)
tinyfont.append(0b0100000001001000)
tinyfont.append(0b0000001001000010)
tinyfont.append(0b0000111000001110)
tinyfont.append(0b0000010000100100)
tinyfont.append(0b1110011000000100)
tinyfont.append(0b1111101110001100)
tinyfont.append(0b1111100111111001)
tinyfont.append(0b1110111110011111)
tinyfont.append(0b1111100010001111)
tinyfont.append(0b1110100110011110)
tinyfont.append(0b1111111010001111)
tinyfont.append(0b1111100011101000)
tinyfont.append(0b1111100010011111)
tinyfont.append(0b1001100111111001)
tinyfont.append(0b1110010001001110)
tinyfont.append(0b0111001010101110)
tinyfont.append(0b1011110010101001)
tinyfont.append(0b1000100010001111)
tinyfont.append(0b1111101110011001)
tinyfont.append(0b1001110110111001)
tinyfont.append(0b1111100110011111)
tinyfont.append(0b1111100111111000)
tinyfont.append(0b1111100110111111)
tinyfont.append(0b1111100111111010)
tinyfont.append(0b1111100011110111)
tinyfont.append(0b1111010001000100)
tinyfont.append(0b1001100110011111)
tinyfont.append(0b1001100110010110)
tinyfont.append(0b1001100110111111)
tinyfont.append(0b1001011001101001)
tinyfont.append(0b1001100111110100)
tinyfont.append(0b1111001001001111)
tinyfont.append(0b0110010001000110)
tinyfont.append(0b1000010001000010)
tinyfont.append(0b0110001000100110)
tinyfont.append(0b0100101000000000)
tinyfont.append(0b0000000000001111)
tinyfont.append(0b0100001000000000)
tinyfont.append(0b1100011011100000)
tinyfont.append(0b1000111011100000)
tinyfont.append(0b1110100011100000)
tinyfont.append(0b0010111011100000)
tinyfont.append(0b1110111011000000)
tinyfont.append(0b0111111001000000)
tinyfont.append(0b0110111000101100)
tinyfont.append(0b1000111010100000)
tinyfont.append(0b0100010001000000)
tinyfont.append(0b0100010001001000)
tinyfont.append(0b1010110010100000)
tinyfont.append(0b1000100001100000)
tinyfont.append(0b1110111010100000)
tinyfont.append(0b1100101010100000)
tinyfont.append(0b1110101011100000)
tinyfont.append(0b1110101011101000)
tinyfont.append(0b1110101011100010)
tinyfont.append(0b1100100010000000)
tinyfont.append(0b0110010011000000)
tinyfont.append(0b0100111001000000)
tinyfont.append(0b1010101001100000)
tinyfont.append(0b1010101001000000)
tinyfont.append(0b1010111011100000)
tinyfont.append(0b1010010010100000)
tinyfont.append(0b1010011000100100)
tinyfont.append(0b1100010001100000)
tinyfont.append(0b0010110011000010)
tinyfont.append(0b0100010001000100)
tinyfont.append(0b0100001100110100)
tinyfont.append(0b0000011110100000)
tinyfont.append(0b1111111111111111)
@pkamp3
Copy link
Author

pkamp3 commented May 25, 2017

tinyfont

Rename that to 'tinyfont.png' to try the font generator with the commands in the files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment