Home > Blockchain >  Crop image from cowplot lines as mask
Crop image from cowplot lines as mask

Time:10-15

I would like to clip an image by an irregular mask, but do not know which libraries to use or if is possible using magick with cowplot.

Let's say I have an image downloaded into R via the magick library:

library(magick)
#> Linking to ImageMagick 6.9.12.3
#> Enabled features: cairo, fontconfig, freetype, heic, lcms, pango, raw, rsvg, webp
#> Disabled features: fftw, ghostscript, x11
library(cowplot)

tdir=tempdir()
url = "https://upload.wikimedia.org/wikipedia/commons/b/b3/USA-NYC-Empire_State1.JPG"
download.file(url,destfile = file.path(tdir,"/ESB.jpg"))
#if(file.exists(paste(tdir,"/ESB.jpg",sep=""))==FALSE){
#  download.file(url, destfile = file.path(tdir,"ESB.jpg"))}

ESB = image_read(path = paste(tdir,"/ESB.jpg",sep=""))
ESB2 = image_resize(ESB, "500x500")

I can use ggdraw() from the cowplot package to draw_lines on top of this image, like so:

ggdraw() 
  draw_image(ESB2) 
  draw_line(x=c(.5,.285),y=c(.9,.1),col='red') 
  draw_line(x=c(.5,.715),y=c(.9,.1),col='red') 
  draw_line(x=c(.715,.285),y=c(.1,.1),col='red')

But there is no way to clip the image area outside of these lines. I have seen other Stack Exchange posts that clip on simpler polygons, like circles. Is there a way to clip an image in such a way? I am open to other libraries to solve the problem.

CodePudding user response:

As of R 4.1, we can define clipping masks in grid graphics. Convert your magick image to a rasterGrob and draw it in a viewport that has a mask made from your triangle co-ordinates. The following is a full reprex:

library(magick)
#> Linking to ImageMagick 6.9.12.3
#> Enabled features: cairo, freetype, fftw, ghostscript, heic, lcms, pango, raw, rsvg, webp
#> Disabled features: fontconfig, x11
library(grid)

url <- paste0("https://upload.wikimedia.org/wikipedia/commons/",
              "b/b3/USA-NYC-Empire_State1.JPG")

ESB <- image_read(url)
ESB2 <- image_resize(ESB, "500x500")
ESB_grob <- rasterGrob(ESB2)

mask <- as.mask(polygonGrob(x = c(0.285, 0.5, 0.715, 0.285),
                            y = c(0.1, 0.9, 0.1, 0.1)))

grid.newpage()
pushViewport(viewport(mask = mask))
grid.draw(ESB_grob)

enter image description here

Created on 2022-10-13 with reprex v2.0.2

  • Related