Docs / Watermarking

Watermarking v0.2.0

The watermark is the last thing drawn on the image: after cropping, sizing and padding and filters, right before the result is encoded.

Raster transform order
  1. Autorotate
    / rotate
  2. Crop
  3. Size × DPR
    × scale
  4. Fit
    / gravity
  5. Pad
  6. Filters
  7. Watermark

You can add one to a single response with the watermark parameter, or turn on a default mark for everything in config.toml. The condensed tables are in the watermark quick reference.

Watermark parameter

Write it as key:value pairs joined with |. Keys are case-sensitive, and anything you leave out falls back to the [watermark] configuration.

/photo.jpg?watermark=image:marks/logo.png|anchor:bottom-right|opacity:60|pad:20
/photo.jpg?watermark=text:Preview|font:Arial|size:42|color:ffffff|anchor:center|rot:-20
image

Image mark. A path from the request can't leave the data directory.

text

Text mark, used when the request doesn't give an image.

anchor

Places a single mark, or tiles it across the image.

opacity

Opacity of the mark, in percent.

pad padding

Distance from the edge, or the space around each tile when repeating.

rot rotate

Rotates the mark.

scale

Scales an image mark. max_scale is applied afterwards.

font

Font for a text mark. It has to be installed on the server.

size

Font size for a text mark.

color

Colour of a text mark.

Colours can be white, ff8a1f, rgb(255,138,31) and so on. Leave out the # on hex colours, since the browser would treat the rest of the URL as a fragment. URL-encode any text that comes from users; a | in it would start a new segment.

watermark=false switches off a configured watermark for one request. A parameter with only styling keys, like watermark=opacity:60, draws nothing unless the configuration supplies an image or text.

Image and text sources

picturium uses the first of these that’s set:

  1. image from the request
  2. text from the request
  3. watermark.image.path from the configuration
  4. watermark.text.text from the configuration

Request values always beat configuration, so a request text replaces a configured image. When the request (or the configuration) provides both an image and text, the image wins.

An image path from the request is resolved under data.dir and can’t escape it. The configured watermark.image.path is set by you, the operator, so it isn’t restricted and can point to a separately mounted file.

/photo.jpg?watermark=image:marks/brand.png|scale:0.75
/photo.jpg?watermark=text:Internal|color:ff8a1f|size:36

Position, padding, and scale

anchor accepts:

center · repeat · top · right · bottom · left · top-left · top-right · bottom-left · bottom-right

For a single mark, padding is the distance from the edge it’s anchored to. With anchor:repeat, the mark is tiled from the top-left corner and the padding becomes empty space around each tile.

/photo.jpg?watermark=image:mark.png|anchor:top-left|padding:12,24
/photo.jpg?watermark=text:Draft|anchor:repeat|padding:30|opacity:18|rot:-30

A mark that’s too big gets scaled down, keeping its proportions. watermark.max_scale limits its width and height to a fraction of the final image, and padding eats into that space too. Padding, image scale and text size from the request are all multiplied by dpr.

Configuration defaults

Configure an image or a text before you turn the global watermark on. picturium won’t start with enabled = true and no source.

[watermark]
enabled = true
position = "bottom-right"
opacity = 50
padding = "16"
rotate = 0
max_scale = 0.25

[watermark.image]
path = "/opt/picturium/marks/brand.png"
scale = 1.0

For a text watermark, swap the image table for:

[watermark.text]
text = "Preview"
font_family = "Arial"
font_size = 24
font_color = "white"

opacity has to be between 0 and 100, image.scale above zero, and max_scale above zero and at most 1. An invalid value, an unparseable text colour, or an enabled watermark with no source all stop picturium from starting. Every key and default is in the [watermark] config reference.

Processing behaviour

The mark is drawn on every frame of an animated image or video clip and on every rendered page of a document. Since it comes after filters, filter= doesn’t change its colour or opacity.

No watermark is added when picturium returns the source file with original=true, or a document with f=pdf or f=svg. JPEG, PNG, WebP, GIF, AVIF and JXL output all get it. An animated watermark image only contributes its first frame.