blob: 46dbcbc3304426deec04548d2e2c0e58f6006368 [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
antaldaniel8d1bd5b2018-05-30 21:43:33 +020031#' `c("\\\\usepackage{threeparttable}", "\\\\usepackage{icons}")` You could
32#' probably add your language package here if you use non-English text in your
33#' table, such as `\\\\usepackage[magyar]{babel}`.
Hao Zhu2a64dc62017-08-28 10:57:57 -040034#' @param keep_pdf A T/F option to control if the mid-way standalone pdf should
35#' be kept. Default is `FALSE`.
Hao Zhu4840bc92017-09-15 15:55:05 -040036#' @param density Resolution to read the PDF file. Default value is 300, which
37#' should be sufficient in most cases.
Salzer27eb90b2018-02-11 16:14:04 -050038#' @param keep_tex A T/F option to control if the latex file that is initially created
39#' should be kept. Default is `FALSE`.
Hao Zhu2a64dc62017-08-28 10:57:57 -040040#'
Hao Zhu2a64dc62017-08-28 10:57:57 -040041#' @export
42kable_as_image <- function(kable_input, filename = NULL,
43 file_format = "png",
44 latex_header_includes = NULL,
Hao Zhu4840bc92017-09-15 15:55:05 -040045 keep_pdf = FALSE,
Salzer27eb90b2018-02-11 16:14:04 -050046 density = 300,
47 keep_tex = FALSE) {
Hao Zhu4840bc92017-09-15 15:55:05 -040048 if (!requireNamespace("magick", quietly = TRUE)) {
49 stop('kable_as_image requires the magick package, which is not available ',
50 'on all platforms. Please get it installed ',
51 'via install.packages("magick"). If you are running on Windows, you ',
52 'also need to install Ghostscript. Please download it here:',
53 'https://ghostscript.com/')
Hao Zhu2a64dc62017-08-28 10:57:57 -040054 } else {
Hao Zhu4840bc92017-09-15 15:55:05 -040055 temp_tex <- c(
56 "\\documentclass[border=1mm, preview]{standalone}",
57 "\\usepackage[active,tightpage]{preview}",
58 "\\usepackage{varwidth}",
59 "\\usepackage{amssymb, amsmath}",
60 "\\usepackage{ifxetex,ifluatex}",
61 "\\usepackage{fixltx2e}",
62 "\\usepackage{polyglossia}",
63 "\\setmainlanguage{$mainlang$}",
64 latex_pkg_list(),
65 "\\usepackage{graphicx}",
66 "\\usepackage{mathspec}",
67 "\\usepackage{xltxtra,xunicode}",
68 latex_header_includes,
69 "\\begin{document}",
Hao Zhu3fc0e882018-04-03 16:06:41 -040070 solve_enc(kable_input),
Hao Zhu4840bc92017-09-15 15:55:05 -040071 "\\end{document}"
72 )
73 temp_tex <- paste(temp_tex, collapse = "\n")
74 temp_file <- paste0("table_", format(Sys.time(), "%Y-%m-%d_%H%M%S"))
antaldaniel2ea01fb2018-05-30 21:20:50 +020075 writeLines(temp_tex, paste0(temp_file, ".tex"), useBytes = T)
Hao Zhu4840bc92017-09-15 15:55:05 -040076 system(paste0("xelatex -interaction=batchmode ", temp_file, ".tex"))
77 temp_file_delete <- paste0(temp_file, c(".tex", ".aux", ".log"))
Salzer27eb90b2018-02-11 16:14:04 -050078 if(!keep_tex) {
79 unlink(temp_file_delete)
80 }
Hao Zhu2a64dc62017-08-28 10:57:57 -040081
Hao Zhu4840bc92017-09-15 15:55:05 -040082 table_img_pdf <- try(magick::image_read(paste0(temp_file, ".pdf"),
83 density = density),
84 silent = T)
85 if (class(table_img_pdf) == "try-error") {
86 stop("Ghostscript is required to read PDF on windows. ",
87 "Please download it here: https://ghostscript.com/")
88 }
89 if (!keep_pdf) {
90 unlink(paste0(temp_file, ".pdf"))
91 }
92 table_img <- magick::image_convert(table_img_pdf, file_format)
93 if (!is.null(filename)) {
94 temp_img <- paste0(filename, ".", file_format)
95 } else {
96 temp_img <- tempfile(fileext = paste0(".", file_format))
97 }
98 magick::image_write(table_img, temp_img)
99
100 include_graphics(temp_img)
101 }
Hao Zhu2a64dc62017-08-28 10:57:57 -0400102}