From: git Date: Tue, 17 Feb 2026 17:38:43 +0000 (-0500) Subject: initial public commit X-Git-Url: https://git.datadissipation.net/?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=fontgen.git initial public commit --- a28d19df914d09ffa93608f23220dfb43c9b1238 diff --git a/README.md b/README.md new file mode 100644 index 0000000..cd6ff36 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +This script produces a ROM image that can be used to turn any parallel ROM into a character generator for 6845-style CRTCs and similar video output systems. + +It works by going over one character cell at a time, starting at the top left corner of an image and processing through each row (if there are multiple), turning every pixel with a value of `#000` (black) into a `1` (every other value is a `0`). + +An example font is provided. diff --git a/font.png b/font.png new file mode 100644 index 0000000..7019ef7 Binary files /dev/null and b/font.png differ diff --git a/fontgen.py b/fontgen.py new file mode 100644 index 0000000..740ae1d --- /dev/null +++ b/fontgen.py @@ -0,0 +1,66 @@ +from bitarray import bitarray +from PIL import Image +import numpy as np +import os, sys, glob + +os.chdir(sys.path[0]) # look for png files in the script directory + +pxs = int(input('Character width (in pxs): ')) +lns = int(input('Character height (in pxs): ')) +romwrd = int(input('Parallel ROM Word size (in bits): ')) +romcpt = int(input('ROM size (in KWords): ')) + +actualromsz = romwrd * romcpt * 1024 + +if romwrd < pxs: + raise ValueError("Character width should be less than or equal to the ROM word size") + +png = sorted(glob.glob("*.png")) +if len(png) == 0: + raise ValueError("No PNG files found in the current directory.") + +print('\nFound images:') +for i, filename in enumerate(png, 1): + print(f'{i}. {filename}') + +while 1: + try: + selection = int(input('\nSelect image by number: ')) + if 1 <= selection <= len(png): + selected = png[selection - 1] + print(f'Selected: {selected}') + break + else: + print(f'Please enter a number between 1 and {len(png)}.') + except ValueError: + print('Invalid input. Please enter a number.') + +im = Image.open(png[0]).convert('RGB') +if im.size[0] % pxs != 0 or im.size[1] % lns != 0: + raise ValueError("Image resolution should be in multiples of character width and height specified.") + +imgarr = np.array(im) + +outarr = bitarray() +paddbits = romwrd - pxs if pxs < romwrd else 0 + +for y in range(im.size[1] // lns): + for x in range(im.size[0] // pxs): + for y1 in range(lns): + if paddbits > 0: + outarr.extend([0] * paddbits) + + ystart = y1 + lns * y + xstart = pxs * x + char_block = imgarr[ystart, xstart:xstart + pxs] + + isblack = np.all(char_block == 0, axis=1) + outarr.extend(isblack.astype(int).tolist()) + +if outarr[actualromsz:].count(1) > 0: + print("Couldn't fit all the data: insufficient ROM size.") + +with open("a.out", "wb") as f: + outarr[0:actualromsz].tofile(f) + +print('\nDone!') diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1682c30 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +numpy +pillow +bitarray