Nastroj pro generovani fontu (neuplny!!!)
This commit is contained in:
parent
034c2ab149
commit
74b3ab8606
205
tools/fontconv.py
Normal file
205
tools/fontconv.py
Normal file
@ -0,0 +1,205 @@
|
||||
#http://stackoverflow.com/questions/5747739/python-render-non-anti-aliased-font-to-internal-image
|
||||
#Author: Pavel Brychta
|
||||
from PIL import Image
|
||||
from PIL import ImageFont, ImageDraw
|
||||
import sys
|
||||
import ast
|
||||
|
||||
def character(fontname, fontsize, bitsperpixel, char):
|
||||
""" Vykresli znak do vnitrniho povrchu a nasledne ho prevede do pole elementu intenzit,
|
||||
ktere ma vzdy 4 bity/bod (intenzita 0-15).
|
||||
Vraci [rozmer obrazku v ose X, rozmer obrazku v ose Y, Prvni radek obrazku, ktery nese obrazovou informaci (offset od 0), Posledni radek obrazku, ktery nese obrazovou informaci, [pole elementu]
|
||||
"""
|
||||
result = []
|
||||
|
||||
usr_font = ImageFont.truetype(fontname, fontsize)
|
||||
imagexsize, imageysize = usr_font.getsize(char)
|
||||
image = Image.new("RGB", (imagexsize, imageysize), "Black")
|
||||
#image = Image.new("RGB", (320, 320), "Black")
|
||||
# print(imagexsize, imageysize)
|
||||
d_usr = ImageDraw.Draw(image)
|
||||
if bitsperpixel > 1:
|
||||
d_usr.fontmode = "L" # Zapneme antialiasovani
|
||||
else:
|
||||
d_usr.fontmode = "1" # Vypneme antialiasovani (pro fonty o hloubce 1bit/pixel)
|
||||
#imagexsize, imageysize = d_usr.textsize(char, usr_font)
|
||||
d_usr.text((0, 0), char, "White", font=usr_font)
|
||||
#print "Imageinfosize:", ord(char), imagexsize, imageysize
|
||||
#image.save('test_' + str(ord(char)) + '.png', 'PNG')
|
||||
pix = image.load()
|
||||
firstimageline = 1000
|
||||
lastimageline = -1
|
||||
for x in range(imagexsize):
|
||||
for y in range(imageysize):
|
||||
R, G, B = pix[x, y]
|
||||
if R < 0x08:
|
||||
outpix = 0
|
||||
elif R < 0x18:
|
||||
outpix = 1
|
||||
elif R < 0x28:
|
||||
outpix = 2
|
||||
elif R < 0x38:
|
||||
outpix = 3
|
||||
elif R < 0x48:
|
||||
outpix = 4
|
||||
elif R < 0x58:
|
||||
outpix = 5
|
||||
elif R < 0x68:
|
||||
outpix = 6
|
||||
elif R < 0x78:
|
||||
outpix = 7
|
||||
elif R < 0x88:
|
||||
outpix = 8
|
||||
elif R < 0x98:
|
||||
outpix = 9
|
||||
elif R < 0xa8:
|
||||
outpix = 10
|
||||
elif R < 0xb8:
|
||||
outpix = 11
|
||||
elif R < 0xc8:
|
||||
outpix = 12
|
||||
elif R < 0xd8:
|
||||
outpix = 13
|
||||
elif R < 0xe8:
|
||||
outpix = 14
|
||||
else:
|
||||
outpix = 15
|
||||
result.append(outpix),
|
||||
if outpix != 0:
|
||||
if firstimageline > y:
|
||||
firstimageline = y
|
||||
if lastimageline < y:
|
||||
lastimageline = y
|
||||
if firstimageline == 1000:
|
||||
firstimageline = imageysize >> 1
|
||||
lastimageline = firstimageline
|
||||
return imagexsize, imageysize, firstimageline, lastimageline, result
|
||||
|
||||
def encodechar(chardata, bitsperpixel, firstline, height):
|
||||
""" Prevede zadanou bitovou mapu s rozsahem 0-15 do binarniho tvaru
|
||||
s orezem na viditelnou cast za pomoci firstline a height parametru
|
||||
"""
|
||||
result = []
|
||||
w, h, rawdata = chardata
|
||||
# print(rawdata)
|
||||
# print(chardata)
|
||||
# print(firstline, w, len(rawdata))
|
||||
# print(firstline, h, height, len(rawdata))
|
||||
|
||||
index = 0
|
||||
for x in range(w):
|
||||
posBit = 0
|
||||
outdata = 0
|
||||
for y in range(h):
|
||||
if (y >= firstline) and (y <= (height + firstline)):
|
||||
data = rawdata[index] >> 3
|
||||
mask = data << posBit
|
||||
outdata |= mask
|
||||
posBit += 1
|
||||
if posBit > 7:
|
||||
result.append(outdata)
|
||||
posBit = 0
|
||||
outdata = 0
|
||||
index += 1
|
||||
if posBit != 0:
|
||||
result.append(outdata)
|
||||
# optimalizace dat (odstraneni poslednich bytu, ktere jsou nulove)
|
||||
while len(result) > 1 and result[-1] == 0:
|
||||
del result[-1]
|
||||
return result
|
||||
|
||||
def buildfontname(fontname, ptsize, charfrom, charto, bitsperpixel, reduceheight, codepage):
|
||||
""" Build ID of the font
|
||||
"""
|
||||
result = "Font"
|
||||
result += fontname.split(".")[0] + "_"
|
||||
result += "{0}pt_".format(ptsize)
|
||||
result += "{0:02X}_".format(charfrom)
|
||||
result += "{0:02X}_".format(charto)
|
||||
return result
|
||||
|
||||
def createfont(fontname, ptsize, charfrom, charto, bitsperpixel, reduceheight, codepage):
|
||||
""" Write Font file
|
||||
"""
|
||||
fontminline = 65535
|
||||
fontmaxline = 0
|
||||
fontrawdata = []
|
||||
fontheight = 0
|
||||
fontvaliddata = []
|
||||
fontoffsets = []
|
||||
fontsizes = []
|
||||
actualoffset = 0
|
||||
fontmonospacewidth = 0
|
||||
|
||||
for c in range(charfrom, charto + 1):
|
||||
encchar = chr(c)
|
||||
fchar = character(fontname, ptsize, bitsperpixel, encchar)
|
||||
w, h, ymin, ymax, dummy = fchar
|
||||
if w > fontmonospacewidth:
|
||||
fontmonospacewidth = w # znak je zatim nejsirsi - zapamatujeme si jeho sirku pro monospace vystup
|
||||
fontrawdata.append((w, h, dummy))
|
||||
if ymin < fontminline:
|
||||
fontminline = ymin # znak zacina drive nez predchozi (ve vyssim bode), zapamatujeme si pocatek
|
||||
if ymax > fontmaxline:
|
||||
fontmaxline = ymax # znak konci pozdeji nez predchozi (v nizsim bode), zapamatujeme si konec
|
||||
if reduceheight:
|
||||
fontheight = fontmaxline - fontminline + 1 # vypocitame si vysku skutecneho pismena
|
||||
else:
|
||||
fontminline = 0
|
||||
fontheight = h
|
||||
|
||||
for c in fontrawdata:
|
||||
fontoffsets.append(actualoffset)
|
||||
fontchar = encodechar(c, bitsperpixel, fontminline, fontheight)
|
||||
fontvaliddata.append(fontchar)
|
||||
fontsizes.append(len(fontchar))
|
||||
actualoffset += len(fontchar)
|
||||
|
||||
OutFile = open(buildfontname(fontname, ptsize, charfrom, charto, 1, reduceheight, codepage) + ".c", 'w')
|
||||
OutFile.write("/* Font resource created by fontconv.py (c) 2020 by Pavel Brychta (1 bit per pixel)*/\n")
|
||||
OutFile.write("const uint8_t " + buildfontname(fontname, ptsize, charfrom, charto, 1, reduceheight, codepage) + "[] PROGMEM =\n{\n")
|
||||
OutFile.write("\t{0}, /* width for monospace output */\n".format(fontmonospacewidth))
|
||||
OutFile.write("\t{0}, /* font height */\n".format(fontheight))
|
||||
OutFile.write("\t{0}, /* first char ID */\n".format(charfrom))
|
||||
OutFile.write("\t{0}, /* number of characters */\n".format(charto - charfrom + 1))
|
||||
OutFile.write("\t/* index table: offset MSB, offset LSB, length, width */\n")
|
||||
ptr = 0
|
||||
for o in fontoffsets:
|
||||
f = fontrawdata[ptr]
|
||||
OutFile.write("\t0x{0:02X},".format((o >> 8) & 0xff)) # MSB
|
||||
OutFile.write("0x{0:02X},".format(o & 0xff)) # LSB
|
||||
OutFile.write("0x{0:02X},".format(fontsizes[ptr])) # length
|
||||
OutFile.write("0x{0:02X},".format(f[0])) # width
|
||||
OutFile.write("\n")
|
||||
ptr += 1
|
||||
OutFile.write("\t/* glyph raw */")
|
||||
count = 0
|
||||
for c in fontvaliddata:
|
||||
for u in c:
|
||||
if 0 == count:
|
||||
OutFile.write("\n\t")
|
||||
OutFile.write("0x{0:02X}".format(u))
|
||||
count += 1
|
||||
if 20 == count:
|
||||
count = 0
|
||||
OutFile.write(",")
|
||||
OutFile.write("\n};\n")
|
||||
OutFile.close()
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 8:
|
||||
sys.stderr.write("Invalid number of parameters.")
|
||||
return 1
|
||||
else:
|
||||
fontname = argv[1] # jmeno fontu
|
||||
fontsize = int(argv[2]) # velikost fontu (vyska v bodech)
|
||||
charfrom = ast.literal_eval(argv[3]) # kod prvniho znaku, ktery bude ve vyslednem fontu ulozeny
|
||||
charto = ast.literal_eval(argv[4]) # kod posledniho znaku, ktery bude ve vyslednem fontu ulozeny
|
||||
bitsperpixel = int(argv[5]) # pocet bitu/pixel. Platne hodnoty jsou 1, 2, 4
|
||||
reduceheight = int(argv[6]) # priznak, zda do vysledneho fontu neukladat "mrtve" oblasti (spocita skutecnou vysku nejvyssiho znaku a na tuto vysku prepocita vsechny ostatni znaky)
|
||||
codepage = argv[7] # pouzita kodova stranka pro narodni znaky (diakritiku)
|
||||
createfont(fontname, fontsize, charfrom, charto, bitsperpixel, reduceheight, codepage)
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
1
tools/requirements.txt
Normal file
1
tools/requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
PIL
|
7
tools/test_fontconv.sh
Normal file
7
tools/test_fontconv.sh
Normal file
@ -0,0 +1,7 @@
|
||||
# python3 fontconv.py "built titling lt.ttf" 25 0x30 0xff 1 1 cp852
|
||||
# python3 fontconv.py "built_titling_lt.ttf" 25 0x20 0x3f 1 1 cp852
|
||||
# python3 fontconv.py "built_titling_lt.ttf" 60 0x30 0x39 1 1 cp852
|
||||
# python3 fontconv.py "built_titling_sb.ttf" 60 0x30 0x39 1 1 cp852
|
||||
#python3 fontconv.py "built_titling_sb.ttf" 60 0x20 0x23 1 1 cp852
|
||||
#python3 fontconv.py "built_titling_sb.ttf" 60 0x23 0x24 1 1 cp852
|
||||
python3 fontconv.py "built_titling_sb.ttf" 60 0x30 0x39 1 1 cp852
|
Loading…
Reference in New Issue
Block a user