I decided to send personalised Easter cards this year. The plan was to dig out photos of friend and make them more eastery. I found a lovely frame to add to the photos only to realise that I had no idea how to combine them. A quick internet search left me annoyed, so I decided to do what I always do. I turned to R!

Getting to work

I used the magick package. Reading in images is easy, and if you want to look at them just print them in the console. I am using a photo of my dog for this blog post and the frame I used is from It says that is fine to use for personal use but make sure to check the copyright of whatever image you use.

frame <- image_read(here::here('photo_frame.png'))
background <- image_read(here::here('IMG_8386.png'))

Here are the images!

I want to add the frame to the photo of dog. To add the frame right in the middle I change the gravity option of the image_composite() function to ‘center’.

card <- image_composite(background, frame, gravity='center')

The problem is that the two images are not the same size.


I need to crop it. I use image_info() to get the dimensions of the two images. Since the frame is added in the centre of the background photo, I need to remove half of the difference between the background and the frame for both width and height.

frame_dim <- image_info(frame)
background_dim <- image_info(background)
diff_width <- (background_dim$width-frame_dim$width)/2
diff_height <- (background_dim$height-frame_dim$height)/2
card_cropped <- image_crop(card, paste0(frame_dim$width, 'x', frame_dim$height, '+', diff_width, '+',  diff_height))

Look how great it looks! To save the image you use image_write(). I sent paper copies to my friend using an online postcard service but I can guess you can email them to people as well.

image_write(card_cropped, here::here('card.png'))

Packages used

## ── Attaching packages ────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.0     ✓ purrr   0.3.3
## ✓ tibble  3.0.0     ✓ dplyr   0.8.5
## ✓ tidyr   1.0.2     ✓ stringr 1.4.0
## ✓ readr   1.3.1     ✓ forcats 0.5.0
## ── Conflicts ───────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()