mirror of
https://gitlab.com/MisterBiggs/bdfparse.git
synced 2025-06-16 06:26:39 +00:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
0e82fef264 | |||
5eefdb3ce1 | |||
4eeaecf193 | |||
65e188c764 | |||
a49ce715cc | |||
83c3284e91 | |||
217ff46bd7 | |||
295c9207a5 | |||
7df856e3d6 | |||
7c587789ec | |||
77f1ac9696 | |||
7c82d87248 | |||
7ff36f34eb |
42
README.md
42
README.md
@ -5,20 +5,42 @@ This project takes a .bdf file and turns it into a [NumPy](https://www.numpy.org
|
||||
## Usage
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from bdfparse import Font
|
||||
|
||||
font = parse_chars("9x18.bdf")
|
||||
matrix = font["A"]
|
||||
text = "nson"
|
||||
font = Font('9x18.bdf')
|
||||
|
||||
for letter in text:
|
||||
matrix = np.concatenate((matrix, font[letter]), axis=1)
|
||||
|
||||
plt.imshow(matrix)
|
||||
plt.show()
|
||||
print(font.word('Hi'))
|
||||
```
|
||||
|
||||
Which outputs:
|
||||
|
||||
```python
|
||||
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0]
|
||||
[0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0]
|
||||
[0 0 1 0 0 0 0 0 1 0 0 0 1 1 1 1 1 0]
|
||||
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
||||
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
|
||||
```
|
||||
|
||||
Or you can use matplotlib to make the output a bit prettier.
|
||||
|
||||
```python
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
plt.imshow(font.word('Anson'))
|
||||
```
|
||||
|
||||

|
||||
|
@ -1 +0,0 @@
|
||||
name = "bdf_to_numpy"
|
180
bdfparse.py
180
bdfparse.py
@ -1,180 +0,0 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
def parse_properties(bdfFile):
|
||||
|
||||
properties = {"COMMENT": []}
|
||||
with open(bdfFile, "r") as bdf:
|
||||
line = bdf.readline()
|
||||
|
||||
while not line.startswith("STARTCHAR"):
|
||||
|
||||
if line.startswith("COMMENT"):
|
||||
properties["COMMENT"].append(
|
||||
line.replace("COMMENT", "").replace("\n", "")
|
||||
)
|
||||
|
||||
if line.startswith("FONT"):
|
||||
properties["FONT"] = line.replace("FONT", "").replace("\n", "")
|
||||
|
||||
if line.startswith("SIZE"):
|
||||
properties["SIZE"] = line.replace("SIZE", "").replace("\n", "")
|
||||
|
||||
if line.startswith("FONTBOUNDINGBOX"):
|
||||
properties["FONTBOUNDINGBOX"] = [
|
||||
int(x)
|
||||
for x in (
|
||||
line.replace("FONTBOUNDINGBOX ", "").replace("\n", "").split()
|
||||
)
|
||||
]
|
||||
|
||||
if line.startswith("STARTPROPERTIES"):
|
||||
properties["STARTPROPERTIES"] = line.replace(
|
||||
"STARTPROPERTIES", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("FONTNAME_REGISTRY"):
|
||||
properties["FONTNAME_REGISTRY"] = line.replace(
|
||||
"FONTNAME_REGISTRY", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("FOUNDRY"):
|
||||
properties["FOUNDRY"] = line.replace("FOUNDRY", "").replace("\n", "")
|
||||
|
||||
if line.startswith("FAMILY_NAME"):
|
||||
properties["FAMILY_NAME"] = line.replace("FAMILY_NAME", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("WEIGHT_NAME"):
|
||||
properties["WEIGHT_NAME"] = line.replace("WEIGHT_NAME", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("SLANT"):
|
||||
properties["SLANT"] = line.replace("SLANT", "").replace("\n", "")
|
||||
|
||||
if line.startswith("SETWIDTH_NAME"):
|
||||
properties["SETWIDTH_NAME"] = line.replace("SETWIDTH_NAME", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("ADD_STYLE_NAME"):
|
||||
properties["ADD_STYLE_NAME"] = line.replace(
|
||||
"ADD_STYLE_NAME", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("PIXEL_SIZE"):
|
||||
properties["PIXEL_SIZE"] = line.replace("PIXEL_SIZE", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("POINT_SIZE"):
|
||||
properties["POINT_SIZE"] = line.replace("POINT_SIZE", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("RESOLUTION_X"):
|
||||
properties["RESOLUTION_X"] = line.replace("RESOLUTION_X", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("RESOLUTION_Y"):
|
||||
properties["RESOLUTION_Y"] = line.replace("RESOLUTION_Y", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("SPACING"):
|
||||
properties["SPACING"] = line.replace("SPACING", "").replace("\n", "")
|
||||
|
||||
if line.startswith("AVERAGE_WIDTH"):
|
||||
properties["AVERAGE_WIDTH"] = line.replace("AVERAGE_WIDTH", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("CHARSET_REGISTRY"):
|
||||
properties["CHARSET_REGISTRY"] = line.replace(
|
||||
"CHARSET_REGISTRY", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("CHARSET_ENCODING"):
|
||||
properties["CHARSET_ENCODING"] = line.replace(
|
||||
"CHARSET_ENCODING", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("DEFAULT_CHAR"):
|
||||
properties["DEFAULT_CHAR"] = line.replace("DEFAULT_CHAR", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("FONT_DESCENT"):
|
||||
properties["FONT_DESCENT"] = line.replace("FONT_DESCENT", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("FONT_ASCENT"):
|
||||
properties["FONT_ASCENT"] = line.replace("FONT_ASCENT", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("COPYRIGHT"):
|
||||
properties["COPYRIGHT"] = line.replace("COPYRIGHT", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("CAP_HEIGHT"):
|
||||
properties["CAP_HEIGHT"] = line.replace("CAP_HEIGHT", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("X_HEIGHT"):
|
||||
properties["X_HEIGHT"] = line.replace("X_HEIGHT", "").replace("\n", "")
|
||||
|
||||
if line.startswith("_GBDFED_INFO"):
|
||||
properties["_GBDFED_INFO"] = line.replace("_GBDFED_INFO", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
line = bdf.readline()
|
||||
return properties
|
||||
|
||||
|
||||
def from_hex(values, columns):
|
||||
return np.array(
|
||||
[list(f"{int(row[:2], 16):0>{columns}b}") for row in values.split("\n")],
|
||||
dtype=int,
|
||||
)
|
||||
|
||||
|
||||
def parse_chars(bdfFile):
|
||||
font = {}
|
||||
props = parse_properties(bdfFile)
|
||||
cols = props["FONTBOUNDINGBOX"][0]
|
||||
rows = props["FONTBOUNDINGBOX"][1]
|
||||
|
||||
with open(bdfFile, "r") as bdf:
|
||||
line = bdf.readline()
|
||||
|
||||
# Go through file until chars start.
|
||||
while not line.startswith("CHARS "):
|
||||
line = bdf.readline()
|
||||
characters = int(line.split(" ")[1])
|
||||
|
||||
for character in range(characters):
|
||||
line = bdf.readline()
|
||||
char = line.split(" ")[1].replace("\n", "")
|
||||
|
||||
while not line.startswith("BITMAP"):
|
||||
line = bdf.readline()
|
||||
|
||||
bits = ""
|
||||
for row in range(rows):
|
||||
|
||||
bits += bdf.readline()
|
||||
font[char] = from_hex(bits.strip(), cols)
|
||||
|
||||
if bdf.readline().startswith("ENDFONT"):
|
||||
return font
|
||||
return font
|
||||
|
1
bdfparse/__init__.py
Normal file
1
bdfparse/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .bdfparse import Font
|
232
bdfparse/bdfparse.py
Normal file
232
bdfparse/bdfparse.py
Normal file
@ -0,0 +1,232 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Font:
|
||||
def __init__(self, bdfFile):
|
||||
self.properties = self.parse_properties(bdfFile)
|
||||
self.chars = self.parse_chars(bdfFile)
|
||||
self.cols = self.properties["FONTBOUNDINGBOX"][0]
|
||||
self.rows = self.properties["FONTBOUNDINGBOX"][1]
|
||||
self.shape = (self.rows, self.cols)
|
||||
self.charNames = {
|
||||
" ": "space",
|
||||
"-": "minus",
|
||||
"+": "plus",
|
||||
"0": "zero",
|
||||
"1": "one",
|
||||
"2": "two",
|
||||
"3": "three",
|
||||
"4": "four",
|
||||
"5": "five",
|
||||
"6": "six",
|
||||
"7": "seven",
|
||||
"8": "eight",
|
||||
"9": "nine",
|
||||
"!": "exclam",
|
||||
"@": "at",
|
||||
"#": "numbersign",
|
||||
"$": "dollar",
|
||||
"%": "percent",
|
||||
"&": "ampersand",
|
||||
"*": "asterisk",
|
||||
"(": "parenleft",
|
||||
")": "parenright",
|
||||
",": "comma",
|
||||
".": "period",
|
||||
"/": "slash",
|
||||
"?": "question",
|
||||
}
|
||||
|
||||
def parse_properties(self, bdfFile):
|
||||
|
||||
properties = {"COMMENT": []}
|
||||
with open(bdfFile, "r") as bdf:
|
||||
line = bdf.readline()
|
||||
|
||||
while not line.startswith("STARTCHAR"):
|
||||
|
||||
if line.startswith("COMMENT"):
|
||||
properties["COMMENT"].append(
|
||||
line.replace("COMMENT", "").replace("\n", "")
|
||||
)
|
||||
|
||||
if line.startswith("FONT"):
|
||||
properties["FONT"] = line.replace("FONT", "").replace("\n", "")
|
||||
|
||||
if line.startswith("SIZE"):
|
||||
properties["SIZE"] = line.replace("SIZE", "").replace("\n", "")
|
||||
|
||||
if line.startswith("FONTBOUNDINGBOX"):
|
||||
properties["FONTBOUNDINGBOX"] = [
|
||||
int(x)
|
||||
for x in (
|
||||
line.replace("FONTBOUNDINGBOX ", "")
|
||||
.replace("\n", "")
|
||||
.split()
|
||||
)
|
||||
]
|
||||
|
||||
if line.startswith("STARTPROPERTIES"):
|
||||
properties["STARTPROPERTIES"] = line.replace(
|
||||
"STARTPROPERTIES", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("FONTNAME_REGISTRY"):
|
||||
properties["FONTNAME_REGISTRY"] = line.replace(
|
||||
"FONTNAME_REGISTRY", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("FOUNDRY"):
|
||||
properties["FOUNDRY"] = line.replace("FOUNDRY", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("FAMILY_NAME"):
|
||||
properties["FAMILY_NAME"] = line.replace("FAMILY_NAME", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("WEIGHT_NAME"):
|
||||
properties["WEIGHT_NAME"] = line.replace("WEIGHT_NAME", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("SLANT"):
|
||||
properties["SLANT"] = line.replace("SLANT", "").replace("\n", "")
|
||||
|
||||
if line.startswith("SETWIDTH_NAME"):
|
||||
properties["SETWIDTH_NAME"] = line.replace(
|
||||
"SETWIDTH_NAME", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("ADD_STYLE_NAME"):
|
||||
properties["ADD_STYLE_NAME"] = line.replace(
|
||||
"ADD_STYLE_NAME", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("PIXEL_SIZE"):
|
||||
properties["PIXEL_SIZE"] = line.replace("PIXEL_SIZE", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("POINT_SIZE"):
|
||||
properties["POINT_SIZE"] = line.replace("POINT_SIZE", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("RESOLUTION_X"):
|
||||
properties["RESOLUTION_X"] = line.replace(
|
||||
"RESOLUTION_X", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("RESOLUTION_Y"):
|
||||
properties["RESOLUTION_Y"] = line.replace(
|
||||
"RESOLUTION_Y", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("SPACING"):
|
||||
properties["SPACING"] = line.replace("SPACING", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("AVERAGE_WIDTH"):
|
||||
properties["AVERAGE_WIDTH"] = line.replace(
|
||||
"AVERAGE_WIDTH", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("CHARSET_REGISTRY"):
|
||||
properties["CHARSET_REGISTRY"] = line.replace(
|
||||
"CHARSET_REGISTRY", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("CHARSET_ENCODING"):
|
||||
properties["CHARSET_ENCODING"] = line.replace(
|
||||
"CHARSET_ENCODING", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("DEFAULT_CHAR"):
|
||||
properties["DEFAULT_CHAR"] = line.replace(
|
||||
"DEFAULT_CHAR", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("FONT_DESCENT"):
|
||||
properties["FONT_DESCENT"] = line.replace(
|
||||
"FONT_DESCENT", ""
|
||||
).replace("\n", "")
|
||||
|
||||
if line.startswith("FONT_ASCENT"):
|
||||
properties["FONT_ASCENT"] = line.replace("FONT_ASCENT", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("COPYRIGHT"):
|
||||
properties["COPYRIGHT"] = line.replace("COPYRIGHT", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("CAP_HEIGHT"):
|
||||
properties["CAP_HEIGHT"] = line.replace("CAP_HEIGHT", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("X_HEIGHT"):
|
||||
properties["X_HEIGHT"] = line.replace("X_HEIGHT", "").replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
if line.startswith("_GBDFED_INFO"):
|
||||
properties["_GBDFED_INFO"] = line.replace(
|
||||
"_GBDFED_INFO", ""
|
||||
).replace("\n", "")
|
||||
|
||||
line = bdf.readline()
|
||||
return properties
|
||||
|
||||
def parse_chars(self, bdfFile):
|
||||
font = {}
|
||||
cols = self.properties["FONTBOUNDINGBOX"][0]
|
||||
rows = self.properties["FONTBOUNDINGBOX"][1]
|
||||
|
||||
with open(bdfFile, "r") as bdf:
|
||||
line = bdf.readline()
|
||||
|
||||
# Go through file until chars start.
|
||||
while not line.startswith("CHARS "):
|
||||
line = bdf.readline()
|
||||
characters = int(line.split(" ")[1])
|
||||
|
||||
for character in range(characters):
|
||||
line = bdf.readline()
|
||||
char = line.split(" ")[1].replace("\n", "")
|
||||
|
||||
while not line.startswith("BITMAP"):
|
||||
line = bdf.readline()
|
||||
|
||||
bits = ""
|
||||
for row in range(rows):
|
||||
|
||||
bits += bdf.readline()
|
||||
font[char] = self.from_hex(bits.strip(), cols)
|
||||
|
||||
if bdf.readline().startswith("ENDFONT"):
|
||||
return font
|
||||
return font
|
||||
|
||||
def from_hex(self, values, columns):
|
||||
return np.array(
|
||||
[list(f"{int(row[:2], 16):0>{columns}b}") for row in values.split("\n")],
|
||||
dtype=int,
|
||||
)
|
||||
|
||||
def word(self, word: str):
|
||||
matrix = np.zeros(self.shape)
|
||||
for char in word:
|
||||
if char in self.charNames.keys():
|
||||
arr = self.chars[self.charNames[char]]
|
||||
else:
|
||||
arr = self.chars[char]
|
||||
|
||||
matrix = np.concatenate((matrix, arr), axis=1)
|
||||
|
||||
return matrix[:, self.cols :]
|
||||
|
8
setup.py
8
setup.py
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 albig
|
||||
# Copyright (c) 2019 Anson Biggs
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
@ -9,14 +9,14 @@ with open("README.md", "r") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
setuptools.setup(
|
||||
name="bdf-to-numpy",
|
||||
version="2019.1",
|
||||
name="bdfparse",
|
||||
version="2019.8",
|
||||
author="Anson Biggs",
|
||||
author_email="anson@ansonbiggs.com",
|
||||
description="A package for reading .bdf files into NumPy arrays.",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://gitlab.com/MisterBiggs/bdf-to-numpy",
|
||||
url="https://gitlab.com/MisterBiggs/bdfparse",
|
||||
packages=setuptools.find_packages(),
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3.7",
|
||||
|
Loading…
x
Reference in New Issue
Block a user