# `Image.Plug.FaceAware`
[🔗](https://github.com/elixir-image/image_plug/blob/v0.1.0/lib/image/plug/face_aware.ex#L1)

Face-aware crop, zoom, and pixelation, gated on the optional
[`:image_vision`](https://hex.pm/packages/image_vision)
dependency.

This is the single seam between `image_plug` and
`Image.FaceDetection`. The interpreter calls
`available?/0` to decide whether to do face-aware work or
fall back to today's saliency-based behaviour
(libvips' `:attention` crop). Without `:image_vision` in
the consumer's deps, every function in this module returns
`{:error, :unavailable}` and the interpreter routes around
it transparently.

## Used by

* `Resize{gravity: :face, face_zoom: ...}` — pre-crops the
  image to the most prominent face plus padding before the
  regular thumbnail resize pass.

* `PixelateFaces` — detects faces and pixelates only those
  regions, preserving the rest of the image.

Maps to Cloudflare `face-zoom`, ImageKit `z-`, Cloudinary
`gravity=face` / `e_pixelate_faces`, and imgix `crop=faces`.

# `available?`

```elixir
@spec available?() :: boolean()
```

Returns `true` if `Image.FaceDetection` is loaded — i.e. if
the consumer added `:image_vision` to their deps.

Cheap to call; checked on every Resize that asks for
`gravity: :face`.

# `face_crop`

```elixir
@spec face_crop(Vix.Vips.Image.t(), float()) ::
  {:ok, Vix.Vips.Image.t()} | {:error, :no_face | :unavailable}
```

Crops the image to the largest detected face, expanded by
padding derived from `face_zoom`.

### Arguments

* `image` is any `t:Vix.Vips.Image.t/0`.

* `face_zoom` is a float in `[0.0, 1.0]`:
  * `0.0` → loose crop with lots of context around the face
    (`padding = 1.0`).
  * `1.0` → tight crop hugging the face bounding box
    (`padding = 0.0`).
  * `0.6` (Cloudflare's default) → moderate zoom
    (`padding = 0.4`).

### Returns

* `{:ok, cropped_image}` on success.

* `{:error, :no_face}` if no face was detected at the
  default confidence threshold.

* `{:error, :unavailable}` if `Image.FaceDetection` isn't
  loaded.

# `pixelate_faces`

```elixir
@spec pixelate_faces(Vix.Vips.Image.t(), float()) ::
  {:ok, Vix.Vips.Image.t()} | {:error, :unavailable | term()}
```

Pixelates the regions of an image occupied by detected
faces, leaving the rest of the image untouched.

Used by Cloudinary's `e_pixelate_faces`.

### Arguments

* `image` is any `t:Vix.Vips.Image.t/0`.

* `scale` is the pixelation scale factor (smaller =
  chunkier blocks). Same convention as `Image.pixelate/2`.

### Returns

* `{:ok, image_with_pixelated_faces}` on success — the
  returned image has the same dimensions as the input.

* `{:ok, image}` (unchanged) when no faces are detected —
  nothing to pixelate.

* `{:error, :unavailable}` if `Image.FaceDetection` isn't
  loaded.

* `{:error, reason}` if `Image.crop/4`, `Image.pixelate/2`, or
  `Image.compose/3` fails when reconstructing the result.

---

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