{bittermelon}
provides functions for creating and
modifying bitmaps.bm_bitmap()
and
bm_pixmap()
objects it also supports modifying
{magick}
’s “magick-image” objects and base R’s
“nativeRaster” and “raster” objects.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}
:
# Also supports {gridpattern} matrices
gridpattern::pattern_weave("twill_herringbone", nrow=14L, ncol = 50L) |>
as_bm_bitmap() |>
print(compress = "vertical")
█▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█
█▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█
█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█
▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀
██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀
██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ █
█ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██
# Also supports {mazing} mazes
set.seed(42)
m <- mazing::maze(16L, 32L)
m |> as_bm_bitmap(walls = TRUE) |>
print(compress = "vertical")
█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█▀▀▀█▀▀▀▀▀█▀▀▀▀▀▀▀▀▀▀▀█▀▀▀▀▀█▀▀▀▀▀▀▀█▀▀▀▀▀▀▀█▀▀▀█
█ █▀▀▀▀▀▀▀▀▀█ ▀▀▀ █ ▀ █ █ █ █ ▀▀█▀▀▀▀ ▀ █▀▀ █ █▀▀ █ ▀ █▀▀▀█ █ █ █
█ █ ▀▀▀▀█▀▀ ▀▀▀▀█▀█▀▀▀▀ █ █ █▀▀ █▀▀▀█▀█▀▀ █▀▀▀▀ █▀▀▀▀▀█ ▀▀▀ █ █ █
█ █▀▀ █▀▀ █▀▀▀▀ █ █ ▀▀█▀█ ▀▀█ █▀▀ █ █ ▀ ▀▀▀ █▀▀▀▀▀▀▀▀ █ ▀▀█▀▀▀▀ █
█ ▀▀▀▀█ █▀█ █▀▀▀▀ █▀▀ █ █▀▀ █ █ █▀█ ▀▀█▀▀▀▀▀█ █▀█ ▀▀▀▀▀▀▀ █ █ ▀▀█
█▀▀▀▀ █ █ ▀ █ █▀█ █ █▀▀ █ █▀▀ █ ▀ ▀▀█ █ █ ▀▀█ █ ▀▀▀▀▀▀█▀▀▀▀ ▀▀█ █
█ █▀▀▀▀ █ ▀▀█ █ ▀ █ █▀▀ █ █ █ ▀▀▀ █▀▀ █ █▀▀ █ ▀ █▀▀▀█ █▀▀▀▀▀▀▀█ █
█ ▀ █▀█▀▀▀▀ █ ▀▀▀▀█ █ █ █ ▀▀▀▀█ ▀▀█ ▀▀▀▀█ ▀▀▀▀▀▀▀ █ █ ▀ █▀▀▀█ ▀ █
█▀▀▀▀ █ █▀▀▀▀ ▀▀█ █ █ ▀▀▀▀▀▀█ █ █▀▀▀█▀▀ █ █▀▀▀▀ █▀▀▀█▀▀▀█ █ ▀▀█ █
█ ▀▀█ ▀ █ ▀▀█▀▀▀▀ █ ▀▀█ █ ▀▀▀ █ █ █ █ ▀▀█ █ █ █▀▀ █ ▀ █ ▀ ▀▀█ █ █
█▀▀ ▀▀▀▀▀▀█▀▀ █▀▀ █▀▀ █ █▀▀▀█ ▀▀▀ █ ▀▀▀ █▀▀ █▀▀ █▀▀▀█▀▀▀▀▀▀▀▀ █ █
█ █▀▀▀▀▀█ ▀ █▀▀ ▀▀█ ▀▀▀▀▀ █ █▀█▀▀▀▀▀▀▀▀▀▀ ▀▀█ █▀▀ █▀▀ █▀▀▀█ █▀▀ █
█ █ ▀▀█ █▀▀▀▀▀▀▀█ █▀▀▀▀▀█▀█ █ ▀ █▀▀▀█▀▀▀▀▀█ ▀ █▀▀ █ █▀▀ █ ▀▀█ █▀█
█ █▀█ █ ▀ █▀▀▀█ █ ▀▀█ █ ▀ █ █ ▀▀█ ▀▀▀ █ ▀▀▀▀▀▀▀ █ █ ▀ █▀▀▀█ █ █ █
█ █ █ █▀▀▀▀ █ █ ▀▀█ ▀ █ █▀▀ █▀█ █▀▀▀█ █▀▀ █▀▀▀█▀▀ █▀▀▀▀▀▀ █ ▀ █ █
█ ▀ █ ▀▀▀▀█ ▀▀▀▀▀ ▀▀▀▀▀▀▀ █▀▀ ▀ ▀ █ ▀▀▀ █▀▀ ▀▀▀ ▀▀▀▀▀▀▀ █ ▀▀▀▀▀ █
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
[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}
:
{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")
██▀▀▀█▄ ▄█▀▀▀▀▀ ▀▀▀██▀▀▀▄█▀▀▀█▄ ▀▀▀██▀▀▀▄█▀▀▀▀▀
██ ██ ██ ██ ██ ██ ██ ██
██▀▀▀█▄ ▀▀▀▀█▄ ██ ██▀▀▀██ ██ ▀▀▀▀█▄
██ ██ ██ ██ ██ ██ ██ ██
██ ██ ▄▄▄▄▄█▀ ██ ██ ██ ██ ▄▄▄▄▄█▀
█▀▄ ▄▀▀ ▀█▀ ▄▀▄ ▀█▀ ▄▀▀
█▀▄ ▀▄ █ █▀█ █ ▀▄
▀ ▀ ▀▀ ▀ ▀ ▀ ▀ ▀▀
▄▄▄ ▄▄ ▄▄▄ ▄▄ ▄▄▄ ▄▄
█ █ ▀▄ ▀ █ █ █ █ ▀▄ ▀
█▀▀▄ ▄ ▀▄ █ █▀▀█ █ ▄ ▀▄
▀ ▀ ▀▀ ▀ ▀ ▀ ▀ ▀▀
█▀▀▀▄ ▄▀▀▀▄ ▀▀█▀▀ ▄▀▄ ▀▀█▀▀ ▄▀▀▀▄
█ █ █ █ █ █ █ █
█▀█▀ ▀▀▀▄ █ █▄▄▄█ █ ▀▀▀▄
█ ▀▄ ▄ █ █ █ █ █ ▄ █
▀ ▀ ▀▀▀ ▀ ▀ ▀ ▀ ▀▀▀
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.
user system elapsed
120.224 0.179 120.419
[1] "123,234"
[1] "196.5 Mb"
# Faster to load from a cache
saveRDS(font, "unifont.rds")
system.time(font <- readRDS("unifont.rds"))
user system elapsed
0.740 0.000 0.739
# Or just load the subset of GNU Unifont you need
s <- "R很棒!"
system.time(font_s <- unifont(ucp = str2ucp(s)))
user system elapsed
0.719 0.004 0.724
█ ▄▄▄▄▄▄▄ █ █
▄▄▄▄▄▄▄ ▄▀ █ █ █ ▀▀▀▀█▀▀▀▀ ▄█▄
█ ▀▄ ▀ █ █▀▀▀▀▀█ ▀▀▀█▀▀ ▀▀█▀▀▀▀ ███
█ ▄▀ ▄█ █▄▄▄▄▄█ ██▄ ▀▀█▀▀▀█▀▀ ▀█▀
█▀▀▀█▀ ▄▀ █ █ █ ▄▀ █ █ ▀▄▀ █ ▀▄ █
█ ▀▄ █ █ █▀ ▀ █ ▀▀█▀▀
▄█▄ ▄█▄ █ █ ▄ ▀▄ █ ▀▀▀▀█▀▀▀▀ █
█ █▀ ▀▀ █ █
▄▄ ▄▄ ▄▄▄ ▄▄
▄▀ ▀▄▄▄▄▄▀ ▀▄ ▄█▀ ▄█▀██▀█▄
█ ▀ ▀ █ ▄████ ▄▀█ ▄▄ ▄▄ █▀▄
▄█ ▀ ▀ █▄ ▄▄██▄█████ ▀▄█ ▀▀ ▀▀ █▄▀
▄█▀ ▄ ▀█▄ ▄█▄███████████ ▄▀ ▀▄
▀▄ ▀▀▀ ▄▀ ▀▀▀▀▀███▀▀█████ █ ▀▄▄▄▄▀ █
▀▀▄▄▄▀▀ ▄███ ████▀ ▀▀▄▄▄▄▀▀
▀▀▀ ▀▀▀
# Klingon
as_bm_list("", font = font) |>
bm_pad(type = "trim", left = 1L, right = 1L) |>
bm_call(cbind) |>
bm_compress("v")
▄█▄ ▄▄██▀▀ ▀▀████████ ▄▀ ▄█▄ ▄█▀ ▀█▄ ▄▄
▄▄██████▀ ▀██ ▀ ▄█▀ ███▀▀ ███ ██ ▀████████
▀██ ██ ▄███ ▄█ ▄██ ██▀ ▀██▄▄█▀ ██▀ ▀██
▀ █▄ ███ ███▄▄▄▄▄██ ▄███ ▀███▀ ▄█▀ █▀
█▄ ▀█▄ ██▀▀▀▀▀▀███ ▄██████▄ ▀█▄ ▄█▀ █▀
▀▄ ▀▀▄ ▄▀ ▀█▄ ▀▀▄ ▀▀▄ ▄▀ ▀