blob: 30c33f9ff8c7332220ba49c747cb36df1f5a7906 [file] [log] [blame]
Hao Zhu2a64dc62017-08-28 10:57:57 -04001#' Convert a LaTeX table to an image and place it in a rmarkdown document
2#'
3#' @description This is a LaTeX-only function. This function will render the
4#' raw LaTeX code (could be codes generated by other table packages like
5#' `xtable`) to generate a table, convert it to an image and put it back to a
6#' rmarkdown environment. It is a "better than nothing" solution to print high
7#' quality tables in rmarkdown Word document. By using this, you need to take
Hao Zhu245931c2017-09-01 22:43:56 -04008#' the responsibility of explaining to your collaborators why they can't make
Hao Zhua9c43dc2017-09-04 23:00:39 -04009#' edits to the tables in Word.
Hao Zhu2a64dc62017-08-28 10:57:57 -040010#'
11#' Also, if a filename is provided, user has the option to "save" the table to
12#' an image file like `ggplot2::ggsave()`.
13#'
Hao Zhu246b95c2017-09-14 14:29:48 -040014#' Note that, if you are using this function on a Windows computer, you need
15#' to install Ghostscript before you can use this feature. It is essential for
16#' magick to read PDFs on Windows. Website for Ghostscript: https://ghostscript.com/
17#'
Hao Zhu2a64dc62017-08-28 10:57:57 -040018#' The idea of this function was coming from [this StackOverflow question](https://stackoverflow.com/questions/44711313/save-rmarkdowns-report-tables-and-figures-to-file).
19#' The approach was learned and adopted from the [texpreview](https://github.com/metrumresearchgroup/texPreview)
20#' package, which allows you to preview the results of TeX code in the Viewer panel.
21#'
22#' @param kable_input Raw LaTeX code to generate a table. It doesn't have to
23#' came from `kable` or `kableExtra`.
24#' @param filename Character String. If specified, the image will be saved under
25#' the specified (path &) name. You don't need to put file format like ".png"
26#' here.
27#' @param file_format Character String to specify image format, such as `png`,
28#' `jpeg`, `gif`, `tiff`, etc. Default is `png`.
29#' @param latex_header_includes A character vector of extra LaTeX header stuff.
30#' Each element is a row. You can have things like
31#' `c("\\usepackage{threeparttable}", "\\usepackage{icons}")`
32#' @param keep_pdf A T/F option to control if the mid-way standalone pdf should
33#' be kept. Default is `FALSE`.
Hao Zhu4840bc92017-09-15 15:55:05 -040034#' @param density Resolution to read the PDF file. Default value is 300, which
35#' should be sufficient in most cases.
Hao Zhu2a64dc62017-08-28 10:57:57 -040036#'
Hao Zhu2a64dc62017-08-28 10:57:57 -040037#' @export
38kable_as_image <- function(kable_input, filename = NULL,
39 file_format = "png",
40 latex_header_includes = NULL,
Hao Zhu4840bc92017-09-15 15:55:05 -040041 keep_pdf = FALSE,
42 density = 300) {
43 if (!requireNamespace("magick", quietly = TRUE)) {
44 stop('kable_as_image requires the magick package, which is not available ',
45 'on all platforms. Please get it installed ',
46 'via install.packages("magick"). If you are running on Windows, you ',
47 'also need to install Ghostscript. Please download it here:',
48 'https://ghostscript.com/')
Hao Zhu2a64dc62017-08-28 10:57:57 -040049 } else {
Hao Zhu4840bc92017-09-15 15:55:05 -040050 temp_tex <- c(
51 "\\documentclass[border=1mm, preview]{standalone}",
52 "\\usepackage[active,tightpage]{preview}",
53 "\\usepackage{varwidth}",
54 "\\usepackage{amssymb, amsmath}",
55 "\\usepackage{ifxetex,ifluatex}",
56 "\\usepackage{fixltx2e}",
57 "\\usepackage{polyglossia}",
58 "\\setmainlanguage{$mainlang$}",
59 latex_pkg_list(),
60 "\\usepackage{graphicx}",
61 "\\usepackage{mathspec}",
62 "\\usepackage{xltxtra,xunicode}",
63 latex_header_includes,
64 "\\begin{document}",
65 enc2utf8(as.character(kable_input)),
66 "\\end{document}"
67 )
68 temp_tex <- paste(temp_tex, collapse = "\n")
69 temp_file <- paste0("table_", format(Sys.time(), "%Y-%m-%d_%H%M%S"))
Hao Zhub35f1882017-10-10 16:34:16 -040070 writeLines(temp_tex, paste0(temp_file, ".tex"))
Hao Zhu4840bc92017-09-15 15:55:05 -040071 system(paste0("xelatex -interaction=batchmode ", temp_file, ".tex"))
72 temp_file_delete <- paste0(temp_file, c(".tex", ".aux", ".log"))
73 unlink(temp_file_delete)
Hao Zhu2a64dc62017-08-28 10:57:57 -040074
Hao Zhu4840bc92017-09-15 15:55:05 -040075 table_img_pdf <- try(magick::image_read(paste0(temp_file, ".pdf"),
76 density = density),
77 silent = T)
78 if (class(table_img_pdf) == "try-error") {
79 stop("Ghostscript is required to read PDF on windows. ",
80 "Please download it here: https://ghostscript.com/")
81 }
82 if (!keep_pdf) {
83 unlink(paste0(temp_file, ".pdf"))
84 }
85 table_img <- magick::image_convert(table_img_pdf, file_format)
86 if (!is.null(filename)) {
87 temp_img <- paste0(filename, ".", file_format)
88 } else {
89 temp_img <- tempfile(fileext = paste0(".", file_format))
90 }
91 magick::image_write(table_img, temp_img)
92
93 include_graphics(temp_img)
94 }
Hao Zhu2a64dc62017-08-28 10:57:57 -040095}