Per-provider URL builders.
Projects a canonical Image.Plug.Pipeline.t/0 onto the URL
grammar of each supported provider. This is the inverse of the URL
parsers in image_plug's provider modules: those parsers
consume URLs and produce a Pipeline; these builders go the
other way — Pipeline → provider-specific URL string.
Five providers are supported: four commercial image CDNs (Cloudflare Images, Cloudinary, imgix, ImageKit) plus IIIF Image API 3.0, the open standard implemented by cultural-heritage and academic image servers (Cantaloupe, Loris, IIPImage, Wellcome, Library of Congress, …). The same IR drives all five grammars, so an option set produces five URLs with comparable semantics — modulo the per-provider feature gaps.
Coverage
Implements the round-trip subset shared by the five providers:
resize (width/height/fit/gravity/dpr), format/quality,
blur/sharpen, brightness/contrast/saturation/gamma, rotate,
trim, background, plus IIIF-specific region and named-quality
(gray/bitonal) tokens. Operations not natively expressible
in a given provider's URL grammar are dropped silently and
documented in the corresponding image_plug provider's
conformance guide.
Provider semantic differences
The five providers do not all express adjust effects the same way:
Cloudflare takes brightness/contrast/saturation/gamma as raw multipliers (the same units as the IR;
1.0= no change).Cloudinary and imgix take centred percentages in
-100..100, where0= no change. The builders below convert: an IR value of1.4becomese_contrast:40for Cloudinary andcon=40for imgix.ImageKit has only an unparameterised
e-contrasttoggle (auto-contrast). Brightness/contrast/saturation/ gamma multipliers cannot be faithfully expressed in ImageKit URL form, so they are silently dropped — no approximation, by design. Seeguides/imagekit_conformance.mdinimage_plug.IIIF has no parameterised adjust effects at all. Only
Adjust{saturation: 0.0}round-trips, via thegrayquality token in the URL's quality segment; everything else (brightness, contrast, gamma, non-zero saturation) is silently dropped. Seeguides/iiif_conformance.mdinimage_plug.
Examples
iex> alias Image.Plug.Pipeline
iex> alias Image.Plug.Pipeline.Ops
iex> p = %Pipeline{ops: [%Ops.Resize{width: 600}], output: %Ops.Format{type: :webp, quality: 80}}
iex> Image.Components.URL.cloudflare(p, source_path: "/sample.jpg")
"/cdn-cgi/image/width=600,format=webp,quality=80/sample.jpg"
Summary
Functions
Projects the pipeline onto the Cloudflare Images URL grammar: <host>/cdn-cgi/image/<options>/<source>.
Projects the pipeline onto the Cloudinary URL grammar: <host>/<account>/image/upload/<options>/<source>.
Projects the pipeline onto the IIIF Image API 3.0 URL grammar: <host><prefix>/<identifier>/<region>/<size>/<rotation>/<quality>.<format>.
Builds the URL of an IIIF identifier's info.json discovery
document.
Projects the pipeline onto the ImageKit URL grammar: <host>/<endpoint>/tr:<options>/<source>.
Projects the pipeline onto the imgix URL grammar: <host>/<source>?<options>.
Types
@type options() :: keyword()
Per-builder options, shared across the four projectors.
:source_path— the URL-relative source path. Cloudflare, Cloudinary, and ImageKit append this after the options segment; imgix prepends it before the query string. Defaults to"/sample.jpg".:host— when supplied, prepended verbatim (e.g."https://playground.example.com"or just"/img"to scope under a path). Default""— relative URL.:cloudinary_account— Cloudinary's<cloud-name>segment. Default"demo".:imagekit_endpoint— ImageKit's per-account endpoint segment. Default"demo".
Functions
@spec cloudflare(Image.Plug.Pipeline.t(), options()) :: String.t()
Projects the pipeline onto the Cloudflare Images URL grammar: <host>/cdn-cgi/image/<options>/<source>.
Arguments
pipelineis anImage.Plug.Pipeline.t().optionsis a keyword list — see the Options section.
Options
:source_pathis the URL-relative source path. Defaults to"/sample.jpg".:hostis prepended verbatim — e.g."https://playground.example.com"or"/img"to scope under a path. Defaults to""(relative URL).
Returns
- The projected URL as a string. Cloudflare requires at least one option; when the pipeline projects to nothing,
format=auto(a no-op) is emitted.
Examples
iex> alias Image.Plug.Pipeline
iex> alias Image.Plug.Pipeline.Ops
iex> p = %Pipeline{ops: [%Ops.Resize{width: 200}], output: nil}
iex> Image.Components.URL.cloudflare(p, source_path: "/abc.jpg")
"/cdn-cgi/image/width=200/abc.jpg"
@spec cloudinary(Image.Plug.Pipeline.t(), options()) :: String.t()
Projects the pipeline onto the Cloudinary URL grammar: <host>/<account>/image/upload/<options>/<source>.
Arguments
pipelineis anImage.Plug.Pipeline.t().optionsis a keyword list — see the Options section.
Options
:source_pathis the URL-relative source path. Defaults to"/sample.jpg".:hostis prepended verbatim. Defaults to""(relative URL).:cloudinary_accountis the<cloud-name>segment. Defaults to"demo".
Returns
- The projected URL as a string. When the pipeline projects to no options, the
tr:segment is omitted and the URL collapses to<host>/<account>/image/upload/<source>.
Examples
iex> alias Image.Plug.Pipeline
iex> alias Image.Plug.Pipeline.Ops
iex> p = %Pipeline{ops: [%Ops.Resize{width: 200}], output: nil}
iex> Image.Components.URL.cloudinary(p, source_path: "/abc.jpg")
"/demo/image/upload/w_200/abc.jpg"
@spec iiif(Image.Plug.Pipeline.t(), options()) :: String.t()
Projects the pipeline onto the IIIF Image API 3.0 URL grammar: <host><prefix>/<identifier>/<region>/<size>/<rotation>/<quality>.<format>.
Arguments
pipelineis anImage.Plug.Pipeline.t().optionsis a keyword list — see the Options section.
Options
:source_pathis the URL-relative source path used as the IIIF identifier. Leading/is stripped; embedded/characters are percent-encoded as%2Fper the spec. Defaults to"/sample.jpg".:hostis prepended verbatim — e.g."https://iiif.example.org"or""for a relative URL.:iiif_prefixis the server's IIIF version prefix (the/{prefix}segment in the spec). Typical values:"/iiif/3"for an Image API 3.0 server,"/cantaloupe/iiif/3"for Cantaloupe deployments. Defaults to"/iiif/3".:iiif_formatis the format extension used when the pipeline's outputFormat.typeis:auto(IIIF requires an explicit format in the URL). Defaults to:jpeg.
Returns
- The projected URL as a string. The five positional segments are always emitted:
region,size,rotation,quality.format. A pipeline with no transforms produces<host>/iiif/3/<id>/full/max/0/default.jpg.
Conformance gaps
IIIF's URL grammar is narrower than the IR. The following ops project to default / max / full rather than the requested transform — see guides/iiif.md (in image_plug) for the per-op detail:
Resize{fit: :cover}— IIIF cannot express "scale-to-fill plus centred crop" in one URL. Drop and use:containor:squeezeinstead, or supply an explicitCropop for the region you want.Blur,Sharpen,Vignette,Tint,Background, non-grayscaleAdjust,face_zoom,gravity— silently dropped. The IIIF spec scopes to a small set of geometric and quality transforms; effects are out of scope.
Examples
iex> alias Image.Plug.Pipeline
iex> alias Image.Plug.Pipeline.Ops
iex> p = %Pipeline{ops: [%Ops.Resize{width: 600}], output: %Ops.Format{type: :jpeg, quality: 80}}
iex> Image.Components.URL.iiif(p, source_path: "/cat.jpg", host: "https://iiif.example.org")
"https://iiif.example.org/iiif/3/cat.jpg/full/^600,/0/default.jpg"
iex> alias Image.Plug.Pipeline
iex> Image.Components.URL.iiif(%Pipeline{ops: [], output: nil}, source_path: "/cat.jpg")
"/iiif/3/cat.jpg/full/max/0/default.jpg"
Builds the URL of an IIIF identifier's info.json discovery
document.
This is the entry point a deep-zoom viewer (OpenSeadragon, Mirador,
Leaflet-IIIF) reads to discover the source dimensions, available
tile sizes, supported features, and rendering profile. It is also
the canonical IIIF identity URL — the same URL appears as id in
the info.json body.
Arguments
optionsis a keyword list — see the Options section.
Options
:source_pathis the URL-relative source path used as the IIIF identifier. Default"/sample.jpg".:hostis prepended verbatim. Default"".:iiif_prefixis the server's IIIF version prefix. Default"/iiif/3".
Returns
- The URL of the
info.jsondocument as a string.
Examples
iex> Image.Components.URL.iiif_info_url(source_path: "/cat.jpg", host: "https://iiif.example.org")
"https://iiif.example.org/iiif/3/cat.jpg/info.json"
iex> Image.Components.URL.iiif_info_url(source_path: "/sub/cat.jpg")
"/iiif/3/sub%2Fcat.jpg/info.json"
@spec imagekit(Image.Plug.Pipeline.t(), options()) :: String.t()
Projects the pipeline onto the ImageKit URL grammar: <host>/<endpoint>/tr:<options>/<source>.
Arguments
pipelineis anImage.Plug.Pipeline.t().optionsis a keyword list — see the Options section.
Options
:source_pathis the URL-relative source path. Defaults to"/sample.jpg".:hostis prepended verbatim. Defaults to""(relative URL).:imagekit_endpointis the per-account endpoint segment. Defaults to"demo".
Returns
- The projected URL as a string. When the pipeline projects to no options, the
tr:segment is omitted and the URL collapses to<host>/<endpoint>/<source>.
Examples
iex> alias Image.Plug.Pipeline
iex> alias Image.Plug.Pipeline.Ops
iex> p = %Pipeline{ops: [%Ops.Resize{width: 200}], output: nil}
iex> Image.Components.URL.imagekit(p, source_path: "/abc.jpg")
"/demo/tr:w-200/abc.jpg"
@spec imgix(Image.Plug.Pipeline.t(), options()) :: String.t()
Projects the pipeline onto the imgix URL grammar: <host>/<source>?<options>.
Arguments
pipelineis anImage.Plug.Pipeline.t().optionsis a keyword list — see the Options section.
Options
:source_pathis the URL-relative source path. Defaults to"/sample.jpg".:hostis prepended verbatim. Defaults to""(relative URL).
Returns
- The projected URL as a string. When the pipeline projects to no options, the
?…query string is omitted and only<host><source>remains.
Examples
iex> alias Image.Plug.Pipeline
iex> alias Image.Plug.Pipeline.Ops
iex> p = %Pipeline{ops: [%Ops.Resize{width: 200}], output: nil}
iex> Image.Components.URL.imgix(p, source_path: "/abc.jpg")
"/abc.jpg?w=200"