# Dims
Probe **remote image dimensions** (width × height) from just a URL —
without downloading the image.
Image formats keep their dimensions in the file header, so `Dims`
fetches only the **first ~128 KB via an HTTP Range request**, parses the
JPEG / PNG / WebP / GIF header, and discards the bytes. Milliseconds and
a few KB per image instead of megabytes.
```elixir
Dims.probe("https://cdn.example.com/page1.jpg")
#=> %{width: 800, height: 8000}
Dims.probe_all(urls)
#=> [%{url: ..., width: 800, height: 1200}, ...] # input order preserved
```
Useful anywhere you deal with images you don't host: reserving layout
space (`aspect-ratio`, `<img width height>`) before anything loads,
link previews, gallery imports, comic/manga readers deciding page
layouts, CMS ingestion.
---
## Install
```elixir
def deps do
[
{:dims, "~> 0.1"}
]
end
```
## Batch probing, built for the real world
* **Parallel** — `probe_all/2` sweeps the list with bounded concurrency
(default 8), preserving order.
* **Median backfill** — a probe that fails or times out gets the median
dimensions of its successful siblings, not a constant fallback. Image
sets (chapter pages, galleries) are near-uniform, so the estimate is
close — and relative layouts built from the results never explode.
* **Sampling** — `probe_sampled/2` probes ~20 evenly-distributed URLs
of a huge list and median-fills the rest: accuracy within a percent
or two for uniform sets at ~25× less traffic. `probe_auto/2` switches
between full and sampled by list length (default threshold 80).
* **Caching** — results cache in ETS with a 30-day TTL (a URL's bytes
don't change, so its dimensions don't either). Bypass per call with
`cache: false`.
## Options
```elixir
Dims.probe(url,
headers: [{"referer", "https://source.example/"}], # CDNs that check referers
headers_fun: &MyApp.headers_for/1, # per-URL headers
probe_bytes: 131_071,
receive_timeout: 8_000,
cache: true,
cache_ttl: :timer.hours(24 * 30)
)
```
Batch calls also take `:max_concurrency`, `:sample_size`, and
`:full_threshold`.
## Parsing bytes you already have
`Dims.Parser.parse/1` is the pure header parser — hand it the leading
bytes of an upload or a cached chunk and get `%{width:, height:}` back
with no I/O.
## Formats
JPEG (all SOFn markers, so progressive too), PNG, WebP (VP8 / VP8L /
VP8X), GIF (87a/89a).
## License
MIT