Image.Components.URL (image_components v0.1.1)

Copy Markdown View Source

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, where 0 = no change. The builders below convert: an IR value of 1.4 becomes e_contrast:40 for Cloudinary and con=40 for imgix.

  • ImageKit has only an unparameterised e-contrast toggle (auto-contrast). Brightness/contrast/saturation/ gamma multipliers cannot be faithfully expressed in ImageKit URL form, so they are silently dropped — no approximation, by design. See guides/imagekit_conformance.md in image_plug.

  • IIIF has no parameterised adjust effects at all. Only Adjust{saturation: 0.0} round-trips, via the gray quality token in the URL's quality segment; everything else (brightness, contrast, gamma, non-zero saturation) is silently dropped. See guides/iiif_conformance.md in image_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

Types

Per-builder options, shared across the four projectors.

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

options()

@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

cloudflare(pipeline, options \\ [])

@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

  • pipeline is an Image.Plug.Pipeline.t().

  • options is a keyword list — see the Options section.

Options

  • :source_path is the URL-relative source path. Defaults to "/sample.jpg".

  • :host is 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"

cloudinary(pipeline, options \\ [])

@spec cloudinary(Image.Plug.Pipeline.t(), options()) :: String.t()

Projects the pipeline onto the Cloudinary URL grammar: <host>/<account>/image/upload/<options>/<source>.

Arguments

  • pipeline is an Image.Plug.Pipeline.t().

  • options is a keyword list — see the Options section.

Options

  • :source_path is the URL-relative source path. Defaults to "/sample.jpg".

  • :host is prepended verbatim. Defaults to "" (relative URL).

  • :cloudinary_account is 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"

iiif(pipeline, options \\ [])

@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

  • pipeline is an Image.Plug.Pipeline.t().

  • options is a keyword list — see the Options section.

Options

  • :source_path is the URL-relative source path used as the IIIF identifier. Leading / is stripped; embedded / characters are percent-encoded as %2F per the spec. Defaults to "/sample.jpg".

  • :host is prepended verbatim — e.g. "https://iiif.example.org" or "" for a relative URL.

  • :iiif_prefix is 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_format is the format extension used when the pipeline's output Format.type is :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 :contain or :squeeze instead, or supply an explicit Crop op for the region you want.
  • Blur, Sharpen, Vignette, Tint, Background, non-grayscale Adjust, 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"

iiif_info_url(options \\ [])

@spec iiif_info_url(options()) :: String.t()

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

  • options is a keyword list — see the Options section.

Options

  • :source_path is the URL-relative source path used as the IIIF identifier. Default "/sample.jpg".

  • :host is prepended verbatim. Default "".

  • :iiif_prefix is the server's IIIF version prefix. Default "/iiif/3".

Returns

  • The URL of the info.json document 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"

imagekit(pipeline, options \\ [])

@spec imagekit(Image.Plug.Pipeline.t(), options()) :: String.t()

Projects the pipeline onto the ImageKit URL grammar: <host>/<endpoint>/tr:<options>/<source>.

Arguments

  • pipeline is an Image.Plug.Pipeline.t().

  • options is a keyword list — see the Options section.

Options

  • :source_path is the URL-relative source path. Defaults to "/sample.jpg".

  • :host is prepended verbatim. Defaults to "" (relative URL).

  • :imagekit_endpoint is 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"

imgix(pipeline, options \\ [])

@spec imgix(Image.Plug.Pipeline.t(), options()) :: String.t()

Projects the pipeline onto the imgix URL grammar: <host>/<source>?<options>.

Arguments

  • pipeline is an Image.Plug.Pipeline.t().

  • options is a keyword list — see the Options section.

Options

  • :source_path is the URL-relative source path. Defaults to "/sample.jpg".

  • :host is 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"