File: ani.options.R

package info (click to toggle)
r-cran-animation 2.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,268 kB
  • sloc: javascript: 873; sh: 15; makefile: 2
file content (217 lines) | stat: -rw-r--r-- 10,566 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#' Set or query animation options
#'
#' There are various parameters that control the behaviour of the animation,
#' such as time interval, maximum number of animation frames, height and width,
#' etc.
#'
#' @section Animation options: The supported animation parameters: \describe{
#'
#'   \item{interval}{ a positive number to set the time interval of the
#'   animation (unit in seconds); default to be 1. }
#'
#'   \item{nmax}{ maximum number of steps in a loop (e.g. iterations) to create
#'   animation frames. Note: the actual number of frames can be less than this
#'   number, depending on specific animations. Default to be 50.}
#'
#'   \item{ani.width, ani.height}{ width and height of image frames (unit in
#'   px); see graphics devices like \code{\link{png}}, \code{\link{jpeg}}, ...;
#'   default to be 480. NB: for different graphics devices, the units of these
#'   values might be different, e.g. PDF devices usually use inches, whereas
#'   bitmap devices often use pixels.}
#'
#'   \item{ani.res}{ The nominal resolution in ppi which will be recorded in the bitmap file,
#'   if a positive integer. Also used for units other than the default,
#'   and to convert points to pixels.;
#'   see graphics devices like \code{\link{png}}, \code{\link{jpeg}}.}
#'
#'   \item{imgnfmt}{ Customizing image number format in \code{\link{saveHTML}},
#'   \code{\link{saveGIF}}, \code{\link{saveLatex}} and \code{\link{saveVideo}},
#'   \code{\link{saveSWF}} is not included,
#'   it allows user to define the C-style string format for output image.
#'   }
#'
#'   \item{imgdir}{character: the name of the directory (a relative path) for
#'   images when creating HTML animation pages; default to be \code{'images'}.}
#'
#'   \item{htmlfile}{character: name of the target HTML main file (without path
#'   name; basename only; default to be \code{'index.html'})}
#'
#'   \item{ani.dev}{a function or a function name: the graphics device; e.g.
#'   (\code{\link{png}}, \code{\link{pdf}}, ...); default to be \code{'png'}}
#'
#'   \item{ani.type}{character: image format for animation frames, e.g.
#'   \code{png}, \code{jpeg}, ...; default to be \code{'png'}; this will be used
#'   as the file extension of images, so don't forget to change this option as
#'   well when you changed the option \code{ani.dev}}
#'
#'   \item{title, description}{character: the title and description of the
#'   animation in the HTML page created by \code{\link{saveHTML}}}
#'
#'   \item{verbose}{logical: if \code{TRUE}, write a footer part
#'   in the HTML page containing detailed technical information else
#'   the footer of the page will be blank.}
#'
#'   \item{loop}{logical or numeric: Number of times the GIF animation is to
#'    cycle through the image sequence before stopping. By default, this is
#'    set to zero or boolean value TRUE (infinite loop).}
#'
#'   \item{autobrowse}{logical: whether auto-browse the animation page
#'   immediately after it is created? (default to be \code{interactive()})}
#'
#'   \item{autoplay}{logical: whether to autoplay the animation when the HTML
#'   page is loaded (default to be \code{TRUE}); only applicable to
#'   \code{\link{saveHTML}}}
#'
#'   \item{use.dev}{ whether to use the graphics device specified in
#'   \code{ani.options('ani.dev')} (default to be \code{TRUE}); if \code{FALSE},
#'   we need to generate image files by our own approaches in the expression
#'   \code{expr} (see functions \code{\link{saveHTML}}, \code{\link{saveGIF}},
#'   \code{\link{saveLatex}} and \code{\link{saveSWF}}); this can be useful when
#'   the output cannot be captured by standard R graphics devices -- a typical
#'   example is the \pkg{rgl} graphics (we can use \code{rgl.snapshot} to
#'   capture \pkg{rgl} graphics to png files, or \code{rgl.postscript} to save
#'   plots as postscript/pdf; see \code{demo('rgl_animation')} or
#'   \code{demo('use_Cairo')} for examples or the last example below). Note,
#'   however, we do not really have to create the images using R graphics
#'   devices -- see \code{demo('flowers')} on how to download images from the
#'   Internet and create an HTML animation page!}
#'
#'   }
#'
#' @section Hidden options: There are a couple of ``hidden'' options which are
#'   designed to facilitate the usage of some functions but are not initialized
#'   like the above options when the package is loaded, including:
#'
#'   \describe{
#'
#'   \item{convert}{this option will be checked first when calling
#'   \code{\link{im.convert}} (or \code{\link{saveGIF}}) to see if it contains
#'   the path to \file{convert.exe}; we can specify it beforehand to save the
#'   efforts in searching for \file{convert.exe} in ImageMagick under Windows.
#'   For example, \code{ani.options(convert = 'c:/program
#'   files/imagemagick/convert.exe')}; note this option also works for Mac and
#'   Linux (see \code{help(im.convert)})}
#'
#'   \item{swftools}{this can help \code{\link{saveSWF}} save the efforts of
#'   searching for the software package ``SWF Tools'' under Windows; e.g. we can
#'   specify \code{ani.options(swftools = 'c:/program files/swftools')} in
#'   advance}
#'
#'   \item{img.fmt}{the value of this option can be used to determine the image
#'   filename format when we want to use custom graphics devices to record
#'   images, e.g. in \code{\link{saveLatex}}, if \code{ani.options('use.dev') ==
#'   FALSE}, then \code{ani.options('img.fmt')} will be a string like
#'   \code{'path/to/output/img.name\%d.png'}, so we can use it to generate file
#'   names in the argument \code{expr}; see \code{demo('rgl_animation')} for
#'   example or the last example below}
#'
#'   \item{qpdf}{the path of the program \command{qpdf}, e.g.
#'   \code{ani.options(qpdf = 'C:/Software/qpdf/bin/qpdf.exe')}; \command{qpdf}
#'   is mainly used to compress PDF files in this package, and it is a smaller
#'   tool than \command{pdftk}. It is recommended over \command{pdftk}
#'   especially under Linux, because tests show that \command{pdftk} does not
#'   work well under Linux in compressing PDF files, while \command{qpdf} is
#'   much better.}
#'
#'   \item{pdftk}{the path of the program \command{Pdftk}, e.g.
#'   \code{ani.options(pdftk = 'C:/Software/pdftk.exe')} or
#'   \code{ani.options(pdftk = '/home/john/bin/pdftk')}; \command{pdftk} will be
#'   used to compress the PDF graphics output in the function
#'   \code{\link{pdftk}}; compression will not be tried if this options is
#'   \code{NULL}. This option will only affect \code{\link{saveGIF}},
#'   \code{\link{saveLatex}} and \code{\link{saveSWF}} when
#'   \code{ani.options('ani.type')} is \code{'pdf'}.}
#'
#'   \item{ffmpeg}{the path of the progam \command{ffmpeg}, e.g.
#'   \code{ani.options(ffmpeg = 'C:/Software/ffmpeg/bin/ffmpeg.exe')}; FFmpeg is
#'   used to convert a sequence of images to a video. See
#'   \code{\link{saveVideo}}.}
#'
#'   }
#' @param ... arguments in \code{tag = value} form, or a list of tagged values.
#'   The tags usually come from the animation parameters described below, but
#'   they are not restricted to these tags (any tag can be used; this is similar
#'   to \code{\link{options}}).
#' @return \code{ani.options()} returns a list containing the options: when
#'   parameters are set, their former values are returned in an invisible named
#'   list.  Such a list can be passed as an argument to
#'   \code{\link{ani.options}} to restore the parameter values.
#'
#'   \code{ani.options('tag')} returns the value of the option \code{'tag'}.
#'
#'   \code{ani.options(c('tag1', 'tag2'))} or \code{ani.options('tag1', 'tag2')}
#'   returns a list containing the corresponding options.
#' @note Please note that \code{nmax} is not always equal to the number of
#'   animation frames. Sometimes there is more than one frame recorded in a
#'   single step of a loop, for instance, there are 2 frames generated in each
#'   step of \code{\link{kmeans.ani}}, and 4 frames in \code{\link{knn.ani}},
#'   etc; whereas for \code{\link{newton.method}}, the number of animation
#'   frames is not definite, because there are other criteria to break the loop.
#'
#'   This function can be used for almost all the animation functions such as
#'   \code{\link{brownian.motion}}, \code{\link{boot.iid}},
#'   \code{\link{buffon.needle}}, \code{\link{cv.ani}}, \code{\link{flip.coin}},
#'   \code{\link{kmeans.ani}}, \code{\link{knn.ani}}, etc. Most of the options
#'   here will affect the behaviour of animations of the formats HTML, GIF, SWF
#'   and PDF; on-screen animations are only affected by \code{interval} and
#'   \code{nmax}.
#'
#' @author Yihui Xie
#' @references Examples at \url{https://yihui.org/animation/example/ani-options/}
#' @seealso \code{\link{options}}, \code{\link{dev.interactive}},
#'   \code{\link{saveHTML}}, \code{\link{saveGIF}}, \code{\link{saveLatex}},
#'   \code{\link{saveSWF}}, \code{\link{pdftk}}
#'
#'   \url{http://qpdf.sourceforge.net/}
#'
#'   \url{http://www.pdflabs.com/docs/pdftk-man-page/}
#' @export
ani.options = function(...) {
  lst = list(...)
  .ani.opts = .ani.env$.ani.opts
  if (length(lst)) {
    if (is.null(names(lst)) && !is.list(lst[[1]])) {
      lst = unlist(lst)
      if (length(lst) == 1) .ani.opts[[lst]] else .ani.opts[lst]
    } else {
      omf = .ani.opts
      if (is.list(lst[[1]]))
        lst = lst[[1]]
      if (length(lst) > 0) {
        .ani.opts[names(lst)] = lst
        .ani.env$.ani.opts = .ani.opts
        if (!identical(omf$nmax, .ani.opts$nmax) && interactive()) {
          message("animation option 'nmax' changed: ", omf$nmax, ' --> ', .ani.opts$nmax)
        }
        .check.opts(.ani.opts)
      }
      invisible(omf)
    }
  } else {
    .ani.opts
  }
}

## create an environment to store animation options
.ani.env = new.env()

## check validity of options
.check.opts = function(opts) {
  dev = opts$ani.dev
  type = opts$ani.type
  if (opts$use.dev && is.character(dev)) {
    switch(dev, png = {
      if (type != 'png')
        warning("the graphics device is png() but the file extension is not 'png'!")
    }, jpeg = {
      if (!(type %in% c('jpg', 'jpeg')))
        warning("the graphics device is jpeg() but the file extension is not 'jpeg' or 'jpg'!")
    }, pdf = {
      if (type != 'pdf')
        warning("the graphics device is pdf() but the file extension is not 'pdf'!")
    })
  }
  if (type == 'pdf' && (opts$ani.width >= 100 || opts$ani.height >= 100)) {
    warning('you are using a pdf device but the width and height are greater than 100 inches; are you sure this is correct?')
  }
}