Skip to content

Commit 0b2eeb9

Browse files
committed
First stab at implementing images endpoint
1 parent b0532b9 commit 0b2eeb9

File tree

7 files changed

+114
-29
lines changed

7 files changed

+114
-29
lines changed

NAMESPACE

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export(paramORdefault)
2020
export(plot_ly)
2121
export(plotly)
2222
export(plotlyOutput)
23+
export(plotly_IMAGE)
2324
export(plotly_POST)
2425
export(plotly_build)
2526
export(plotly_empty)

R/plotly.R

+20-2
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,26 @@ plotly_build <- function(l = last_plot()) {
316316
}
317317
# search for keyword args in traces and place them at the top level
318318
kwargs <- lapply(x$data, function(z) z[get_kwargs()])
319-
if (length(kwargs) == 1) kwargs <- c(kwargs, kwargs)
320-
x <- c(x, Reduce(modifyList, kwargs))
319+
# later keywords args take precedence
320+
kwargs <- Reduce(modifyList, kwargs)
321+
# empty keyword arguments can cause problems
322+
kwargs <- kwargs[sapply(kwargs, length) > 0]
323+
# filename & fileopt are keyword arguments required by the API
324+
if (!is.null(x$url) || !is.null(kwargs$filename))
325+
kwargs$fileopt <- "overwrite"
326+
kwargs$fileopt <- kwargs$fileopt %||% "new"
327+
# try our damndest to assign a sensible filename
328+
if (is.null(kwargs$filename)) {
329+
kwargs$filename <-
330+
as.character(kwargs$layout$title) %||%
331+
paste(
332+
c(kwargs$layout$xaxis$title,
333+
kwargs$layout$yaxis$title,
334+
kwargs$layout$zaxis$title),
335+
collapse = " vs. "
336+
) %||%
337+
"plot from api"
338+
}
321339
# traces shouldn't have any names
322340
x$data <- setNames(x$data, NULL)
323341
# add plotly class mainly for printing method

R/plotly_IMAGE.R

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#' Create/Modify plotly images
2+
#'
3+
#' The images endpoint turn a plot (which may be given in multiple forms)
4+
#' into an image of the desired format.
5+
#'
6+
#' @param x either a plotly object or a list.
7+
#' @param width Image width in pixels
8+
#' @param height Image height in pixels
9+
#' @param format The desired image format 'png', 'jpeg', 'svg', 'pdf', 'eps', or 'webp'
10+
#' @param scale Both png and jpeg formats will be scaled beyond the specified width and height by this number.
11+
#' @param encoded A boolean flag for base64 encoding of bytes
12+
#' @export
13+
#' @examples
14+
#'
15+
#' plotly_IMAGE(plot_ly(x = 1:10))
16+
#'
17+
#'
18+
19+
plotly_IMAGE <- function(x, width = 1000, height = 500, format = "png",
20+
scale = 4, encoded = FALSE) {
21+
x <- plotly_build(x)
22+
23+
bod <- list(
24+
figure = to_JSON(x[c("data", "layout")]),
25+
width = width,
26+
height = height,
27+
format = format,
28+
scale = scale,
29+
encoded = encoded
30+
)
31+
32+
base_url <- file.path(get_domain("v2"), "images")
33+
resp <- httr::POST(base_url, plotly_headers("v2"), body = bod)
34+
con <- process(struct(resp, "image"))
35+
36+
}

R/plotly_POST.R

+1-20
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,6 @@
2828

2929
plotly_POST <- function(x) {
3030
x <- plotly_build(x)
31-
# empty keyword arguments can cause problems
32-
kwargs <- x[get_kwargs()]
33-
kwargs <- kwargs[sapply(kwargs, length) > 0]
34-
35-
# filename & fileopt are keyword arguments required by the API
36-
# (note they can also be specified by the user)
37-
if (!is.null(x$url) || !is.null(kwargs$filename)) kwargs$fileopt <- "overwrite"
38-
if (is.null(kwargs$filename)) {
39-
kwargs$filename <-
40-
as.character(kwargs$layout$title) %||%
41-
paste(
42-
c(kwargs$layout$xaxis$title,
43-
kwargs$layout$yaxis$title,
44-
kwargs$layout$zaxis$title),
45-
collapse = " vs. "
46-
) %||%
47-
"plot from api"
48-
}
49-
if (is.null(kwargs$fileopt)) kwargs$fileopt <- "new"
5031
# construct body of message to plotly server
5132
bod <- list(
5233
un = verify("username"),
@@ -55,7 +36,7 @@ plotly_POST <- function(x) {
5536
platform = "R",
5637
version = as.character(packageVersion("plotly")),
5738
args = to_JSON(x$data),
58-
kwargs = to_JSON(kwargs)
39+
kwargs = to_JSON(x[get_kwargs()])
5940
)
6041
base_url <- file.path(get_domain(), "clientresp")
6142
resp <- httr::POST(base_url, body = bod)

R/process.R

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ process.clientresp <- function(resp) {
1515
con
1616
}
1717

18+
process.image <- function(resp) {
19+
httr::stop_for_status(resp)
20+
browser()
21+
con <- from_JSON(httr::content(resp, as = "text"))
22+
}
23+
1824
process.figure <- function(resp) {
1925
httr::stop_for_status(resp)
2026
con <- from_JSON(content(resp, as = "text"))

R/utils.R

+20-7
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,11 @@ struct <- function(x, y, ...) {
141141
get_domain <- function(type = "main") {
142142
if (type == "stream") {
143143
Sys.getenv("plotly_streaming_domain", "http://stream.plot.ly")
144+
} else if (type == "v2") {
145+
Sys.getenv("plotly_domain", "https://api.plot.ly/v2/")
144146
} else {
145147
Sys.getenv("plotly_domain", "https://plot.ly")
146148
}
147-
148149
}
149150

150151
# plotly's special keyword arguments in POST body
@@ -153,12 +154,24 @@ get_kwargs <- function() {
153154
}
154155

155156
# POST header fields
156-
plotly_headers <- function() {
157-
httr::add_headers(.headers = c(
158-
"plotly-username" = verify("username"),
159-
"plotly-apikey" = verify("api_key"),
160-
"plotly-version" = as.character(packageVersion("plotly")),
161-
"plotly-platform" = "R"))
157+
plotly_headers <- function(type = "main") {
158+
usr <- verify("username")
159+
key <- verify("api_key")
160+
h <- if (type == "v2") {
161+
c(
162+
"Plotly-Username" = base64enc::base64encode(charToRaw(usr)),
163+
"Plotly-Apikey" = base64enc::base64encode(charToRaw(key)),
164+
"Plotly-Client-Platform" = paste("R", as.character(packageVersion("plotly")))
165+
)
166+
} else {
167+
c(
168+
"plotly-username" = usr,
169+
"plotly-apikey" = key,
170+
"plotly-version" = as.character(packageVersion("plotly")),
171+
"plotly-platform" = "R"
172+
)
173+
}
174+
httr::add_headers(.headers = h)
162175
}
163176

164177
# try to write environment variables to an .Rprofile

man/plotly_IMAGE.Rd

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
% Generated by roxygen2 (4.1.1): do not edit by hand
2+
% Please edit documentation in R/plotly_IMAGE.R
3+
\name{plotly_IMAGE}
4+
\alias{plotly_IMAGE}
5+
\title{Create/Modify plotly images}
6+
\usage{
7+
plotly_IMAGE(x, width = 1000, height = 500, format = "png", scale = 4,
8+
encoded = FALSE)
9+
}
10+
\arguments{
11+
\item{x}{either a plotly object or a list.}
12+
13+
\item{width}{Image width in pixels}
14+
15+
\item{height}{Image height in pixels}
16+
17+
\item{format}{The desired image format 'png', 'jpeg', 'svg', 'pdf', 'eps', or 'webp'}
18+
19+
\item{scale}{Both png and jpeg formats will be scaled beyond the specified width and height by this number.}
20+
21+
\item{encoded}{A boolean flag for base64 encoding of bytes}
22+
}
23+
\description{
24+
The images endpoint turn a plot (which may be given in multiple forms)
25+
into an image of the desired format.
26+
}
27+
\examples{
28+
plotly_IMAGE(qplot(1:10))
29+
}
30+

0 commit comments

Comments
 (0)