Skip to content

Instantly share code, notes, and snippets.

@formicant
Last active June 26, 2024 02:44
Show Gist options
  • Select an option

  • Save formicant/2731a0d4c1e678ef3b2d83ec9a406a01 to your computer and use it in GitHub Desktop.

Select an option

Save formicant/2731a0d4c1e678ef3b2d83ec9a406a01 to your computer and use it in GitHub Desktop.
import numpy as np
from sys import byteorder
_utf32 = 'utf-32-le' if byteorder == 'little' else 'utf-32-be'
_braille_char_base = 0x2800 # U+2800 BRAILLE PATTERN BLANK
_braille_matrix = np.array([
[0x01, 0x08],
[0x02, 0x10],
[0x04, 0x20],
[0x40, 0x80],
], dtype=np.uint32)
def to_braille(bitmap: np.ndarray, threshold: float=128) -> list[str]:
"""
Converts a bitmap into Braille characters. Returns a list of lines.
`bitmap` should be a 2D Numpy array of bools or numbers.
`True` values or numeric values >= `threshold` are shown as dots.
"""
if bitmap.dtype != np.bool_:
bitmap = bitmap >= threshold
h, w = bitmap.shape
if h % 4 != 0 or w % 2 != 0:
bitmap = np.pad(bitmap, ((0, (4 - h) % 4), (0, w % 2)))
h, w = bitmap.shape
# split the bitmap into 4-row chunks and each row into 2-pixel chunks:
chunks = np.reshape(bitmap, (h // 4, 4, w // 2, 2))
# multiply every 4×2 chunk by `_braille_matrix` using scalar multiplication:
braille_char_numbers = np.tensordot(chunks, _braille_matrix, axes=((1, 3), (0, 1)))
utf32_codepoints = (_braille_char_base + braille_char_numbers).astype(np.uint32)
return [line.tobytes().decode(_utf32) for line in utf32_codepoints]
_format_normal = '\033[0m'
_format_bold = '\033[1m'
def print_braille(bitmap: np.ndarray, threshold: float=128, bold: bool=True) -> None:
joined_lines = '\n'.join(to_braille(bitmap, threshold))
if bold:
print(_format_bold + joined_lines + _format_normal)
else:
print(joined_lines)
if __name__ == '__main__':
r = 25
def f(x: float, y: float) -> float:
return ((x - r)**2 + (y - r)**2) % 200
bitmap = np.fromfunction(f, (2 * r, 2 * r))
print_braille(bitmap, threshold=100, bold=False)
print()
print_braille(bitmap, threshold=100, bold=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment