Encodes an image as an LQIP CSS (Low Quality Image Placeholder) value.
LQIP CSS represents a placeholder as a single 32-bit value packed into an RGBA
hex code such as #a1b2c3d4. A static CSS rule then unpacks that value into
three colors and paints two radial gradients over a background color, producing
a blurred gradient placeholder using only the browser's CSS engine.
This module is the encoder only: it extracts the three colors and returns the packed hex string. The CSS is static and identical for every image.
See the LQIP CSS guide for the copy-and-paste stylesheet.
How it works
The image is resized to a 3x3 thumbnail and three pixels are sampled:
- the top-left pixel becomes the background color (
--lqip-c0) - the center pixel becomes the first radial gradient (
--lqip-c1) - the bottom-right pixel becomes the second radial gradient (
--lqip-c2)
Each color is quantized (adjusted for chroma)
and bit-packed: the first two into 11 bits (RRRR GGGG BBB) and the third
into 10 bits (RRR GGGG BBB). They are then combined into a single 32-bit
value rendered as an 8-digit #RRGGBBAA hex string.
Usage
Compute the value once and store it. Then set a CSS variable using inline styles or use a data attribute, and include the LQIP CSS stylesheet:
hex = Image.Lqip.Css.encode!(image)
# => "#a1b2c3d4"
# In your template:
# <img src="photo.jpg" style="--lqip: #a1b2c3d4" />
# or
# <img src="photo.jpg" data-lqip="#a1b2c3d4" />See the LQIP CSS guide for more usage information.
Chroma-aware packing
Because each channel is packed into only 3 or 4 bits, independent per-channel
rounding can give near-grey colors a visible tint. To reduce that, the encoder
chooses each color's packed value to be the one closest to the source in the
CIELAB space, measured with CIEDE2000 (via Color.Distance.delta_e_2000/3).
This keeps near-greys closer to neutral while still preserving chroma for saturated colors.
Example
iex> image = Image.open!("./test/support/images/Kip_small.jpg")
iex> Image.Lqip.Css.encode(image)
{:ok, "#22333091"}
Summary
Operations
Encodes an image as a packed LQIP hex value.
Encodes an image as a packed LQIP hex value, or raises on error.
Operations
@spec encode(image :: Vix.Vips.Image.t()) :: {:ok, String.t()} | {:error, Image.error()}
Encodes an image as a packed LQIP hex value.
Arguments
imageis anyVix.Vips.Image.t/0. It is converted to the:srgbcolorspace before sampling, and any alpha channel is ignored.
Returns
{:ok, hex}wherehexis an 8-digit#RRGGBBAAstring, or{:error, reason}
Example
iex> image = Image.open!("./test/support/images/Kip_small.jpg")
iex> Image.Lqip.Css.encode(image)
{:ok, "#22333091"}
@spec encode!(image :: Vix.Vips.Image.t()) :: String.t() | no_return()
Encodes an image as a packed LQIP hex value, or raises on error.
See encode/1.