Invisible link to canonical for Microformats

Optimize your images with R and reSmush.it

Introducing the resmush package


The resmush package has recently been accepted on CRAN! This small utility package allows for the optimization (i.e., compression) of local and online images using reSmush.it.

You can install resmush from CRAN with:

install.packages("resmush")

What is reSmush.it?

reSmush.it is a free online API that provides image optimization and has been implemented on WordPress, Drupal, or Magento. Some features of reSmush.it include:

  • Free optimization services, no API key required.
  • Optimization of local and online images.
  • Supported image file formats: PNG, JPG/JPEG, GIF, BMP, TIFF, WebP.
  • Maximum image size: 5 MB.
  • Compression using several algorithms:
    • PNGQuant: Strip unneeded chunks from PNGs while preserving full alpha transparency.
    • JPEGOptim: Lossless optimization based on optimizing the Huffman tables.
    • OptiPNG: png reducer used by several online optimizers.

reSmush.it is free of charge, but its team is planning to offer more serves as well as extend the service to support other types of image files. If you enjoy this API (as I do), you can consider supporting them.

Why the resmush package?

One of the main reasons I developed resmush is because I usually include precomputed vignettes with my packages (see tidyterra as an example). I found that the plots created on CRAN with the standard configuration (i.e., not precomputed vignettes but built on CRAN itself) were not very satisfying. In some of the packages I developed, especially those related to mapping, they didn’t do justice to the actual results when a user runs them.

Precomputing vignettes has the drawback of producing higher-quality images at the expense of size. To avoid exceeding CRAN’s 5Mb maximum size policy, I developed resmush, which enables me to reduce the size of the images without a significant loss in quality.

Another use case for resmush is optimizing images in the context of web page development and SEO optimization. For example, I optimized all the images on this blog using resmush_dir(), which is a shorthand for optimizing all files in a specific folder.

There are other alternatives that I would discuss at the end of this post, but in one line, the reSmush.it API performs fast with minimal configuration for a wide range of formats without needing an API key.

Using the resmush package

With local files

Let’s present an example of how a local file can be optimized. First we create a large plot with ggplot2

library(tidyterra)
library(ggplot2)
library(terra)
library(maptiles)

cyl <- vect(system.file("extdata/cyl.gpkg", package = "tidyterra")) %>%
  project("EPSG:3857")
cyl_img <- get_tiles(cyl, "Esri.WorldImagery", zoom = 8, crop = TRUE)
cyl_gg <- autoplot(cyl_img, maxcell = Inf) +
  geom_spatvector(data = cyl, alpha = 0.3)

cyl_gg
Original file

Original file


# And we save it for resmushing
ggsave("cyl.png", width = 5, height = 0.7 * 5)

Cool, but the file has a size of 1.7 Mb. So we can use resmush_file() to reduce it, see:

library(resmush)
resmush_file("cyl.png")
#> ══ resmush summary ══════════════════════════════════════════
#> ℹ Input: 1 file with size 1.7 Mb
#> ✔ Success for 1 file: Size now is 762.2 Kb (was 1.7 Mb). Saved 948.9 Kb (55.46%).
#> See result in directory '.'.

# Check
png::readPNG("cyl_resmush.png") %>%
  grid::grid.raster()
Optimized file

Optimized file

By default, resmush_file() and resmush_dir() do not overwrite the original file, although this behavior may be modified with the overwrite = TRUE parameter. Now, the resmushed file ("cyl_resmush.png") has a size of 762.2 Kb.

Let’s compare the results side-by-side:

Original online figure Optimized figure

Original picture (left/top) 1.7 Mb and optimized picture (right/bottom) 762.2 Kb (Compression 55.46%). Click in the images to enlarge.

We can verify that the image has been compressed without reducing its dimensions.

size_src <- file.size("cyl.png") %>%
  `class<-`("object_size") %>%
  format(units = "auto")
size_dest <- file.size("cyl_resmush.png") %>%
  `class<-`("object_size") %>%
  format(units = "auto")

dim_src <- dim(png::readPNG("cyl.png"))[1:2] %>% paste0(collapse = "x")
dim_dest <- dim(png::readPNG("cyl_resmush.png"))[1:2] %>% paste0(collapse = "x")

data.frame(
  source = c("original file", "compressed file"),
  size = c(size_src, size_dest),
  dimensions = c(dim_src, dim_dest)
) %>%
  knitr::kable()
source size dimensions
original file 1.7 Mb 1050x1500
compressed file 762.2 Kb 1050x1500

With online files

We can also optimize online files with resmush_url() and download them to disk. In this example, I demonstrate a feature of all the functions in resmush: they return an invisible data frame with a summary of the process.

url <- "https://dieghernan.github.io/assets/img/samples/sample_1.3mb.jpg"

# Invisible data frame
dm <- resmush_url(url, "sample_optimized.jpg", report = FALSE)
knitr::kable(dm)
src_img dest_img src_size dest_size compress_ratio notes src_bytes dest_bytes
https://dieghernan.github.io/assets/img/samples/sample_1.3mb.jpg sample_optimized.jpg 1.3 Mb 985 Kb 26.63% OK 1374693 1008593
Original online figure Optimized online figure

Original picture (left/top) 1.3 Mb and optimized picture (right/bottom) 985 Kb (Compression 26.63%). Click in the images to enlarge.

Other alternatives

There are other alternatives for optimizing images with R, but first…

Yihui Xie, one of the most prominent figures in the R community, was recently laid off from his position at Posit PBC (formerly RStudio) (more info here).

Yihui is the developer of knitr, markdown, blogdown, and bookdown, among others, and he has been one of the key contributors (if not the most) to the reproducible research space with R through his libraries.

If you have ever used and enjoyed his packages, consider sponsoring him on GitHub.

  • One of the many packages developed by Yihui is xfun, which includes the following functions for optimizing image files:
    • xfun::tinify() is similar to resmush_file() but uses TinyPNG. An API key is required.
    • xfun::optipng() compresses local files with OptiPNG (which needs to be installed locally).
  • tinieR package by jmablog. An R package that provides a full interface with TinyPNG.
  • optout package by @coolbutuseless. Similar to xfun::optipng() with additional options. Requires additional software to be installed locally.
Table 1: R packages: Comparison of alternatives for optimizing images.
tool CRAN Additional software? Online? API Key? Limits?
xfun::tinify() Yes No Yes Yes 500 files/month (Free tier)
xfun::optipng() Yes Yes No No No
tinieR No No Yes Yes 500 files/month (Free tier)
optout No Yes No No No
resmush Yes No Yes No Max size 5Mb
Table 2: R packages: Formats admitted.
tool png jpg gif bmp tiff webp pdf
xfun::tinify()
xfun::optipng()
tinieR
optout
resmush

Additionally, if you host your projects on GitHub, you can try Imgbot, which is free for open-source projects. Imgbot provides automatic optimization for files in your repositories, and the optimized files will be included in specific pull requests before merging into your work.


Related