Skip to content

Images

Images carry a page more than any decoration: the product, the place, the people, the brand. This page covers the image element — fixed artwork and image fields — how it fills its box, how to crop it into a shape, how to keep text readable over a photo, and how to put a photo behind a whole page. As on every technique page, each technique is shown in the editor and in the document.

Every example is in the image lab, a two-page template: the first page shows the techniques side by side, the second a full-page background.

The image lab: fit, fill and stretch; image fields aligned to the top and centre; circle and rounded frames, zoom; an opacity mask, a veil under text, an SVG badge; and a page with a background photo

The src of an image — or the value of an image field — can be:

Source Example Notes
A Madoo storage path the path returned by an upload The right choice for a template that will be shared or published: stored images travel with the template
An HTTPS URL https://images.example.com/courtyard.jpg Fetched at render time; it must stay reachable. Plain HTTP is rejected
A data URI data:image/png;base64,…, data:image/svg+xml;base64,… Small images such as a generated badge or a logo

Photos in PNG, JPEG, WebP or GIF; SVG is accepted too, and prints as vectors at its own proportions — useful for logos and badges produced by a workflow. A single image may be up to 20 MiB, and a render up to 100 MiB of images in total.

To bring a file into Madoo, upload it (upload_asset in MCP, POST /api/v1/assets in REST); list_assets finds files already there. See Assets.

An image has a box (left, top, width, height) and a fitMode that decides how the picture meets it.

fitMode What happens Use it for
fit The whole picture is shown, as large as the box allows; the rest of the box stays empty Logos, badges, product cut-outs, anything that must never be cropped
fill The picture covers the box; what exceeds is cropped Photos — the usual choice
stretch The picture takes exactly the box, distorted if the proportions differ Almost never: only textures and patterns
{ "$type": "image", "id": "5c0de444-0000-4000-8000-000000000101", "name": "Hero photo",
"left": 40, "top": 40, "width": 515, "height": 300,
"src": "https://images.unsplash.com/photo-1507842217343-583bb7270b66?w=1200", "fitMode": "fill" }

With fill, a fixed image is cropped around its centre. To keep another part of it — a face near the top, a product on the right — give it a frame with a focal point (see Frames), or make it a field and choose an alignment.

In the editor

Choose Add image in the tool bar on the left and click on the page, then Add image (or Replace image) in the image bar to upload a PNG, JPEG, WebP or GIF. Image options chooses Photo fit: Fit, Fill or Stretch. An SVG file is imported as editable vector artwork rather than as a picture — see the vector artwork page.

An image becomes a field with a placeholder of type image: its picture comes from data. The field carries its own fitMode and an alignment — top_left, top_center, top_right, center_left, center, center_right, bottom_left, bottom_center, bottom_right — which decides which part of the box the picture keeps:

  • with fill, the alignment is the part of the photo that survives the crop: top_center keeps the heads of a portrait, bottom_center the feet of a product on a floor;
  • with fit, it is where the picture sits in the box: top_center puts a logo at the top of its space, center_left aligns it with the text on its left.
{ "$type": "image", "id": "5c0de444-0000-4000-8000-000000000102", "name": "Speaker portrait",
"left": 40, "top": 220, "width": 160, "height": 110, "src": "", "fitMode": "fill",
"placeholder": { "id": "5c0de444-0000-4000-8000-000000000103", "name": "Speaker portrait",
"code": "portrait", "placeholderType": "image", "required": true,
"fitMode": "fill", "alignment": "top_center",
"description": "A portrait photo; the face in the upper half." } }

Say in the field’s description what picture is expected and where its subject is: it is what a person or an agent reads when preparing the data. A workflow that generates the picture should generate it in the proportions of the box.

In the editor

Choose Add image placeholder in the tool bar, or select an image and choose Make Placeholder from the … menu of its action bar. In the dialog, with Value type Image, set Fit Mode and click a cell of the Alignment grid.

A frame crops an image into a shape — a circle for a portrait, rounded corners for a card, any closed vector path — and places the picture inside it independently of the box. It is written as two properties:

  • clipPath — the shape, as an SVG path in points relative to the image’s top-left corner;
  • frame — how the picture sits in the shape: focalX and focalY (0–1, the point of the picture kept in view: 0.5/0.3 keeps the upper middle), scale (zoom, 1 = the picture just covers the shape), offsetX / offsetY (points), rotation (degrees), and an inside border with strokeColor and strokeWidth.

A circular portrait, 110 × 110, keeping the face:

{ "$type": "image", "id": "5c0de444-0000-4000-8000-000000000104", "name": "Round portrait",
"left": 65, "top": 370, "width": 110, "height": 110, "fitMode": "fill",
"src": "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=800",
"frame": { "focalX": 0.5, "focalY": 0.3, "scale": 1, "offsetX": 0, "offsetY": 0, "rotation": 0 },
"clipPath": { "units": "user_space_on_use", "transform": [], "shapes": [
{ "pathData": "M 55 0 A 55 55 0 1 1 55 110 A 55 55 0 1 1 55 0 Z", "fillRule": "non_zero",
"transform": [], "opacity": 1, "luminance": 1, "color": "#000000" } ] } }
  • Rounded corners: a path with quadratic corners — for a 160 × 110 card with radius 18: M 18 0 H 142 Q 160 0 160 18 V 92 Q 160 110 142 110 H 18 Q 0 110 0 92 V 18 Q 0 0 18 0 Z.
  • Zoom on a detail: the same frame with "scale": 1.8 and a focal point on the subject.
  • A border that follows the shape: "strokeColor": "#e9c46a", "strokeWidth": 4 in frame — drawn inside the shape.
  • An image field can have a frame too: every picture the data brings is cropped into the same shape — the way to give every card of a list the same rounded photo.

In the editor

Select the image and choose Crop / mask: pick a Mask shape (rectangle, ellipse, circle, triangle, diamond, star), drag inside to move the photo, use Mask handles or Photo handles to resize one or the other, edit the contour’s points, then Done. Any rectangle, ellipse or vector path you drew becomes a frame too: select it and choose Use as image frame, or select it together with the image and choose Use shape as frame. The border is under Image options (Border width, Border color); Remove mask releases the image.

An opacity mask makes part of an image transparent: outside the mask the image disappears, inside it keeps the mask shape’s opacity. A soft oval vignette, a photo that fades into the page:

"opacityMask": { "units": "user_space_on_use", "contentUnits": "user_space_on_use",
"x": 0, "y": 0, "width": 160, "height": 110, "transform": [],
"shapes": [ { "pathData": "M 80 0 A 80 55 0 1 1 80 110 A 80 55 0 1 1 80 0 Z", "fillRule": "non_zero",
"transform": [], "opacity": 0.6, "luminance": 1, "color": "#ffffff" } ] }

The mask is vector: it stays sharp in the PDF.

In the editor

Select the image together with a closed shape and choose Use shape as alpha mask.

Text directly on a photo is readable only where the photo happens to be dark or plain. Put a veil between them: a rectangle in the ink color at 50–70% opacity, over the part of the photo that holds the text — or a gradient from transparent to dark, for a softer edge. Then white or light text on the veil.

{ "$type": "rectangle", "id": "5c0de444-0000-4000-8000-000000000105", "name": "Veil",
"left": 0, "top": 520, "width": 595, "height": 322, "fill": "#0b1f33", "opacity": 0.7 }

Elements are painted in order: the photo first, the veil, then the text.

A page can have a background image above its background color or gradient. It always covers the page from edge to edge and sits behind every element.

"backgroundColor": "#0b1f33",
"backgroundImage": { "src": "https://images.unsplash.com/photo-1519681393784-d120267933ba?w=1600",
"fitMode": "cover", "focalX": 0.5, "focalY": 0.3, "scale": 1 }
  • fitMode: cover fills the page and crops the edges; contain shows the whole picture, with the background color around it; stretch distorts it to the page.
  • focalX / focalY choose the part kept in view; scale (0.25–4) enlarges or reduces it — below 1 it reveals the color underneath.
  • Transparent areas of a PNG show the background color or gradient.

A background image is part of the design, not a field. For a background that changes with the data, place an image field covering the whole page as the first element instead.

In the editor

Open Page settings from the page thumbnails. Under Background, Image overlay (optional) uploads the picture; Fit to page chooses Fill page (crop edges), Show whole image or Stretch to page; Image size scales it; drag the picture in the small preview to position it.

A QR code on a page is an image field fed by the QR Code & Barcode node (image/code) of the workflow. Connect its svg output to the field: the code stays vector in the PDF and prints sharp at any size. In a workflow that makes one document per item (a badge per participant, a label per product), put the node after the enumerator — every item gets its own code, as in the F13 event badges.

  • Style: module shape (square, rounded, circle, dots, diamond, heart, star), eye frame and eye ball shapes, code, eye and background colours, an optional centre logo (SVG, PNG or JPEG). A white or light logo needs Logo Background (square, rounded, circle): a plate behind it, in the code colour unless you choose another.
  • It always scans: the node decodes every code it draws; a style that stops it from scanning — a pale colour, a logo too large — fails the node instead of reaching the printer. Its check output says what was read.
  • In the editor, the node’s panel shows the code above its parameters, redrawn as you change them, with whether it scans. It is the run’s own drawing (nothing is stored, no credits); without content yet it shows a sample, and a logo computed during the run is left out of the preview.
  • In the template: an image field with fit, square, at least 2 cm on paper (80 points), with white or a light colour around it; the node’s quiet zone (4 modules) is the margin scanners need.
  • A frame with “Scan me” is part of the template, not of the code — see Frames around a QR code.
  • To hand the code over as a file, connect it to an Image Output (output/image): format original keeps the svg output vector (a .svg for the printer or the designer); png, jpg or webp convert it.

The same node draws barcodes: set Symbology to ean13 or code128.

Symbology Use it for Content
ean13 Retail products: packaging, shelf and price labels 12 digits — the check digit is added — or 13, when the check digit is verified; spaces and dashes are ignored
code128 Labels, tickets, logistics: an order, a SKU, a lot, a badge ID Letters, digits and symbols (printable ASCII), up to 48 characters
  • It always scans, as a QR code: the drawn barcode is read back and must give the content (an EAN-13 gives its 13 digits). A wrong check digit is refused with the right one — the check digit of ‘5901234123458’ should be 7.
  • The human-readable line (on by default, Human-Readable Text) is drawn under the bars as vector outlines: the SVG carries no font, so it prints the same in any PDF, a PDF/X print file included. An EAN-13 follows the GS1 layout — the first digit left of the bars, two groups of six, the guard bars running down into the digits.
  • Size and margins: the usual height is kept (69 modules for an EAN-13), Bar Height changes it; the standard quiet zones are always drawn (11 and 7 modules for EAN-13, 10 for Code 128). Code and background colours apply as for QR codes; shapes, logos and error correction are for QR codes only.
  • In the template: an image field with fit, as wide as the barcode needs — an EAN-13 is about 37 mm wide at its nominal size (100%), and should not print below 80% of it; keep white around it.

A sticker frame — a banner that says SCAN ME, a speech bubble, a ticket — is drawn in the template around the image field, in the brand’s fonts and colours; the code itself stays plain, so it always scans. The QR frames lab has six frames fed by three fields: qr (the image), call_to_action (the text) and frame_color (a colour field on every coloured shape). Its two sample sets show the same page in two brands:

The QR frames lab in coral with SCAN ME and in navy with SEE THE MENU: A a banner below the code, B a tab above, C a speech bubble with the text under its pointer, D a round badge, E a ticket with a dashed perforation and two notches, F a phone with the code on its screen

Frame How it is built
A Banner below A coloured rounded rectangle; a white rounded card inside it with the code; the call to action in white on the colour under the card
B Tab above A coloured border (a rounded rectangle with a white one inside), and a coloured tab overlapping its top edge with the text
C Speech bubble A coloured rounded square and a triangular path pointing down, both with the colour field; the text in ink under the pointer
D Round badge A coloured circle; a white rounded card inside the circle, the code on it and the text in white below
E Ticket A coloured rounded rectangle; two circles in the page colour cut the notches; a dashed white line is the perforation
F Phone A coloured rounded rectangle is the body, a white one the screen, two small white bars the speaker and the home bar

Frame A:

{ "$type": "group", "id": "9f5a0000-0000-4000-8000-000000000010", "name": "Banner below", "left": 40, "top": 58,
"width": 160, "height": 220, "children": [
{ "$type": "rectangle", "id": "9f5a0000-0000-4000-8000-000000000003", "name": "Frame", "left": 0, "top": 0,
"width": 160, "height": 204, "fill": "#e4572e", "rx": 16, "ry": 16,
"placeholder": { "id": "9f5a0000-0000-4000-8000-000000000004", "name": "Frame colour", "code": "frame_color",
"placeholderType": "color", "required": true, "format": {"colorTarget":"fill"},
"description": "The frame colour, #RRGGBB; white text must read on it." } },
{ "$type": "rectangle", "id": "9f5a0000-0000-4000-8000-000000000005", "name": "Card", "left": 8, "top": 8,
"width": 144, "height": 144, "fill": "#ffffff", "rx": 10, "ry": 10 },
{ "$type": "image", "id": "9f5a0000-0000-4000-8000-000000000006", "name": "QR code", "left": 12, "top": 12,
"width": 136, "height": 136, "src": "", "fitMode": "fit",
"placeholder": { "id": "9f5a0000-0000-4000-8000-000000000007", "name": "QR code", "code": "qr", "placeholderType": "image",
"required": true, "fitMode": "fit", "alignment": "center",
"description": "The QR code: the svg output of the QR Code node, square." } },
{ "$type": "text", "id": "9f5a0000-0000-4000-8000-000000000008", "name": "Call to action", "left": 12,
"top": 164, "width": 136, "height": 30, "text": "SCAN ME", "fontFamily": "Montserrat", "fontSize": 17,
"fontWeight": "bold", "fill": "#ffffff", "charSpacing": 160, "textAlign": "center", "lineHeight": 1.1,
"fixedHeight": 30, "overflowMode": "shrink", "minFontSize": 6,
"placeholder": { "id": "9f5a0000-0000-4000-8000-000000000009", "name": "Call to action", "code": "call_to_action",
"placeholderType": "text", "required": true,
"description": "A short call to action, e.g. \"SCAN ME\" or \"SEE THE MENU\"." } } ] }

What makes a frame work:

  • The code sits on white. Put it on a white or very light card inside the frame, never directly on the frame colour, and keep the node’s quiet zone: the card is decoration, the quiet zone is what the scanner needs.
  • One field, many places. The same code (frame_color) can sit on several shapes when every occurrence has the same contract — name, type, requirement, format — so one value paints the whole frame.
  • One field per element. A text that is the call-to-action field cannot also take its colour from a field: give it a fixed colour that reads on every frame colour — white on the colour, ink on the page.
  • A short call to action that stays inside. Keep it on one line — a fixed height with shrink and a small minFontSize, or grow with maxLines: 1 and beyond: shrink — and keep its box a few points inside the frame’s rounded corners: SEE THE MENU shrinks where SCAN ME fits.
You need Do
A logo that is never cropped fit, aligned to the side of the text it goes with
Product photos on a white background, all the same Image fields with fit and bottom_center alignment: every product stands on the same line
Portraits in a list of speakers An image field with fill, a circle frame and focalY around 0.3
A hero photo with a title on it The photo with fill, a veil rectangle at 60% over the lower part, the title in white on it
A card photo with rounded corners A frame with a rounded path; the same frame on every card
A badge produced by a workflow An image field with fit fed an SVG data URI or file
A barcode on a price label or a shipping label The QR Code & Barcode node with ean13 (a GTIN) or code128 (a SKU, an order), its svg output into an image field with fit
A QR code with SCAN ME in the brand’s colours A frame from the QR frames lab: shapes with a colour field around a square image field fed by the QR Code node
A QR code per participant or product The QR Code node after the enumerator, its svg output into a square image field
A cover with a full-page photo backgroundImage with cover and a focal point on the subject, a veil under the text
  • Photos use fill, logos and cut-outs use fit; nothing important is cropped (check every sample set).
  • Every image field says in its description what picture it expects and where the subject is.
  • Portraits and subjects off-centre have an alignment or a focal point.
  • Text over a photo sits on a veil.
  • Photos are large enough for their printed size (about 1500 px on the long side for half an A4 page).
  • Images of a template that will be shared are in Madoo storage, not on an external URL.