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(ggplot2)
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) +
  opts(panel.grid.major=theme_blank(),
       panel.grid.minor=theme_blank(),
       panel.border=theme_rect(colour="grey80", size=5),
       axis.text.x=theme_blank(),
       axis.text.y=theme_blank(),
       axis.title.x=theme_blank(),
       axis.title.y=theme_blank(),
       legend.position="none")

 
Simply read jpeg image and draw as a grid object:

img.path <- "http://www.r-project.org/Rlogo.jpg" # from CRAN
img <- readImage(img.path) # needs library(EBImage)
grid.newpage()
gob <- ebimageGrob(img, raster=TRUE) # needs library(gridExtra)
grid.draw(gob) 

 
Then, use the gob grob object for ggplot2 background

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

# 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")
    return(r)
  })

# 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")
    return(r)
  })

 
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")
  }
  structure(function(...)rasterob, call=match.call())
}

# 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)
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)
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)")

11 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 ????

    Dams

  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…

  4. First of all, thanks to your efforts here, it really helped me.
    Unfortunately, I still have a problem:
    When using the following code:

    library(png)
    back_map <- readPNG("back_map.png")
    grid.newpage()
    gob plot_combined + theme(panel.background=function(…)pngob)
    Error in (function (el, elname) :
    Element panel.background must be a element_rect object.

    I had to use png because EBImage wasn’t available…

  5. Pingback: ggplot2 - La inserción de una imagen a ggplot2

  6. Pingback: ggplot2 - Inserimento di un'immagine ggplot2

  7. Pingback: Inserting an image to ggplot2 - PhotoLens

  8. Pingback: Insertar una imagen en ggplot2 - Fallosweb.com

Leave a comment