I'm trying to build a visualisation with both drawn shapes (e.g. using geom\_circle) and images. In both cases, I want to be able to position them on the page specifically with coordinates, rather than using one of the built in chart types.

**See update further down...**

However, I can either get the circles with the correct aspect ratio (i.e. round not oval) or the images, but not both. In the example below, you can see the image is not shown as square when it is.

[![enter image description here](https://i.stack.imgur.com/1VGKN.png)](https://i.stack.imgur.com/1VGKN.png)

I have tried various things including coord\_fixed, scale\_size\_identity and coord\_cartesian, but to no avail. The overall output will be landscape, which is why I have set the cartesian limits as I have.

This is a simplified version. In the full version, I'll get the coordinates from the data (which I'm fine with).

```
images <-data.frame(url = c("https://upload.wikimedia.org/wikipedia/commons/d/de/Windows_live_square.JPG"))

ggplot(mpg) + 
    ggforce::geom_circle(aes(x0 = displ * 50 - 60, y0 = hwy, r=cty)) +
    #scale_size_identity() +

    # Add Image
    ggimage::geom_image(data = images,
                 aes(x = 4, y = 20, image=url),
                 size = 0.4,
                 hjust = 0.0, 
                 by="height"
        ) +
        coord_cartesian(
            xlim = c(0, 120),
            ylim = c(0, 80),
            expand = FALSE,
            clip = "on"
        )

```

**Update following really helpful input from @tjebo and further investigation.**

I have now found there are at least 4 ways to add images to plots, each with their own advantages and disadvantages. I've listed these below to help others on this search.

**Draw basic shapes to which images can be added**

```
g <- ggplot(mpg) + 
  ggforce::geom_circle(aes(x0 = displ * 50 - 60, y0 = hwy, r=cty))

```

**Plot with ggtexture - multiple images - aspect defined by x and y max - min**

<https://rdrr.io/github/clauswilke/ggtextures/man/geom_textured_rect.html>

```
g + ggtextures::geom_textured_rect(data = images, 
                                   aes(xmin = 20, xmax = 60,
                                       ymin = 20, ymax = 60, image = url), 
                                   lty = "blank", # line type of blank to remove border
                                   fill="white", # used to fill transparent areas of image
                                   nrow = 1,
                                   ncol = 1,
                                   img_width = unit(1, "null"),
                                   img_height = unit(1, "null"),
                                   position = "identity") +
  coord_equal() # A fixed scale coordinate system forces a specified ratio between the physical representation of data units on the axes. 

```

**Plot with ggimage - multiple images - aspect defined by device**

```
g + ggimage::geom_image(data = images,
                        aes(x = 20, y = 40, image=url),
                        size = 0.2,
                        by="height"
  )

```

**Plot with cowplot - single image - freedom over aspect**

Independent drawing surface and scale (0-1)

```
cowplot::ggdraw(g) + 
  cowplot::draw_image(images[[1, "url"]], 
                      x = .5, y = .3, width = 0.5, height = 0.5)

```

**Plot with annotation\_custom (ggplot) - original aspect**

Seems to use widest of width of height and centre on mid coordinates

```
image <- magick::image_read(images[[1, "url"]])
rasterImg <- grid::rasterGrob(image, interpolate = FALSE) 
g + annotation_custom(rasterImg, xmin = 00, xmax =200, ymin = 10, ymax = 50)

```