A step (Storehouse.Analyzer) that makes what a page shows while a
photograph loads, under "placeholder":
"placeholder"- a tiny version of it, a few hundred bytes, as a data URI the browser stretches into a soft blur: a<img>'s background, or React'splaceholder."color"- its average colour,#rrggbb, painted under it."width"and"height"- the tiny version's, its proportions.
# mix.exs: libvips, through Vix.
{:vix, "~> 0.31"}
Storehouse.store(upload.path, analyze: [Storehouse.Analyzer.Placeholder])It is made with libvips, shrinking as it loads: a 6000 × 4000 JPEG is decoded at an eighth of its size or less, never whole, in about 150 ms where decoding it whole takes 260, and a few kilobytes past what the decoder holds. It is turned as its EXIF says, in sRGB. A file libvips does not read (one that is not an image; HEIC, where libvips is built without its codec) is skipped, or fails the step, with why: the photograph still shows, on its page's ground.
Options
:size- the longest edge, in pixels. The default is 16: larger is sharper, and heavier.:format-:webp(the default),:jpegor:png.:quality- 1 to 100, for WebP and JPEG. The default is 40.:background-"#rrggbb": a photograph with transparency is laid on it, and its colour taken so. The default keeps its transparency (in WebP and PNG; JPEG has none, and is laid on white).
In a page
<img src={@photo.url} width={@photo.width} height={@photo.height}
style={"background: #{analyzed.color} url(#{analyzed.placeholder}) center / cover"} />and in JSON, for a React <img> (Storehouse.File.to_map(file, analysis: [:placeholder])).
For a frontend that decodes a hash instead, Storehouse.Analyzer.ThumbHash
and Storehouse.Analyzer.BlurHash.