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”.bm_bitmap()
and
bm_pixmap()
objects it also supports modifying
{magick}
’s “magick-image” objects and base R’s
“nativeRaster” and “raster” objects.::install_github("trevorld/bittermelon") remotes
read_monobit()
and
write_monobit()
require that monobit is installed
(i.e. pip3 install monobit
).bm_distort()
requires the suggested
package magick.library("bittermelon") # remotes::install_github("trevorld/bittermelon")
<- system.file("fonts/spleen/spleen-8x16.hex.gz", package = "bittermelon")
font_file <- read_hex(font_file)
font <- as_bm_list("RSTATS", font = font)
bml # With vertical compression
<- bml |> bm_call(cbind) |> bm_compress("vertical")
bm print(bm)
██▀▀▀█▄ ▄█▀▀▀▀▀ ▀▀▀██▀▀▀▄█▀▀▀█▄ ▀▀▀██▀▀▀▄█▀▀▀▀▀
██ ██ ██ ██ ██ ██ ██ ██
██▀▀▀█▄ ▀▀▀▀█▄ ██ ██▀▀▀██ ██ ▀▀▀▀█▄
██ ██ ██ ██ ██ ██ ██ ██
██ ██ ▄▄▄▄▄█▀ ██ ██ ██ ██ ▄▄▄▄▄█▀
# Upside down with ASCII characters
<- bml |>
bm bm_flip("both") |>
bm_call(cbind, direction = "RTL")
print(bm, px = px_ascii)
------------------------------------------------
------------------------------------------------
------------------------------------------------
------------------------------------------------
--@@@@@@---@@----@@---@@---@@-----@@@@@@-@@---@@
-@@--------@@----@@---@@---@@----@@------@@---@@
-@@--------@@----@@---@@---@@----@@------@@---@@
-@@--------@@----@@---@@---@@----@@------@@---@@
-@@--------@@----@@---@@---@@----@@------@@---@@
--@@@@@----@@----@@@@@@@---@@-----@@@@@---@@@@@@
------@@---@@----@@---@@---@@---------@@-@@---@@
------@@---@@----@@---@@---@@---------@@-@@---@@
------@@---@@----@@---@@---@@---------@@-@@---@@
-@@@@@@-@@@@@@@@--@@@@@-@@@@@@@@-@@@@@@---@@@@@@
------------------------------------------------
------------------------------------------------
# With a shadow effect and borders
<- bml |>
bm 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"))
# Also supports {gridpattern} matrices
::pattern_weave("twill_herringbone", nrow=14L, ncol = 50L) |>
gridpatternas_bm_bitmap() |>
print(compress = "vertical")
█▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█
█▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█
█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█ █▄ ▀█
▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀▀▄▄▀▄▄▀
██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀
██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ █
█ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██ ▄█▀ ██
::pattern_square(subtype=8L, nrow=8L, ncol = 50L) |>
gridpatternas_bm_pixmap(s, col = grDevices::rainbow(8L)) |>
plot()
# Also supports {mazing} mazes
set.seed(42)
<- mazing::maze(16L, 32L)
m |> as_bm_bitmap(walls = TRUE) |>
m print(compress = "vertical")
█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█▀▀▀█▀▀▀▀▀█▀▀▀▀▀▀▀▀▀▀▀█▀▀▀▀▀█▀▀▀▀▀▀▀█▀▀▀▀▀▀▀█▀▀▀█
█ █▀▀▀▀▀▀▀▀▀█ ▀▀▀ █ ▀ █ █ █ █ ▀▀█▀▀▀▀ ▀ █▀▀ █ █▀▀ █ ▀ █▀▀▀█ █ █ █
█ █ ▀▀▀▀█▀▀ ▀▀▀▀█▀█▀▀▀▀ █ █ █▀▀ █▀▀▀█▀█▀▀ █▀▀▀▀ █▀▀▀▀▀█ ▀▀▀ █ █ █
█ █▀▀ █▀▀ █▀▀▀▀ █ █ ▀▀█▀█ ▀▀█ █▀▀ █ █ ▀ ▀▀▀ █▀▀▀▀▀▀▀▀ █ ▀▀█▀▀▀▀ █
█ ▀▀▀▀█ █▀█ █▀▀▀▀ █▀▀ █ █▀▀ █ █ █▀█ ▀▀█▀▀▀▀▀█ █▀█ ▀▀▀▀▀▀▀ █ █ ▀▀█
█▀▀▀▀ █ █ ▀ █ █▀█ █ █▀▀ █ █▀▀ █ ▀ ▀▀█ █ █ ▀▀█ █ ▀▀▀▀▀▀█▀▀▀▀ ▀▀█ █
█ █▀▀▀▀ █ ▀▀█ █ ▀ █ █▀▀ █ █ █ ▀▀▀ █▀▀ █ █▀▀ █ ▀ █▀▀▀█ █▀▀▀▀▀▀▀█ █
█ ▀ █▀█▀▀▀▀ █ ▀▀▀▀█ █ █ █ ▀▀▀▀█ ▀▀█ ▀▀▀▀█ ▀▀▀▀▀▀▀ █ █ ▀ █▀▀▀█ ▀ █
█▀▀▀▀ █ █▀▀▀▀ ▀▀█ █ █ ▀▀▀▀▀▀█ █ █▀▀▀█▀▀ █ █▀▀▀▀ █▀▀▀█▀▀▀█ █ ▀▀█ █
█ ▀▀█ ▀ █ ▀▀█▀▀▀▀ █ ▀▀█ █ ▀▀▀ █ █ █ █ ▀▀█ █ █ █▀▀ █ ▀ █ ▀ ▀▀█ █ █
█▀▀ ▀▀▀▀▀▀█▀▀ █▀▀ █▀▀ █ █▀▀▀█ ▀▀▀ █ ▀▀▀ █▀▀ █▀▀ █▀▀▀█▀▀▀▀▀▀▀▀ █ █
█ █▀▀▀▀▀█ ▀ █▀▀ ▀▀█ ▀▀▀▀▀ █ █▀█▀▀▀▀▀▀▀▀▀▀ ▀▀█ █▀▀ █▀▀ █▀▀▀█ █▀▀ █
█ █ ▀▀█ █▀▀▀▀▀▀▀█ █▀▀▀▀▀█▀█ █ ▀ █▀▀▀█▀▀▀▀▀█ ▀ █▀▀ █ █▀▀ █ ▀▀█ █▀█
█ █▀█ █ ▀ █▀▀▀█ █ ▀▀█ █ ▀ █ █ ▀▀█ ▀▀▀ █ ▀▀▀▀▀▀▀ █ █ ▀ █▀▀▀█ █ █ █
█ █ █ █▀▀▀▀ █ █ ▀▀█ ▀ █ █▀▀ █▀█ █▀▀▀█ █▀▀ █▀▀▀█▀▀ █▀▀▀▀▀▀ █ ▀ █ █
█ ▀ █ ▀▀▀▀█ ▀▀▀▀▀ ▀▀▀▀▀▀▀ █▀▀ ▀ ▀ █ ▀▀▀ █▀▀ ▀▀▀ ▀▀▀▀▀▀▀ █ ▀▀▀▀▀ █
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
# Can also visualize the maze solutions
<- grDevices::palette.colors()
pal |> as_bm_pixmap(start = "top", end = "bottom",
m col = c(pal[6L], "white", pal[7L], pal[5L])) |>
bm_pad(sides = 1L) |>
plot()
# Contains some built-in farming crops sprites
<- farming_crops_16x16()
crops 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"
<- crops$corn$portrait
corn <- crops$grapes$portrait
grapes <- crops$orange$stage5
orange <- crops$tulip$portrait
tulip <- cbind(corn, grapes, orange, tulip) pm
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)
{bittermelon}
has a builtin versions of the 8x16 Spleen font as well as 4x6
and 6x13 Fixed
fonts.
<- read_hex(system.file("fonts/spleen/spleen-8x16.hex.gz",
spleen_8x16 package = "bittermelon"))
<- read_yaff(system.file("fonts/fixed/4x6.yaff.gz",
fixed_4x6 package = "bittermelon"))
<- read_yaff(system.file("fonts/fixed/5x8.yaff.gz",
fixed_5x8 package = "bittermelon"))
<- read_yaff(system.file("fonts/fixed/6x13.yaff.gz",
fixed_6x13 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
<- "R很棒!"
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).
{bittermelon}
will likely support including a specialized
{ggplot2}
geom.{bittermelon}
to convert
to/from “nativeRaster” objects.{bittermelon}
font objects.{bittermelon}
’s
bm_distort()
method.nr_text_bitmap()
method works with
{bittermelon}
font objects.monobit-convert
which is used by
bittermelon::read_monobit()
and
bittermelon::write_monobit()
.Fixed aka “Unicode fonts and tools for X11”
Embedded in {hexfont}
package:
Embedded in {bdftools}
package: