# `PhoenixKit.Modules.Storage.Shape`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.62.1/lib/modules/storage/shape.ex#L1)

The shape of a picture: ordinary, **wide** (a horizontal panorama) or **tall**
(a vertical one, a Pinterest pin).

Shape is read from a file's `aspect_ratio` (width ÷ height, kept by Postgres,
V212), never from EXIF: no camera flag is involved, and an edit that crops or
rotates the photo changes its shape with no job to keep a flag right. Where wide
stops and panorama starts is a taste, so the two thresholds live here and are
the one place to change (a per-user setting would replace these constants):

  * **wide**: `aspect_ratio >= 2.0` (2:1 or wider);
  * **tall**: `aspect_ratio <= 0.5` (1:2 or taller; a phone screenshot, at
    about 1:2.16, counts as tall).

## Filtering

    Shape.filter(File, :wide)           # or :tall; nil / "all" leave it alone
    Storage.list_files_in_scope(nil, shape: :wide)

A file with no usable size (`aspect_ratio` nil) is neither.

# `t`

```elixir
@type t() :: :wide | :tall | :normal
```

# `classify`

```elixir
@spec classify(number() | {integer(), integer()} | map() | nil) :: t() | nil
```

The shape of a ratio, a `{width, height}` pair or anything carrying them (a
file); `nil` when there is no usable size.

# `filter`

```elixir
@spec filter(Ecto.Queryable.t(), t() | String.t() | nil) :: Ecto.Query.t()
```

Narrows a query over files (or anything with an `aspect_ratio`) to a shape.
`nil`, `"all"` and `""` leave it unfiltered; `:wide`/`"wide"` and
`:tall`/`"tall"` filter; anything else raises, so a typo is not silently
"no filter".

# `megapixels`

```elixir
@spec megapixels(integer() | nil, integer() | nil) :: float()
```

A size in megapixels to one decimal: 4032 × 3024 is `12.2`. `0.0` without a usable size.

# `tall_max`

```elixir
@spec tall_max() :: float()
```

The largest `aspect_ratio` of a tall picture.

# `wide_min`

```elixir
@spec wide_min() :: float()
```

The smallest `aspect_ratio` of a wide picture.

---

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