Use image for background in ggplot2

ggplot2 does not support drawing image files by default, but it is easy to draw images for background using ggplot2.

Here is a tutorial.
First of all, you need to load EBImage package from bioconductor and gridExtra package.
If they are not available, see below for workaround.

library(EBImage) # from bioconductor for readImage 
library(gridExtra) # for ebimageGrob

# basic layer and options
p <- qplot(1:10, 1:10, size=15, colour=1:10) +
       panel.border=theme_rect(colour="grey80", size=5),

Simply read jpeg image and draw as a grid object:

img.path <- "" # from CRAN
img <- readImage(img.path) # needs library(EBImage)
gob <- ebimageGrob(img, raster=TRUE) # needs library(gridExtra)

Then, use the gob grob object for ggplot2 background

# background image in ggplot preserving original size
p + opts(title="oritinal size ") +

# automatic scaling preserving aspect ratio
p + opts(title="automatic scale") +
  opts(panel.background=function(...) {
    r<-getGrob(gob, gPath("rastergrob"),grep=T)
    r$vp$width <- unit(1, "npc")
    r$vp$height <- unit(1, "npc")

# automatic fit to the plot region
p + opts(title="automatic fit") +
  opts(panel.background=function(...) {
    r<-getGrob(gob, gPath("rastergrob"),grep=T)
    r$vp <- NULL
    r$width <- unit(1, "npc")
    r$height <- unit(1, "npc")

Here is a simple wrapper function and its usage:

# wrapper for reading and drawing image.
# @param scale: scale to plot region preserving aspect ratio. ignored if fit==TRUE
# @param fit: fit to plot region destroying aspect ratio
theme_image <- function(path, scale = FALSE, fit = FALSE){
  img <- readImage(path)
  ebimageob <- ebimageGrob(img, raster=TRUE)
  rasterob <- getGrob(ebimageob, gPath("rastergrob"),grep=T)
  if (fit) {
    rasterob$width <- unit(1, "npc")
    rasterob$height <- unit(1, "npc")
    rasterob$vp <- NULL
  }else if (scale) {
    rasterob$vp$width <- unit(1, "npc")
    rasterob$vp$height <- unit(1, "npc")

# very easy to use
p + opts(panel.background=theme_image(img.path), title="jpeg version - unscaled")
p + opts(panel.background=theme_image(img.path, scale = TRUE), title="jpeg version - auto scaled")
p + opts(panel.background=theme_image(img.path, fit = TRUE), title="jpeg version - auto fit")

EBImage supports other file formats:

img.path.png <- system.file("images", "lena-color.png", package="EBImage")
p + opts(panel.background=theme_image(img.path.png, scale = TRUE), title="png version")

# gif file
img.path.gif <- system.file("images", "lena.gif", package="EBImage")
p + opts(panel.background=theme_image(img.path.gif, fit = TRUE), title="gif version")

* these images are from EBImage package.

If EBImage is not available, other packages can do workaround, for example:

# png version using library(png)
img <- readPNG(system.file("img", "Rlogo.png", package="png"))
pngob <- rasterGrob(img)
p + opts(panel.background=function(...)pngob, title="library(png)")

# jpeg version using library(ReadImages)
img <- read.jpeg((paste(R.home(),"/doc/html/logo.jpg", sep=""))) # cannot use url as a file path
jpegob <- rasterGrob(unclass(img))
p + opts(panel.background=function(...)jpegob, title="library(ReadImages)")

6 thoughts on “Use image for background in ggplot2

  1. Hi,

    As an alternative to opts(panel.background) the ggExtra package provides a geom to wrap ebimageGrob or pixmapGrob as ggplot2 layers.

  2. Hello!! I’m french and i would like to know who create the image “read Image”? it’s very cool! Is it you kohske ????


  3. Hi Kohske, thanks for your post, I was wondering how this piece of code should change to make it work with new versions of ggplot2. I tried your example with R version 2.15.1 (2012-06-22) and ggplot2_0.9.2.99 but I’m getting the following error and warning:

    Error in function (el, elname) :
    Element panel.background must be a element_rect object.
    In addition: Warning message:
    ‘opts’ is deprecated.
    Use ‘theme’ instead.
    See help(“Deprecated”)

    Thanks for your help

    • Hi julovi

      The internal structure of ggplot2 is changing largely, so these codes will not work with the latest version of ggplot2. I may rewrite these topics with the latest version of ggplot2, but definitely I don’t have enough time to do that now…

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s