如何为 bookdown / rmarkdown 网站重新缩放本地图像?
How do I rescale local images for bookdown / rmarkdown website?
我的 bookdown 项目(或 rmarkdown 网站,我认为并不重要)中有一个相当大的 (~14MB) *.jpeg
。
这是一个外部静态图像,R 未触及(到目前为止)。
我是这样称呼图片的:
```{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")
```
我还通过 opts_knit$set(fig.retina = 2)
设置了 Retina。
我真的不在乎 PDF 有多大,但显然,网站 上的 ~14MB 图片非常糟糕。
knitr()
rmarkdown()
bookdown()
工具链的某些元素是否可以自动将图像重新缩放到指定的适当分辨率?
我天真地假设,如果指定了 out.width
和 dpi
,图像将在后面重新缩放(即:较小的文件大小)窗帘,但似乎并非如此,或者我用错了。
Ps.: 我知道可以指定一个 dpi
然后让 knitr
找出合适的大小;那不是我关心的。我想要那种 inverse。
我认为调整实际图像大小(而不仅仅是它在 HTML 中的缩放方式)的唯一方法是将图像加载到 R 中并对其进行栅格化:
```{r fig.width=3}
library(jpeg)
library(grid)
img <- readJPEG("test.jpg")
grid.raster(img)
```
(光栅化方法改编自:How to set size for local image using knitr for markdown?)
这将生成一个较小的 image/HTML 文件。
我现在还在纯 R 中实现了压缩 和 re-scaling 函数。
速度不快,可能有些笨拙,但它完成了工作。
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
}
}
我的 bookdown 项目(或 rmarkdown 网站,我认为并不重要)中有一个相当大的 (~14MB) *.jpeg
。
这是一个外部静态图像,R 未触及(到目前为止)。
我是这样称呼图片的:
```{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")
```
我还通过 opts_knit$set(fig.retina = 2)
设置了 Retina。
我真的不在乎 PDF 有多大,但显然,网站 上的 ~14MB 图片非常糟糕。
knitr()
rmarkdown()
bookdown()
工具链的某些元素是否可以自动将图像重新缩放到指定的适当分辨率?
我天真地假设,如果指定了 out.width
和 dpi
,图像将在后面重新缩放(即:较小的文件大小)窗帘,但似乎并非如此,或者我用错了。
Ps.: 我知道可以指定一个 dpi
然后让 knitr
找出合适的大小;那不是我关心的。我想要那种 inverse。
我认为调整实际图像大小(而不仅仅是它在 HTML 中的缩放方式)的唯一方法是将图像加载到 R 中并对其进行栅格化:
```{r fig.width=3}
library(jpeg)
library(grid)
img <- readJPEG("test.jpg")
grid.raster(img)
```
(光栅化方法改编自:How to set size for local image using knitr for markdown?)
这将生成一个较小的 image/HTML 文件。
我现在还在纯 R 中实现了压缩 和 re-scaling 函数。 速度不快,可能有些笨拙,但它完成了工作。
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
}
}