Etcher.Raster (etcher v0.7.0)

Copy Markdown View Source

Server-side, dependency-free rendering of Etcher annotations to static output.

Etcher renders shapes live (SVG) on the Fresco canvas in the browser. This module is the server counterpart: it turns the same annotation geometry into either ImageMagick convert -draw arguments (to bake shapes into a raster — e.g. an annotated thumbnail) or a standalone SVG string (to overlay shapes on an image without JS).

It is the single source of truth for "Etcher geometry → drawn shape" on the server, mirroring the wire format documented in the README. Pure functions, no system dependencies — the caller owns rasterization (running convert, embedding the SVG, …).

Input

A list of annotation maps as they travel in etcher:annotations-changed / the extensions.etcher blob — %{"kind" => ..., "geometry" => ..., "style" => ...} (string keys; atom keys are also accepted). Unknown or malformed shapes are skipped, so one bad row never breaks a render.

Examples

iex> rect = [%{"kind" => "rectangle", "geometry" => %{"x" => 10, "y" => 20, "w" => 30, "h" => 40}}]
iex> Etcher.Raster.to_draw_args(rect, stroke_width: 4)
["-fill", "none", "-stroke", "#ef4444", "-strokewidth", "4", "-draw", "rectangle 10,20 40,60"]

iex> rect = [%{"kind" => "rectangle", "geometry" => %{"x" => 10, "y" => 20, "w" => 30, "h" => 40}}]
iex> Etcher.Raster.to_svg(rect, width: 100, height: 100)
~s(<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" fill="none"><rect x="10" y="20" width="30" height="40" stroke="#ef4444" stroke-width="2"/></svg>)

Summary

Functions

Normalises annotations into drawing primitives + colour.

Builds ImageMagick convert arguments that draw the annotations' outlines.

Renders the annotations as a standalone <svg> string (outlines only).

Types

annotation()

@type annotation() :: map()

opts()

@type opts() :: keyword()

Functions

primitives(annotations)

@spec primitives([annotation()]) :: [{tuple(), String.t() | nil}]

Normalises annotations into drawing primitives + colour.

Each entry is {primitive, color} where primitive is one of: {:rect, x, y, w, h}, {:circle, cx, cy, r}, {:polygon, points}, {:polyline, points}, {:line, x1, y1, x2, y2} (coords are numbers, points is a list of {x, y}). Exposed so callers can add their own backend.

to_draw_args(annotations, opts \\ [])

@spec to_draw_args([annotation()], opts()) :: [String.t()]

Builds ImageMagick convert arguments that draw the annotations' outlines.

Returns a flat arg list to splice into a convert invocation before any resize/crop, so shapes are drawn in the source image's pixel space (Etcher geometry is in canvas/image pixels) and scale with the image.

Returns [] when there is nothing drawable.

Options

  • :stroke_width — outline width in source pixels (default 2)
  • :default_color — colour for shapes without a style colour (default #ef4444)

to_svg(annotations, opts \\ [])

@spec to_svg([annotation()], opts()) :: String.t()

Renders the annotations as a standalone <svg> string (outlines only).

Suitable as an absolutely-positioned overlay on an image. With preserveAspectRatio="xMidYMid slice" the SVG crops identically to CSS object-cover, so shapes line up with a cover-fit thumbnail.

Returns "" when there is nothing drawable.

Options

  • :width / :height — the source image dimensions for the viewBox (required for correct positioning; default 100)
  • :stroke_width — outline width in viewBox units (default 2)
  • :default_color — colour fallback (default #ef4444)
  • :class — extra class on the <svg> element