The magick package: Advanced Image-Processing in R

The magick package provide a modern and simple toolkit for image processing in R. It wraps the ImageMagick STL which is the most comprehensive open-source image processing library available today.

The ImageMagick library has an overwhelming amount of functionality. Magick exposes a decent subset of it, but it is impossible to document everything in detail. This article introduces some basic concepts and examples to get started.

Installing magick

On Windows or macOS the package is most easily installed via CRAN.

install.packages("magick")

The binary CRAN packages work out of the box and have most important features enabled. Use magick_config to see which features and formats are supported by your version of ImageMagick.

library(magick)
## Linking to ImageMagick 6.9.12.98
## Enabled features: fontconfig, freetype, fftw, heic, lcms, pango, raw, webp, x11
## Disabled features: cairo, ghostscript, rsvg
## Using 4 threads
str(magick::magick_config())
## List of 24
##  $ version           :Class 'numeric_version'  hidden list of 1
##   ..$ : int [1:4] 6 9 12 98
##  $ modules           : logi TRUE
##  $ cairo             : logi FALSE
##  $ fontconfig        : logi TRUE
##  $ freetype          : logi TRUE
##  $ fftw              : logi TRUE
##  $ ghostscript       : logi FALSE
##  $ heic              : logi TRUE
##  $ jpeg              : logi TRUE
##  $ lcms              : logi TRUE
##  $ libopenjp2        : logi TRUE
##  $ lzma              : logi TRUE
##  $ pangocairo        : logi TRUE
##  $ pango             : logi TRUE
##  $ png               : logi TRUE
##  $ raw               : logi TRUE
##  $ rsvg              : logi FALSE
##  $ tiff              : logi TRUE
##  $ webp              : logi TRUE
##  $ wmf               : logi TRUE
##  $ x11               : logi TRUE
##  $ xml               : logi TRUE
##  $ zero-configuration: logi FALSE
##  $ threads           : int 4

Build from source

On Linux you need to install the ImageMagick++ library: on Debian/Ubuntu this is called libmagick++-dev:

sudo apt-get install libmagick++-dev

On Fedora or CentOS/RHEL we need ImageMagick-c++-devel:

sudo yum install ImageMagick-c++-devel

To install from source on macOS you need either imagemagick@6 or imagemagick from homebrew.

brew install imagemagick@6

Unfortunately the current imagemagick@6 configuration on homebrew disables a bunch of features, including librsvg and fontconfig. Therefore the quality of fonts and svg rendering might be suboptimal. The is not a problem for the CRAN binary package.

Image IO

What makes magick so magical is that it automatically converts and renders all common image formats. ImageMagick supports dozens of formats and automatically detects the type. Use magick::magick_config() to list the formats that your version of ImageMagick supports.

Read and write

Images can be read directly from a file path, URL, or raw vector with image data with image_read. The image_info function shows some meta data about the image, similar to the imagemagick identify command line utility.

library(magick)
tiger <- image_read_svg('http://jeroen.github.io/images/tiger.svg', width = 350)
print(tiger)
##   format width height colorspace matte filesize density
## 1    PNG   350    350       sRGB  TRUE        0   72x72

We use image_write to export an image in any format to a file on disk, or in memory if path = NULL.

# Render svg to png bitmap
image_write(tiger, path = "tiger.png", format = "png")

If path is a filename, image_write returns path on success such that the result can be piped into function taking a file path.

Converting formats

Magick keeps the image in memory in its original format. Specify the format parameter image_write to convert to another format. You can also internally convert the image to another format earlier, before applying transformations. This can be useful if your original format is lossy.

tiger_png <- image_convert(tiger, "png")
image_info(tiger_png)
##   format width height colorspace matte filesize density
## 1    PNG   350    350       sRGB  TRUE        0   72x72

Note that size is currently 0 because ImageMagick is lazy (in the good sense) and does not render until it has to.

Preview

IDE’s with a built-in web browser (such as RStudio) automatically display magick images in the viewer. This results in a neat interactive image editing environment.

rstudio screenshot

Alternatively, on Linux you can use image_display to preview the image in an X11 window. Finally image_browse opens the image in your system’s default application for a given type.

# X11 only
image_display(tiger)

# System dependent
image_browse(tiger)

Another method is converting the image to a raster object and plot it on R’s graphics display. However this is very slow and only useful in combination with other plotting functionality. See #raster below.

Transformations

The best way to get a sense of available transformations is walk through the examples in the ?transformations help page in RStudio. Below a few examples to get a sense of what is possible.

Cut and edit

Several of the transformation functions take an geometry parameter which requires a special syntax of the form AxB+C+D where each element is optional. Some examples:

  • image_crop(image, "100x150+50"): crop out width:100px and height:150px starting +50px from the left
  • image_scale(image, "200"): resize proportionally to width: 200px
  • image_scale(image, "x200"): resize proportionally to height: 200px
  • image_fill(image, "blue", "+100+200"): flood fill with blue starting at the point at x:100, y:200
  • image_border(frink, "red", "20x10"): adds a border of 20px left+right and 10px top+bottom

The full syntax is specified in the Magick::Geometry documentation.

# Example image
frink <- image_read("https://jeroen.github.io/images/frink.png")
print(frink)
##   format width height colorspace matte filesize density
## 1    PNG   220    445       sRGB  TRUE    73494   72x72

# Add 20px left/right and 10px top/bottom
image_border(image_background(frink, "hotpink"), "#000080", "20x10")

# Trim margins
image_trim(frink)

# Passport pica
image_crop(frink, "100x150+50")

# Resize
image_scale(frink, "300") # width: 300px

image_scale(frink, "x300") # height: 300px

# Rotate or mirror
image_rotate(frink, 45)

image_flip(frink)

image_flop(frink)

# Brightness, Saturation, Hue
image_modulate(frink, brightness = 80, saturation = 120, hue = 90)

# Paint the shirt orange
image_fill(frink, "orange", point = "+100+200", fuzz = 20)