Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

suggestion: offer rescaling / compression option to include_graphics() for external images #1273

Closed
maxheld83 opened this issue Aug 20, 2016 · 5 comments
Milestone

Comments

@maxheld83
Copy link
Contributor

it would be really nice if knitr::include_graphics() (which is used heavily, and elegantly in bookdown() would allow me to specify a DPI and size, and then rescale the external image accordingly, as per this stack-exchange question.

Note: I mean external image, like some JPEG from a camera or something, not plot images generated by R.

It would be neat especially for any kind of website output, if knitr (or some other element of the toolchain) could take care of the resizing, so that users don't end up deploying huge images when bookdown is rendered to a website, etc.

(I guess, in principal, the same concern applies to PDFs, though file size is usually less of a concern there).

@yihui
Copy link
Owner

yihui commented Sep 5, 2016

If anybody is able to implement it, I'll be happy to take a look at the pull request, otherwise I'm afraid I won't have the time to implement it in the near future.

@yihui yihui added this to the v1.15 milestone Nov 5, 2016
@yihui yihui modified the milestone: v1.15 Nov 15, 2016
@maxheld83
Copy link
Contributor Author

Just two more thoughts on this in light of related blogdown issue and bookdown issue.

On the one hand (automatic) rescaling/resizing/cropping is on the roadmap for HUGO anyway. That'll probably be easier and/or more specialised than it could be in R. For blogdown related issues, this might be a better way.

On the other hand, it's not available yet, and the HUGO support wouldn't fix this for other knitr use cases.

@maxheld83
Copy link
Contributor Author

maxheld83 commented Jan 31, 2017

I have now implemented this for my own purposes (inside blogdown), and it does work:

# resize and compress images ===
library(magick)
library(pbapply)  # just so we have a progress bar, because this thing takes a while

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
    # magick workflow
    image_raw <- image_read(path = file_in)
    if (image_info(image_raw)["width"] > xmax) {  # only resize if smaller
      image_resized <- image_scale(image = image_raw, geometry = as.character(xmax))
    } else {
      image_resized <- image_raw
    }
    image_write(image = image_resized, path = file_out, format = "jpeg", quality = quality)
  }
}

This is a bit clumsy, but it works.

This both increases the compression, and downscales the image.

While this works, it's pretty darn slow (at least on OS X for some reason, Travis CI was much faster ...), and I'm guessing this is because R isn't really meant/optimised for this kind of thing.
Handling huge, uncompressed images in RAM in R feels a bit painful, but it does work.

@yihui is this a direction you think might be worthwhile for me to pursue in a pull request?

I'm a bit confused as to where in the knitr, rmarkdown, blogdown/bookdown stack this is best included.

(Updated to now feature magick, which is a lot faster than imager).

@maxheld83 maxheld83 changed the title suggestion: offer rescaling / rastering option to include_graphics() for external images suggestion: offer rescaling / compression option to include_graphics() for external images Jan 31, 2017
@yihui yihui added this to the v0.18 milestone Oct 15, 2017
@yihui
Copy link
Owner

yihui commented Oct 15, 2017

I suggest you write your own wrapper function like

include_image = function(x, ...) {
  # first process x by yourself
  magic::whatever....
  # return
  knitr::include_graphics(x, ...)
}

I don't have much interest in provide built-in support for this.

@yihui yihui closed this as completed Oct 15, 2017
@github-actions
Copy link

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants