Skip to content

trevorld/bittermelon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

bittermelon bittermelon hex sticker

CRAN Status Badge R-CMD-check Coverage Status

Table of Contents

Please note this README is best viewed elsewhere than github.com. github.com's default line-height setting causes distracting extraneous horizontal lines to appear when "printing" bitmaps and github.com does not allow using CSS to set a more reasonable line-height value.

  • {bittermelon} features over a dozen functions that can modify individual bitmaps or every bitmap within a "bitmap list" or "bitmap font".
  • There is a special emphasis on bitmap fonts and their glyphs. It provides native read/write support for the 'hex' and 'yaff' bitmap font formats and if monobit is also installed then it can read/write several more bitmap font formats.
  • It can print bitmaps to the R terminal.
  • Besides supporting the builtin bm_bitmap() and bm_pixmap() objects it also supports modifying {magick}'s "magick-image" objects and base R's "nativeRaster" and "raster" objects.
remotes::install_github("trevorld/bittermelon")
  • The functions read_monobit() and write_monobit() require that monobit is installed (i.e. pip3 install monobit).
  • The function bm_distort() requires the suggested package magick.
  • Support for "nativeRaster" objects requires the suggested package farver.
library("bittermelon") # remotes::install_github("trevorld/bittermelon")
font_file <- system.file("fonts/spleen/spleen-8x16.hex.gz", package = "bittermelon")
font <- read_hex(font_file)
bml <- as_bm_list("RSTATS", font = font)
# With vertical compression
bm <- bml |> bm_call(cbind) |> bm_compress("vertical")
print(bm)
                                                
β–ˆβ–ˆβ–€β–€β–€β–ˆβ–„ β–„β–ˆβ–€β–€β–€β–€β–€ β–€β–€β–€β–ˆβ–ˆβ–€β–€β–€β–„β–ˆβ–€β–€β–€β–ˆβ–„ β–€β–€β–€β–ˆβ–ˆβ–€β–€β–€β–„β–ˆβ–€β–€β–€β–€β–€ 
β–ˆβ–ˆ   β–ˆβ–ˆ β–ˆβ–ˆ         β–ˆβ–ˆ   β–ˆβ–ˆ   β–ˆβ–ˆ    β–ˆβ–ˆ   β–ˆβ–ˆ      
β–ˆβ–ˆβ–€β–€β–€β–ˆβ–„  β–€β–€β–€β–€β–ˆβ–„    β–ˆβ–ˆ   β–ˆβ–ˆβ–€β–€β–€β–ˆβ–ˆ    β–ˆβ–ˆ    β–€β–€β–€β–€β–ˆβ–„ 
β–ˆβ–ˆ   β–ˆβ–ˆ      β–ˆβ–ˆ    β–ˆβ–ˆ   β–ˆβ–ˆ   β–ˆβ–ˆ    β–ˆβ–ˆ        β–ˆβ–ˆ 
β–ˆβ–ˆ   β–ˆβ–ˆ β–„β–„β–„β–„β–„β–ˆβ–€    β–ˆβ–ˆ   β–ˆβ–ˆ   β–ˆβ–ˆ    β–ˆβ–ˆ   β–„β–„β–„β–„β–„β–ˆβ–€ 
                                                
                                                
# Upside down with ASCII characters
bm <- bml |>
    bm_flip("both") |>
    bm_call(cbind, direction = "RTL")
print(bm, px = px_ascii)
------------------------------------------------
------------------------------------------------
------------------------------------------------
------------------------------------------------
--@@@@@@---@@----@@---@@---@@-----@@@@@@-@@---@@
-@@--------@@----@@---@@---@@----@@------@@---@@
-@@--------@@----@@---@@---@@----@@------@@---@@
-@@--------@@----@@---@@---@@----@@------@@---@@
-@@--------@@----@@---@@---@@----@@------@@---@@
--@@@@@----@@----@@@@@@@---@@-----@@@@@---@@@@@@
------@@---@@----@@---@@---@@---------@@-@@---@@
------@@---@@----@@---@@---@@---------@@-@@---@@
------@@---@@----@@---@@---@@---------@@-@@---@@
-@@@@@@-@@@@@@@@--@@@@@-@@@@@@@@-@@@@@@---@@@@@@
------------------------------------------------
------------------------------------------------
# With a shadow effect and borders
bm <- bml |>
    bm_pad(sides = 2L) |>
    bm_shadow() |>
    bm_extend(sides = c(2L, 1L), value = 3L) |>
    bm_call(cbind) |>
    bm_pad(sides = 2L, value = 3L)
print(bm)
β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“
β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“
β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–’β–’β–ˆβ–ˆβ–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–’β–’β–’β–’β–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–’β–’β–ˆβ–ˆβ–’β–’β–’β–’β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–’β–’β–ˆβ–ˆβ–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–’β–’β–ˆβ–ˆβ–’β–’β–’β–’β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–’β–’β–’β–’β–’β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–’β–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–’β–’β–ˆβ–ˆβ–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–’β–’β–’β–ˆβ–ˆβ–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–’β–’β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–’β–’β–’β–ˆβ–ˆβ–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–’β–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–’β–’β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–‘β–’β–’β–‘β–‘β–‘β–’β–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–’β–’β–‘β–‘β–‘β–’β–’β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“
β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–“β–“
β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“
β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“

We can also print colored terminal output with help of {cli}:

if (cli::num_ansi_colors() >= 16L)
    print(bm, px = " ",
          bg = c(cli::bg_br_white, cli::bg_blue, cli::bg_cyan, cli::bg_red))
plot(bm, col = c("white", "blue3", "cyan3", "red3"))

Stylized bitmap image that says 'RSTATS`.

# Also supports {gridpattern} matrices
gridpattern::pattern_weave("twill_herringbone", nrow=14L, ncol = 50L) |>
    as_bm_bitmap() |>
    print(compress = "vertical")
 β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  
  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ 
β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ  β–ˆβ–„ β–€β–ˆ
β–€β–€β–„β–„β–€β–„β–„β–€β–€β–„β–„β–€β–„β–„β–€β–€β–„β–„β–€β–„β–„β–€β–€β–„β–„β–€β–„β–„β–€β–€β–„β–„β–€β–„β–„β–€β–€β–„β–„β–€β–„β–„β–€β–€β–„β–„β–€β–„β–„β–€
 β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ 
β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆ
β–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ β–„β–ˆβ–€ β–ˆβ–ˆ
gridpattern::pattern_square(subtype=8L, nrow=8L, ncol = 50L) |>
    as_bm_pixmap(s, col = grDevices::rainbow(8L)) |>
    plot()

Rainbow squares

# Also supports {mazing} mazes
set.seed(42)
m <- mazing::maze(16L, 32L)
m |> as_bm_bitmap(walls = TRUE) |>
    print(compress = "vertical")
β–ˆβ–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–ˆβ–€β–€β–€β–ˆβ–€β–€β–€β–€β–€β–ˆβ–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–ˆβ–€β–€β–€β–€β–€β–ˆβ–€β–€β–€β–€β–€β–€β–€β–ˆβ–€β–€β–€β–€β–€β–€β–€β–ˆβ–€β–€β–€β–ˆ 
β–ˆ β–ˆβ–€β–€β–€β–€β–€β–€β–€β–€β–€β–ˆ β–€β–€β–€ β–ˆ β–€ β–ˆ β–ˆ β–ˆ β–ˆ β–€β–€β–ˆβ–€β–€β–€β–€ β–€ β–ˆβ–€β–€ β–ˆ β–ˆβ–€β–€ β–ˆ β–€ β–ˆβ–€β–€β–€β–ˆ β–ˆ β–ˆ β–ˆ 
β–ˆ β–ˆ β–€β–€β–€β–€β–ˆβ–€β–€ β–€β–€β–€β–€β–ˆβ–€β–ˆβ–€β–€β–€β–€ β–ˆ β–ˆ β–ˆβ–€β–€ β–ˆβ–€β–€β–€β–ˆβ–€β–ˆβ–€β–€ β–ˆβ–€β–€β–€β–€ β–ˆβ–€β–€β–€β–€β–€β–ˆ β–€β–€β–€ β–ˆ β–ˆ β–ˆ 
β–ˆ β–ˆβ–€β–€ β–ˆβ–€β–€ β–ˆβ–€β–€β–€β–€ β–ˆ β–ˆ β–€β–€β–ˆβ–€β–ˆ β–€β–€β–ˆ β–ˆβ–€β–€ β–ˆ β–ˆ β–€ β–€β–€β–€ β–ˆβ–€β–€β–€β–€β–€β–€β–€β–€ β–ˆ β–€β–€β–ˆβ–€β–€β–€β–€ β–ˆ 
β–ˆ β–€β–€β–€β–€β–ˆ β–ˆβ–€β–ˆ β–ˆβ–€β–€β–€β–€ β–ˆβ–€β–€ β–ˆ β–ˆβ–€β–€ β–ˆ β–ˆ β–ˆβ–€β–ˆ β–€β–€β–ˆβ–€β–€β–€β–€β–€β–ˆ β–ˆβ–€β–ˆ β–€β–€β–€β–€β–€β–€β–€ β–ˆ β–ˆ β–€β–€β–ˆ 
β–ˆβ–€β–€β–€β–€ β–ˆ β–ˆ β–€ β–ˆ β–ˆβ–€β–ˆ β–ˆ β–ˆβ–€β–€ β–ˆ β–ˆβ–€β–€ β–ˆ β–€ β–€β–€β–ˆ β–ˆ β–ˆ β–€β–€β–ˆ β–ˆ β–€β–€β–€β–€β–€β–€β–ˆβ–€β–€β–€β–€ β–€β–€β–ˆ β–ˆ 
β–ˆ β–ˆβ–€β–€β–€β–€ β–ˆ β–€β–€β–ˆ β–ˆ β–€ β–ˆ β–ˆβ–€β–€ β–ˆ β–ˆ β–ˆ β–€β–€β–€ β–ˆβ–€β–€ β–ˆ β–ˆβ–€β–€ β–ˆ β–€ β–ˆβ–€β–€β–€β–ˆ β–ˆβ–€β–€β–€β–€β–€β–€β–€β–ˆ β–ˆ 
β–ˆ β–€ β–ˆβ–€β–ˆβ–€β–€β–€β–€ β–ˆ β–€β–€β–€β–€β–ˆ β–ˆ β–ˆ β–ˆ β–€β–€β–€β–€β–ˆ β–€β–€β–ˆ β–€β–€β–€β–€β–ˆ β–€β–€β–€β–€β–€β–€β–€ β–ˆ β–ˆ β–€ β–ˆβ–€β–€β–€β–ˆ β–€ β–ˆ 
β–ˆβ–€β–€β–€β–€ β–ˆ β–ˆβ–€β–€β–€β–€ β–€β–€β–ˆ β–ˆ β–ˆ β–€β–€β–€β–€β–€β–€β–ˆ β–ˆ β–ˆβ–€β–€β–€β–ˆβ–€β–€ β–ˆ β–ˆβ–€β–€β–€β–€ β–ˆβ–€β–€β–€β–ˆβ–€β–€β–€β–ˆ β–ˆ β–€β–€β–ˆ β–ˆ 
β–ˆ β–€β–€β–ˆ β–€ β–ˆ β–€β–€β–ˆβ–€β–€β–€β–€ β–ˆ β–€β–€β–ˆ β–ˆ β–€β–€β–€ β–ˆ β–ˆ β–ˆ β–ˆ β–€β–€β–ˆ β–ˆ β–ˆ β–ˆβ–€β–€ β–ˆ β–€ β–ˆ β–€ β–€β–€β–ˆ β–ˆ β–ˆ 
β–ˆβ–€β–€ β–€β–€β–€β–€β–€β–€β–ˆβ–€β–€ β–ˆβ–€β–€ β–ˆβ–€β–€ β–ˆ β–ˆβ–€β–€β–€β–ˆ β–€β–€β–€ β–ˆ β–€β–€β–€ β–ˆβ–€β–€ β–ˆβ–€β–€ β–ˆβ–€β–€β–€β–ˆβ–€β–€β–€β–€β–€β–€β–€β–€ β–ˆ β–ˆ 
β–ˆ β–ˆβ–€β–€β–€β–€β–€β–ˆ β–€ β–ˆβ–€β–€ β–€β–€β–ˆ β–€β–€β–€β–€β–€ β–ˆ β–ˆβ–€β–ˆβ–€β–€β–€β–€β–€β–€β–€β–€β–€β–€ β–€β–€β–ˆ β–ˆβ–€β–€ β–ˆβ–€β–€ β–ˆβ–€β–€β–€β–ˆ β–ˆβ–€β–€ β–ˆ 
β–ˆ β–ˆ β–€β–€β–ˆ β–ˆβ–€β–€β–€β–€β–€β–€β–€β–ˆ β–ˆβ–€β–€β–€β–€β–€β–ˆβ–€β–ˆ β–ˆ β–€ β–ˆβ–€β–€β–€β–ˆβ–€β–€β–€β–€β–€β–ˆ β–€ β–ˆβ–€β–€ β–ˆ β–ˆβ–€β–€ β–ˆ β–€β–€β–ˆ β–ˆβ–€β–ˆ 
β–ˆ β–ˆβ–€β–ˆ β–ˆ β–€ β–ˆβ–€β–€β–€β–ˆ β–ˆ β–€β–€β–ˆ β–ˆ β–€ β–ˆ β–ˆ β–€β–€β–ˆ β–€β–€β–€ β–ˆ β–€β–€β–€β–€β–€β–€β–€ β–ˆ β–ˆ β–€ β–ˆβ–€β–€β–€β–ˆ β–ˆ β–ˆ β–ˆ 
β–ˆ β–ˆ β–ˆ β–ˆβ–€β–€β–€β–€ β–ˆ β–ˆ β–€β–€β–ˆ β–€ β–ˆ β–ˆβ–€β–€ β–ˆβ–€β–ˆ β–ˆβ–€β–€β–€β–ˆ β–ˆβ–€β–€ β–ˆβ–€β–€β–€β–ˆβ–€β–€ β–ˆβ–€β–€β–€β–€β–€β–€ β–ˆ β–€ β–ˆ β–ˆ 
β–ˆ β–€ β–ˆ β–€β–€β–€β–€β–ˆ β–€β–€β–€β–€β–€ β–€β–€β–€β–€β–€β–€β–€ β–ˆβ–€β–€ β–€ β–€ β–ˆ β–€β–€β–€ β–ˆβ–€β–€ β–€β–€β–€ β–€β–€β–€β–€β–€β–€β–€ β–ˆ β–€β–€β–€β–€β–€ β–ˆ 
β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€β–€ 
# Can also visualize the maze solutions
pal <- grDevices::palette.colors()
m |> as_bm_pixmap(start = "top", end = "bottom",
                  col = c(pal[6L], "white", pal[7L], pal[5L])) |>
   bm_pad(sides = 1L) |>
   plot()

A maze

# Contains some built-in farming crops sprites
crops <- farming_crops_16x16()
names(crops)
 [1] "avocado"    "cassava"    "coffee"     "corn"       "cucumber"  
 [6] "eggplant"   "grapes"     "lemon"      "melon"      "orange"    
[11] "pineapple"  "potato"     "rice"       "rose"       "strawberry"
[16] "sunflower"  "tomato"     "tulip"      "turnip"     "wheat"     
corn <- crops$corn$portrait
grapes <- crops$grapes$portrait
orange <- crops$orange$stage5
tulip <- crops$tulip$portrait
pm <- cbind(corn, grapes, orange, tulip)

We can pretty print sprites to the terminal with help of {cli}:

if (cli::is_utf8_output() && cli::num_ansi_colors() >= 256L)
    print(pm, compress = "v", bg = "white")
plot(pm)

Sprites of some food crops

{bittermelon} has a builtin versions of the 8x16 Spleen font as well as 4x6 and 6x13 Fixed fonts.

spleen_8x16 <- read_hex(system.file("fonts/spleen/spleen-8x16.hex.gz",
                                    package = "bittermelon"))
fixed_4x6 <- read_yaff(system.file("fonts/fixed/4x6.yaff.gz",
                                   package = "bittermelon"))
fixed_5x8 <- read_yaff(system.file("fonts/fixed/5x8.yaff.gz",
                                   package = "bittermelon"))
fixed_6x13 <- read_yaff(system.file("fonts/fixed/6x13.yaff.gz",
                                    package = "bittermelon"))
as_bm_bitmap("RSTATS", font = spleen_8x16) |> bm_compress("v")
                                                
β–ˆβ–ˆβ–€β–€β–€β–ˆβ–„ β–„β–ˆβ–€β–€β–€β–€β–€ β–€β–€β–€β–ˆβ–ˆβ–€β–€β–€β–„β–ˆβ–€β–€β–€β–ˆβ–„ β–€β–€β–€β–ˆβ–ˆβ–€β–€β–€β–„β–ˆβ–€β–€β–€β–€β–€ 
β–ˆβ–ˆ   β–ˆβ–ˆ β–ˆβ–ˆ         β–ˆβ–ˆ   β–ˆβ–ˆ   β–ˆβ–ˆ    β–ˆβ–ˆ   β–ˆβ–ˆ      
β–ˆβ–ˆβ–€β–€β–€β–ˆβ–„  β–€β–€β–€β–€β–ˆβ–„    β–ˆβ–ˆ   β–ˆβ–ˆβ–€β–€β–€β–ˆβ–ˆ    β–ˆβ–ˆ    β–€β–€β–€β–€β–ˆβ–„ 
β–ˆβ–ˆ   β–ˆβ–ˆ      β–ˆβ–ˆ    β–ˆβ–ˆ   β–ˆβ–ˆ   β–ˆβ–ˆ    β–ˆβ–ˆ        β–ˆβ–ˆ 
β–ˆβ–ˆ   β–ˆβ–ˆ β–„β–„β–„β–„β–„β–ˆβ–€    β–ˆβ–ˆ   β–ˆβ–ˆ   β–ˆβ–ˆ    β–ˆβ–ˆ   β–„β–„β–„β–„β–„β–ˆβ–€ 
                                                
                                                
as_bm_bitmap("RSTATS", font = fixed_4x6) |> bm_compress("v")
β–ˆβ–€β–„ β–„β–€β–€ β–€β–ˆβ–€ β–„β–€β–„ β–€β–ˆβ–€ β–„β–€β–€ 
β–ˆβ–€β–„  β–€β–„  β–ˆ  β–ˆβ–€β–ˆ  β–ˆ   β–€β–„ 
β–€ β–€ β–€β–€   β–€  β–€ β–€  β–€  β–€β–€  
as_bm_bitmap("RSTATS", font = fixed_5x8) |> bm_compress("v")
β–„β–„β–„   β–„β–„   β–„β–„β–„  β–„β–„   β–„β–„β–„  β–„β–„  
β–ˆ  β–ˆ β–€β–„ β–€   β–ˆ  β–ˆ  β–ˆ   β–ˆ  β–€β–„ β–€ 
β–ˆβ–€β–€β–„ β–„ β–€β–„   β–ˆ  β–ˆβ–€β–€β–ˆ   β–ˆ  β–„ β–€β–„ 
β–€  β–€  β–€β–€    β–€  β–€  β–€   β–€   β–€β–€  
as_bm_bitmap("RSTATS", font = fixed_6x13) |> bm_compress("v")
                                    
β–ˆβ–€β–€β–€β–„ β–„β–€β–€β–€β–„ β–€β–€β–ˆβ–€β–€  β–„β–€β–„  β–€β–€β–ˆβ–€β–€ β–„β–€β–€β–€β–„ 
β–ˆ   β–ˆ β–ˆ       β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ     
β–ˆβ–€β–ˆβ–€   β–€β–€β–€β–„   β–ˆ   β–ˆβ–„β–„β–„β–ˆ   β–ˆ    β–€β–€β–€β–„ 
β–ˆ  β–€β–„ β–„   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–„   β–ˆ 
β–€   β–€  β–€β–€β–€    β–€   β–€   β–€   β–€    β–€β–€β–€  
                                    

The {hexfont} package includes a helper function unifont() which loads several GNU Unifont hex fonts as a single {bittermelon} bm_font() object. GNU Unifont is a monoscale bitmap font (8x16 and 16x16 glyphs) that pretty much covers all of the official Unicode glyphs plus several of the artificial scripts in the (Under-)ConScript Unicode Registry.

library("hexfont")
system.time(font <- unifont()) # Unifont is a **big** font
   user  system elapsed 
152.565   0.027 152.621 
length(font) |> prettyNum(big.mark = ",") # number of glyphs
[1] "123,234"
object.size(font) |> format(units = "MB") # memory used
[1] "196.5 Mb"
# Faster to load from a cache
saveRDS(font, "unifont.rds")
system.time(font <- readRDS("unifont.rds"))
   user  system elapsed 
  0.497   0.004   0.501 
# Or just load the subset of GNU Unifont you need
s <- "οΌ²εΎˆζ£’οΌ"
system.time(font_s <- unifont(ucp = str2ucp(s)))
   user  system elapsed 
  0.725   0.000   0.725 
# Mandarin Chinese
as_bm_bitmap(s, font = font_s) |> bm_compress("v")
                    β–ˆ β–„β–„β–„β–„β–„β–„β–„      β–ˆ      β–ˆ                     
   β–„β–„β–„β–„β–„β–„β–„        β–„β–€  β–ˆ     β–ˆ      β–ˆ  β–€β–€β–€β–€β–ˆβ–€β–€β–€β–€      β–„β–ˆβ–„        
    β–ˆ     β–€β–„     β–€  β–ˆ β–ˆβ–€β–€β–€β–€β–€β–ˆ   β–€β–€β–€β–ˆβ–€β–€ β–€β–€β–ˆβ–€β–€β–€β–€       β–ˆβ–ˆβ–ˆ        
    β–ˆ     β–„β–€      β–„β–ˆ  β–ˆβ–„β–„β–„β–„β–„β–ˆ     β–ˆβ–ˆβ–„ β–€β–€β–ˆβ–€β–€β–€β–ˆβ–€β–€      β–€β–ˆβ–€        
    β–ˆβ–€β–€β–€β–ˆβ–€      β–„β–€ β–ˆ  β–ˆ  β–ˆ  β–„β–€   β–ˆ β–ˆ β–€β–„β–€  β–ˆ  β–€β–„       β–ˆ         
    β–ˆ    β–€β–„        β–ˆ  β–ˆ   β–ˆβ–€    β–€  β–ˆ    β–€β–€β–ˆβ–€β–€                   
   β–„β–ˆβ–„    β–„β–ˆβ–„      β–ˆ  β–ˆ β–„  β–€β–„      β–ˆ  β–€β–€β–€β–€β–ˆβ–€β–€β–€β–€       β–ˆ         
                   β–ˆ  β–ˆβ–€     β–€β–€    β–ˆ      β–ˆ                     
# Emoji
as_bm_bitmap("🐭🐲🐡", font = font) |> bm_compress("v")
  β–„β–„       β–„β–„           β–„β–„β–„            β–„β–„       
β–„β–€  β–€β–„β–„β–„β–„β–„β–€  β–€β–„       β–„β–ˆβ–€           β–„β–ˆβ–€β–ˆβ–ˆβ–€β–ˆβ–„    
β–ˆ    β–€   β–€    β–ˆ      β–„β–ˆβ–ˆβ–ˆβ–ˆ       β–„β–€β–ˆ β–„β–„  β–„β–„ β–ˆβ–€β–„ 
β–„β–ˆ   β–€   β–€   β–ˆβ–„   β–„β–„β–ˆβ–ˆβ–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ     β–€β–„β–ˆ β–€β–€  β–€β–€ β–ˆβ–„β–€ 
β–„β–ˆβ–€    β–„    β–€β–ˆβ–„ β–„β–ˆβ–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ     β–„β–€      β–€β–„   
  β–€β–„  β–€β–€β–€  β–„β–€   β–€β–€β–€β–€β–€β–ˆβ–ˆβ–ˆβ–€β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ    β–ˆ β–€β–„β–„β–„β–„β–€ β–ˆ   
    β–€β–€β–„β–„β–„β–€β–€        β–„β–ˆβ–ˆβ–ˆ   β–ˆβ–ˆβ–ˆβ–ˆβ–€     β–€β–€β–„β–„β–„β–„β–€β–€    
                  β–€β–€β–€     β–€β–€β–€                   
# Klingon
as_bm_list("ο£‘ο£ο£¦ο£™ο£—ο£˜", font = font) |>
    bm_pad(type = "trim", left = 1L, right = 1L) |>
    bm_call(cbind) |>
    bm_compress("v")
                                                                              
    β–„β–ˆβ–„ β–„β–„β–ˆβ–ˆβ–€β–€  β–€β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ               β–„β–€       β–„β–ˆβ–„    β–„β–ˆβ–€  β–€β–ˆβ–„    β–„β–„       
 β–„β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€            β–€β–ˆβ–ˆ β–€            β–„β–ˆβ–€       β–ˆβ–ˆβ–ˆβ–€β–€  β–ˆβ–ˆβ–ˆ    β–ˆβ–ˆ   β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 
  β–€β–ˆβ–ˆ  β–ˆβ–ˆ             β–„β–ˆβ–ˆβ–ˆ    β–„β–ˆ      β–„β–ˆβ–ˆ       β–ˆβ–ˆβ–€      β–€β–ˆβ–ˆβ–„β–„β–ˆβ–€      β–ˆβ–ˆβ–€ β–€β–ˆβ–ˆ 
   β–€    β–ˆβ–„           β–ˆβ–ˆβ–ˆ      β–ˆβ–ˆβ–ˆβ–„β–„β–„β–„β–„β–ˆβ–ˆ      β–„β–ˆβ–ˆβ–ˆ        β–€β–ˆβ–ˆβ–ˆβ–€      β–„β–ˆβ–€   β–ˆβ–€ 
         β–ˆβ–„          β–€β–ˆβ–„      β–ˆβ–ˆβ–€β–€β–€β–€β–€β–€β–ˆβ–ˆβ–ˆ    β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„       β–€β–ˆβ–„     β–„β–ˆβ–€   β–ˆβ–€  
          β–€β–„           β–€β–€β–„   β–„β–€        β–€β–ˆβ–„         β–€β–€β–„        β–€β–€β–„  β–„β–€    β–€    
                                                                              

I wrote {bittermelon} in order to help create Game Bit, a fixed-width bitmap font specialized for making board game diagrams. The duospaced version is called Game Bit Duo while the square monospaced version is called Game Bit Mono. Check out the Game Bit Github repo to see an extended example of using {bittermelon} to make a custom font (albeit with several glyphs adopted/adapted from GNU Unifont).

Go diagram Dominoes diagram

R packages

  • bdftools provides some tools for reading and manipulating BDF bitmap fonts. In particular provides much richer graphical output capabilities than {bittermelon} will likely support including a specialized {ggplot2} geom.
  • farver provides colour space manipulation. Allows {bittermelon} to convert to/from "nativeRaster" objects.
  • fontr allows one to extract character glyphs from a specific font (which itself may not be a bitmap font) as a bitmap.
  • hexfont provides GNU Unifont as {bittermelon} font objects.
  • magick bindings to ImageMagick. Powers {bittermelon}'s bm_distort() method.
  • mazing generates mazes.
  • nara "nativeRaster" tools.
  • naratext renders text to "nativeRaster" images im memory. Its nr_text_bitmap() method works with {bittermelon} font objects.
  • pixeltrix lets you make pixel art interactively in a plot window.

Python

  • BDF Parser Python library
  • bdflib
  • monobit lets one modify bitmap fonts and convert between several formats. Provides monobit-convert which is used by bittermelon::read_monobit() and bittermelon::write_monobit().

Other

Fonts