# `PhoenixKitAI.Images.Operations`
[🔗](https://github.com/BeamLabEU/phoenix_kit_ai/blob/0.23.1/lib/phoenix_kit_ai/images/operations.ex#L1)

The named image operations `PhoenixKitAI.Images.process/4` composes
into one edit prompt.

An operation is a prompt template plus, optionally, parameters it
needs, request options it implies (a transparent cutout wants
`background: "transparent"` and a PNG), a fallback template for when
those options are not available on the model, presets for a
parameter, and whether it needs reference images after the subject.

## Built-ins

| operation | parameters | notes |
|---|---|---|
| `:instruction` | `text` | free text; a bare string in the list means this |
| `:clean_background` | `color` (default `"white"`) | plain studio backdrop |
| `:blur_background` | | shallow depth of field |
| `:remove_background` | | transparent PNG; falls back to plain white |
| `:replace_background` | `with` | described new background |
| `:remove_reflections` | | glare and specular highlights |
| `:remove_objects` | `what` | remove and fill |
| `:enhance` | | exposure, white balance, sharpness |
| `:upscale` | `resolution` (default `"2K"`) | asks for a bigger output |
| `:relight` | `light` (preset atom or text) | `:day`, `:evening`, `:night`, `:studio`, `:golden_hour`, `:overcast` |
| `:recolor` | `what`, `color` | one element's colour |
| `:straighten` | | level horizon, vertical verticals |
| `:crop_to_subject` | | tight crop, even margins |
| `:restyle` | | needs reference images; borrows their materials and mood |

## Extending

A host adds or overrides operations in config:

    config :phoenix_kit_ai, image_operations: %{
      product_shot: %{
        description: "Catalogue product shot",
        prompt: "Place the product on a seamless white sweep with soft studio light.",
        options: %{aspect_ratio: "1:1"}
      }
    }

And an admin can override any operation's wording without a deploy:
a saved prompt named `Image op <name>` — its slug, derived from the
name, is `image-op-<name>` with dashes, e.g. a prompt called
"Image op remove background" — replaces the built-in template; its
`{{Variables}}` are filled from the operation's parameters.

# `name`

```elixir
@type name() :: atom()
```

# `params`

```elixir
@type params() :: %{optional(atom()) =&gt; term()}
```

# `spec`

```elixir
@type spec() :: %{
  :prompt =&gt; String.t(),
  optional(:description) =&gt; String.t(),
  optional(:params) =&gt; [atom()],
  optional(:defaults) =&gt; params(),
  optional(:options) =&gt; map(),
  optional(:fallback_prompt) =&gt; String.t(),
  optional(:presets) =&gt; %{optional(atom()) =&gt; String.t()},
  optional(:references) =&gt; :none | :optional | :required,
  optional(:group) =&gt; atom()
}
```

# `all`

```elixir
@spec all() :: %{required(name()) =&gt; spec()}
```

Every operation: built-ins under the host's `:image_operations`.

# `fetch`

```elixir
@spec fetch(name()) :: {:ok, spec()} | :error
```

One operation's spec.

# `label`

```elixir
@spec label(name()) :: String.t()
```

The translated label of a built-in operation (its `description` for a
host-defined one). The literals here are what the extractor sees, so
every built-in name lands in the catalogue.

# `names`

```elixir
@spec names() :: [name()]
```

Operation names, built-ins first.

# `normalize`

```elixir
@spec normalize([term()]) ::
  {:ok, [{name(), params()}]}
  | {:error,
     {:unknown_operation, term()}
     | {:missing_parameter, name(), atom()}
     | {:conflicting_operations, name(), name()}}
```

Turns the caller's list into `[{name, params}]`.

Accepts atoms (`:enhance`), tuples with keyword or map parameters
(`{:relight, light: :night}`), bare strings (a free-form instruction),
and `{:custom, "text"}`. Unknown names, missing parameters and two
operations from one exclusive group (two background treatments, say)
are errors before anything is sent.

# `options`

```elixir
@spec options([{name(), params()}]) :: map()
```

The request options the operations imply (later operations win).

# `references_required?`

```elixir
@spec references_required?([{name(), params()}]) :: boolean()
```

Whether any operation in the list needs reference images.

# `render`

```elixir
@spec render(name(), params(), keyword()) :: {:ok, String.t()} | {:error, term()}
```

The sentence(s) for one operation. `fallback: true` picks the
operation's fallback wording (its implied options were not available).
A saved prompt whose slug is `image-op-<name>` (a prompt named
"Image op <name>") overrides the template unless
`prompt_overrides: false`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
