Image and Video Generation

# This vignette runs against recorded, credential-free API fixtures. A maintainer
# records them once with real Azure image credentials
# (data-raw/record-doc-outputs.R) and commits them under vignettes/media-generation/.
# When the fixtures are present the image call below executes and its real result
# -- including the generated picture -- is shown. When they are absent the API
# chunk is not evaluated so the vignette still builds without credentials. Nothing
# on this page is fabricated: illustrative-only calls are marked eval = FALSE and
# show code without invented output.
fixture_dir <- "media-generation"
recording <- nzchar(Sys.getenv("FOUNDRY_RECORD_DOCS"))
have_fixtures <- dir.exists(fixture_dir) && length(list.files(fixture_dir)) > 0
run_api <- requireNamespace("httptest2", quietly = TRUE) &&
  (recording || have_fixtures)

# Attach foundryR before start_vignette(): httptest2 only sources the package's
# inst/httptest2/start-vignette.R (which sets replay placeholders) from attached
# packages.
library(foundryR)

if (run_api) {
  httptest2::start_vignette(fixture_dir)
}

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = run_api
)

# Embed the generated image inline as a base64 data URI, reading the file that
# foundry_save_image() just wrote. This demonstrates that helper and renders the
# real picture reliably offline, with no external-file handling (mirrors the
# <audio> players in the audio vignette).
embed_image <- function(path, width = "60%", alt = "Generated image") {
  if (!requireNamespace("base64enc", quietly = TRUE)) {
    return(invisible(NULL))
  }
  uri <- paste0("data:image/jpeg;base64,", base64enc::base64encode(path))
  knitr::asis_output(
    sprintf('<img src="%s" width="%s" alt="%s">', uri, width, alt)
  )
}
library(foundryR)

foundryR supports current v1 preview image generation and editing parameters, while keeping the legacy deployment-style image endpoint available with api = "deployment".

Configure image resources

Image models may be deployed on the same Azure OpenAI resource as your text models, or on a separate resource. Use the image-specific helpers only when the resource or key differs. This setup chunk is illustrative and is not run:

foundry_set_image_endpoint(Sys.getenv("AZURE_FOUNDRY_IMAGE_ENDPOINT"))
foundry_set_image_key("your-image-api-key")

Sys.setenv(AZURE_FOUNDRY_IMAGE_MODEL = "my-image-deployment")

Generate an image

foundry_image() returns one row per generated image with the prompt, any model-revised prompt, the output format, and the image bytes (as a URL or base64, depending on the model). Here we ask for a small, compressed JPEG so the recorded fixture stays light.

image <- foundry_image(
  "A friendly red panda reading a book, flat vector illustration",
  model = "gpt-image-2",
  size = "1024x1024",
  quality = "low",
  output_format = "jpeg",
  output_compression = 40
)

image[, c("prompt", "revised_prompt", "output_format", "created")]

Decode the returned bytes to a file with foundry_save_image() and display the result:

img_path <- tempfile(fileext = ".jpeg")
foundry_save_image(image, img_path)
embed_image(
  img_path,
  alt = "AI-generated flat vector illustration of a friendly red panda reading a book"
)

Image URLs are temporary. Save images that belong in reports, stimuli, or audited records to a location you choose. This vignette uses temporary files and removes them after use. Inline image display requires the suggested base64enc package.

Edit an image

foundry_image_edit() takes an existing image and a prompt. The call below is illustrative (it needs an image file on disk) and is not run here:

edited_path <- tempfile(fileext = ".jpeg")
edited <- foundry_image_edit(
  image = img_path,
  prompt = "Use a blue, Microsoft-inspired color palette.",
  model = "gpt-image-2",
  output_format = "jpeg"
)

foundry_save_image(edited, edited_path)
unlink(edited_path)

Generate video (preview)

Video generation is a preview, long-running workflow: create a job, poll it, and download the content once a generation succeeds. Because the job is asynchronous these calls are shown for reference and are not run here:

job <- foundry_video_job_create(
  "A short animation of dots clustering into groups",
  model = "my-video-model",
  width = 1280,
  height = 720,
  n_seconds = 5
)

job <- foundry_video_job_get(job$job_id)

video_path <- tempfile(fileext = ".mp4")
foundry_video_download(
  generation_id = job$generation_id,
  path = video_path
)
unlink(video_path)

When to use these APIs

if (run_api) {
  unlink(img_path)
  httptest2::end_vignette()
}


Try the foundryR package in your browser

Any scripts or data that you put into this service are public.

foundryR documentation built on Sept. 25, 2026, 1:10 a.m.