--- title: "Introduction to bittermelon" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to bittermelon} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ### Table of Contents * [Overview](#overview) * [Examples](#examples) - [Bitmap font glyphs](#ex-glyphs) - [{gridpattern} matrices](#ex-gridpattern) - [{mazing} mazes](#ex-mazes) - [Sprites](#ex-sprites) * [Builtin Fonts](#fonts) * [GNU Unifont via {hexfont}](#hexfont) ## Overview * `{bittermelon}` provides functions for creating and modifying bitmaps. * It can print bitmaps to the R terminal. * It features [over a dozen functions](https://trevorldavis.com/R/bittermelon/dev/reference/index.html#modify-bitmaps-and-pixmaps) 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](https://github.com/robhagemans/monobit) is also installed then it can read/write [several more bitmap font formats](https://github.com/robhagemans/monobit?tab=readme-ov-file#supported-bitmap-formats). * 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. ## Examples ```{r hidden, echo = FALSE} knitr::opts_chunk$set(fig.cap = '', comment = '', class.output = "bitmap") ``` ```{css, echo=FALSE} pre,code { font-family: Dejavu Sans Mono,FreeMono,monospace; line-height: 1.0; font-size: 100%; } ``` ### Bitmap font glyphs ```{r print} 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}`: ```{r print_color, eval=FALSE} if (cli::num_ansi_colors() >= 16L) print(bm, px = " ", bg = c(cli::bg_br_white, cli::bg_blue, cli::bg_cyan, cli::bg_red)) ``` ```{r plot, fig.width = 6, fig.height = 2, fig.alt = "Stylized bitmap image that says 'RSTATS`."} plot(bm, col = c("white", "blue3", "cyan3", "red3")) ``` ### {gridpattern} matrices ```{r gridpattern, eval=requireNamespace("gridpattern")} # Also supports {gridpattern} matrices gridpattern::pattern_weave("twill_herringbone", nrow=14L, ncol = 50L) |> as_bm_bitmap() |> print(compress = "vertical") ``` ```{r plot_gridpattern, fig.width = 6, fig.height = 1.5, fig.alt = "Rainbow squares", eval=requireNamespace("gridpattern")} gridpattern::pattern_square(subtype=8L, nrow=8L, ncol = 50L) |> as_bm_pixmap(s, col = grDevices::rainbow(8L)) |> plot() ``` ### {mazing} mazes ```{r maze, eval=requireNamespace("mazing")} # Also supports {mazing} mazes set.seed(42) m <- mazing::maze(16L, 32L) m |> as_bm_bitmap(walls = TRUE) |> print(compress = "vertical") ``` ```{r plot_maze, fig.width = 6, fig.height = 3, fig.alt = "A maze", eval=requireNamespace("mazing")} # 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() ``` ### Sprites ```{r farming_crops} # Contains some built-in farming crops sprites crops <- farming_crops_16x16() names(crops) 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}`: ```{r print_crops, eval=FALSE} if (cli::is_utf8_output() && cli::num_ansi_colors() >= 256L) print(pm, compress = "v", bg = "white") ``` ```{r plot_sprites, fig.width = 6, fig.height = 1.5, fig.alt = "Sprites of some food crops"} plot(pm) ``` ## Builtin Fonts `{bittermelon}` has a builtin versions of the 8x16 [Spleen](https://github.com/fcambus/spleen) font as well as 4x6 and 6x13 [Fixed](https://www.cl.cam.ac.uk/~mgk25/ucs-fonts.html) fonts. ```{r builtin} 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") ``` ## GNU Unifont via {hexfont} The [{hexfont}](https://github.com/trevorld/hexfont) package includes a helper function `unifont()` which loads several GNU Unifont hex fonts as a single `{bittermelon}` `bm_font()` object. [GNU Unifont](https://unifoundry.com/unifont/index.html) 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](https://www.kreativekorp.com/ucsur/). ```{r unifont, eval=requireNamespace("hexfont")} library("hexfont") system.time(font <- unifont()) # Unifont is a **big** font length(font) |> prettyNum(big.mark = ",") # number of glyphs object.size(font) |> format(units = "MB") # memory used # Faster to load from a cache saveRDS(font, "unifont.rds") system.time(font <- readRDS("unifont.rds")) # Or just load the subset of GNU Unifont you need s <- "R很棒!" system.time(font_s <- unifont(ucp = str2ucp(s))) # 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") ``` ```{r hidden2, echo = FALSE} unlink("unifont.rds") ```