简体   繁体   中英

How do I rescale local images for bookdown / rmarkdown website?

I have a pretty big (~14MB) *.jpeg in my bookdown project (or rmarkdown website, doesn't really matter, I think). This is an external, static image, not touched by R (so far).

I'm calling the picture like so:

```{r q-pic, echo=FALSE, out.width="100%", fig.cap="Q-Sorting during the 2016 CiviCon", dpi = 72}
include_graphics(path = "img/q-sorting3.jpg")
```

I've also set retina via opts_knit$set(fig.retina = 2) .

I don't really care how huge the PDF is, but obviously, a ~14MB image on a website is pretty bad.

Is there a way that some element of the knitr() rmarkdown() bookdown() toolchain can automatically rescale images to a specified, appropriate resolution?

I naively assumed that if both out.width and dpi were specified, that the image would be rescaled (ie.: smaller file size) behind the curtains, but that either appears not to be the case, or I'm using it wrong .

Ps.: I understand that there's a possibility to specifiy a dpi and then have knitr figure out an appropriate size; that's not my concern. I'd like, sort of, the inverse of that.

I think the only way to adjust the actual image size (and not just how it is scaled in the HTML) is to load the image into R and rasterize it:

```{r fig.width=3}
library(jpeg)
library(grid)
img <- readJPEG("test.jpg")
grid.raster(img)
```

(Rasterization approach adapted from: How to set size for local image using knitr for markdown? )

This will result in a smaller image/HTML file.

I've now also implemented a compression and re-scaling function in plain R. It's not fast, an it may be clumsy, but it get's the job done.

library(jpeg)
library(imager)

resize_n_compress <- function(file_in, file_out, xmax = 1920, quality = 0.7, cutoff = 100000) {
  # xmax <- 1920  # y pixel max
  # quality <- 0.7  # passed on to jpeg::writeJPEG()
  # cutoff <- 100000  # files smaller than this will not be touched
  # file_out <- "test.jpg"
  if (file.size(file_in) < cutoff) {  # in this case, just copy file
    if (!(file_in == file_out)) {
      file.copy(from = file_in, to = file_out, overwrite = TRUE)
    }
  } else {# if larger than cutoff
    image_raw <- imager::load.image(file = file_in)
    if (dim(image_raw)[1] > xmax) {  # resize only when larger
      x_pix <- xmax  # just in case we want to calculate this, too at some point
      x_factor <- xmax/dim(image_raw)[1]
      y_pix <- round(dim(image_raw)[2] * x_factor)
      image_resized <- imager::resize(im = image_raw, size_x = x_pix, size_y = y_pix)
    } else {# otherwise take raw
      image_resized <- image_raw
    }
    saveme <- imager:::convert.im.toPNG(A = image_resized)
    jpeg::writeJPEG(image = saveme, target = file_out, quality = quality)  # this overwrites by default
  }
}

Also see these related issues on knitr and blogdown .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM