---
title: "Image and Video Generation"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Image and Video Generation}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
# 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)
  )
}
```

```{r library, eval = TRUE}
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:

```{r image-config, eval = FALSE}
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.

```{r generate}
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:

```{r show-image}
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:

```{r edit-call, eval = FALSE}
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:

```{r video-call, eval = FALSE}
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

- Generate research stimuli or report illustrations with `foundry_image()`.
- Iterate on existing figures or image stimuli with `foundry_image_edit()`.
- Treat video as experimental: keep prompts, job IDs, and output files together
  so generated assets remain reproducible and auditable.
- Track costs separately from text calls. Image and video generation are usually
  more expensive than text and embedding calls.

```{r cleanup, include = FALSE, eval = TRUE}
if (run_api) {
  unlink(img_path)
  httptest2::end_vignette()
}
```
