rgraphicsrotationimagemagick

Rotate an image with transparent background


I have trouble rotating images with transparent background while retaining a transparent background. magick::image_rotate() adds a white background with a gray border (I think due to anti-aliasing).

How do I rotate an image in R while retaining a transparent background?

I want to use the rotated image in annotation_custom() to overlay on an existing ggplot.

Here is a reproducible example with my tries so far, that demonstrates my problems:

library("magick")

## read R-logo
rlogo <- image_read("https://www.r-project.org/logo/Rlogo.png")
plot(as.raster(rlogo))

## transparent background
rlogo <- image_transparent(rlogo, color = "white")
plot(as.raster(rlogo))

## rotate
rlogo <- image_rotate(rlogo, degrees = 45)
plot(as.raster(rlogo))

## black canvas
canvas <- image_blank(
    width  = image_info(rlogo)$width,
    height = image_info(rlogo)$height,
    color  = "black")
plot(as.raster(canvas))

## 1st try: rotated R logo on black canvas
rlogo_blackbg <- image_composite(canvas, rlogo, operator = "over")
plot(as.raster(rlogo_blackbg))
## -> image_rotate added white background
##    (white corners!)

## try to fix: transparent background again
rlogo <- image_transparent(rlogo, color = "white")
plot(as.raster(rlogo))

## 2nd try: rotated R logo on black canvas
rlogo_blackbg <- image_composite(canvas, rlogo, operator = "over")
plot(as.raster(rlogo_blackbg))
## -> the anti-aliasing during image_rotate created border
##    (frame around the rotated image)


Solution

  • Make the background transparent using magick::image_background():

    library("magick")
    #> Linking to ImageMagick 6.9.12.98
    #> Enabled features: cairo, freetype, fftw, 
    #> ghostscript, heic, lcms, pango, raw, rsvg, webp
    #> Disabled features: fontconfig, x11
    
    rlogo <- image_read("https://www.r-project.org/logo/Rlogo.png")
    
    rlogo_rt <- rlogo |>
      image_background("transparent") |>
      image_rotate(degrees = 45) 
    
    canvas <- image_blank(
      width  = image_info(rlogo_rt)$width,
      height = image_info(rlogo_rt)$height,
      color  = "black")
    
    rlogo_blackbg <- image_composite(canvas, rlogo_rt, operator = "over")
    
    plot(as.raster(rlogo_blackbg))
    

    Created on 2025-08-17 with reprex v2.1.1