Skip to content

9 min read

A brand look is built from references, seeds and constraints, not adjectives

On this page

The prompt was eleven words when the work started and a hundred and eighty when it stopped. Along the way it had acquired "muted", then "soft muted", then "soft muted editorial palette", then a clause about "restrained Scandinavian minimalism with generous negative space and a warm neutral ground", and finally a parenthetical listing four hex codes. Three weeks of that moved the designer's acceptance rate from 18% to 23%, which is inside the noise of the sample size they were using. The prompt was then replaced with forty words plus one reference image lifted from the brand's existing photography library, and acceptance went to 61% on the next fifty generations.

That result is not a story about the designer's taste. It follows from what the different inputs are wired to inside the model, and once that is clear the sequence of things to try changes completely.

What each knob is actually attached to

A text prompt is encoded into an embedding, a fixed-length list of numbers that stands for the meaning of what you wrote, and that embedding conditions the denoising process — the loop, described in the first chapter, that walks a field of noise toward a picture one step at a time. Conditioning means the embedding is fed in at every one of those steps as the thing the picture is being pulled toward. It is a summary — a few hundred dimensions standing in for everything you wrote — and adding adjectives does not add capacity to that summary so much as redistribute it. Stacking four synonyms for "muted" competes for the same region of the conditioning signal, which is why the twelfth adjective often weakens the effect of the third. Guidance scale is a single number, usually somewhere between 1 and 15, controlling how hard the sampler — the code running that denoising loop — is pushed toward the conditioning at each step, and turning it up increases adherence while flattening variety and, past a point, introducing the over-saturated, over-contrasted look that reads as obviously machine-made.

A reference image — an example picture you send alongside the prompt so the model has the look in front of it rather than described to it — enters differently. Depending on the API it is encoded into the same latent space the image is being built in, the compressed numeric representation the model works in instead of raw pixels, or it conditions the process through an adapter, a small extra network trained for exactly this purpose and bolted onto the main one, and either way it carries orders of magnitude more information about palette, grain, lighting direction and compositional habit than any sentence can. "Text-to-Image: Diffusion, Text Conditioning, Guidance, Latent Space" is worth an hour if you want the mechanism rather than the operating rules, because knowing that the reference is conditioning in image space explains why it dominates the text.

That domination is measurable, and measuring it on your own brand is a better use of a morning than more wording. Hold the prompt fixed, vary the reference strength — the parameter, usually 0 to 1, saying how much of the result the reference is allowed to determine — and score the outputs against the brand's palette by converting both to CIELAB, a colour space arranged so that equal numeric distances look like equal differences to the eye, and taking the mean ΔE of the four nearest matched colours — a perceptual distance where a value under 2 is invisible to most people and over 10 is plainly a different colour.

python
from skimage import color
import numpy as np

BRAND_LAB = color.rgb2lab(np.array([
    [0.98, 0.96, 0.92],   # ground
    [0.13, 0.15, 0.18],   # ink
    [0.83, 0.44, 0.21],   # accent
]).reshape(1, -1, 3))

def palette_delta_e(img_rgb: np.ndarray, k: int = 6) -> float:
    lab = color.rgb2lab(dominant_colors(img_rgb, k))       # k-means on pixels
    d = np.linalg.norm(lab[:, None, :] - BRAND_LAB[0][None, :, :], axis=-1)
    return float(d.min(axis=0).mean())                      # per-brand-colour

Run at four strengths with eight samples each and the shape comes out clearly:

Reference strengthMean ΔE to brand paletteDesigner acceptance (n=8)What went wrong
0.0 (text only, hex codes in prompt)21.41 / 8Palette ignored; "warm" read as orange-brown
0.312.83 / 8Ground colour right, accent still saturated
0.65.15 / 8Usable; occasional composition copied from reference
0.92.72 / 8Near-duplicate of the reference image

The useful range is narrow and it has a failure mode at both ends. Too little and the reference is decoration; too much and you are producing variations of one photograph, which is a different product and sometimes a licensing problem if the reference is a stock image. Hex codes in the prompt performed worst of everything tried, which is the finding most teams do not expect: models have no mechanism for reading #D47036 as a colour specification, and the tokens contribute roughly nothing.

What the text is still the right instrument for

Demoting the prompt is easy to overdo. Text remains the only way to specify what is in the frame, and it does that well: subject, action, setting, camera position, time of day and medium are all reliably conditioned by plain description. The forty-word prompt that replaced the hundred-and-eighty-word one did not get shorter by dropping information; it dropped the adjectives that were competing to describe a look the reference image now carried, and kept every clause that named a thing.

A structure that holds up is one clause each for subject, action or state, setting, framing, and medium, in that order, with no evaluative words at all. "A ceramic pour-over coffee set on a pale oak counter, morning side light from a window on the left, shot at eye level with a 50mm lens, full frame in focus" specifies more than any number of instances of "beautiful", "premium" or "editorial", and each clause can be varied independently when you are testing what matters. Ordering has a mild effect on most models, with earlier tokens weighted slightly more heavily, which is a reason to lead with the subject rather than with a style preamble.

Guidance is the one numeric knob worth sweeping alongside the reference strength, and it interacts with it. On the same eight-sample protocol, guidance at 3.0 produced varied compositions that frequently ignored the framing clause; at 5.5 the framing was respected in most samples and the palette held; at 9.0 the images were noticeably contrastier and more saturated, which pushed ΔE back up to 9.3 even at reference strength 0.6 because over-guidance distorts colour before it distorts anything else. A brand-facing default in the middle of that range, established once by measurement, is worth more than per-prompt fiddling.

A seed turns a comparison into an experiment

A seed is the integer that initialises the field of random noise the model starts from, so passing one replaces the dice with a number you chose. With the same model version, the same parameters, the same prompt and the same seed, a generation is reproducible. That property is worth almost nothing to the end user and everything to you, because it converts a side-by-side comparison from an anecdote into a controlled one. Change the prompt with the seed held fixed and the difference you see is attributable to the prompt. Change nothing and regenerate with a free-running seed and you will see differences anyway, which is how three weeks of adjective work produced an apparent improvement that was sampling noise.

python
resp = client.images.generate(
    model="image-gen-1@2026-03-11",     # pinned; see the next chapter
    prompt=BRAND_PROMPT,
    size="1536x1024",
    quality="high",
    n=1,
    extra_body={
        "seed": 8117,
        "reference_images": [{"b64": brand_ref_b64, "strength": 0.6}],
        "guidance": 5.5,
    },
)

Field names differ across providers and some hosted image APIs expose no seed at all, which is worth checking before you design a methodology around one. Where there is no seed, the substitute is sample size: four to eight generations per prompt per condition, compared as a set rather than as individual images. That is more expensive — at the medium landscape cell it is around $0.25 to evaluate one condition properly — and it is the price of knowing whether a change did anything.

Two limits on seeds are load-bearing. A seed is not portable across model versions; the same integer against a new version produces an unrelated image, so seeds cannot be used to prove that a version change was harmless. And on some infrastructures a seed is not perfectly stable across batch sizes or hardware, so a difference of a few pixels between environments is not evidence of a bug.

Removing what a prompt cannot add

Prompts are additive by nature, and a large fraction of brand rejection is about the presence of something rather than the absence. Watermarks, invented lettering on signage, lens flare, stock-photo smiles, and the shallow-depth-of-field bokeh that models reach for by default — bokeh being the soft blur a wide-open lens gives everything outside the plane of focus — are all things you want gone. Where the API supports a negative prompt, a second list of words naming what must not appear, that is the direct instrument, and it behaves like a conditioning signal the sampler is pushed against rather than toward.

python
negative_prompt = ("text, letters, watermark, signature, logo, lens flare, "
                   "bokeh, oversaturated, vignette, extra fingers")

Where it is unsupported — several hosted APIs, including some of the most widely used, offer no negative prompt field — the fallbacks are worse but real: phrase the constraint positively ("plain unmarked surfaces", "even focus across the frame"), or generate a wider canvas and crop the region where the artefact appears, or accept a lower yield and filter.

Aspect and layout are a different case, because part of it is a hard parameter and part of it is a request the model may decline. Aspect ratio is set by the size argument and is obeyed exactly. Layout — "leave the upper third clear for a headline" — is conditioning text, and compliance in practice runs somewhere around half to two-thirds of generations, which is not a rate you can build a template on. The reliable version of that requirement is structural: generate at a taller canvas than the final crop, or supply a mask marking the region to leave plain, and composite the headline yourself.

The attributes that are not reachable at all

Some things a brand team asks for cannot be obtained through the model regardless of prompt, reference or seed, and reaching that conclusion in week one instead of week four is the highest-value output of this whole exercise. The list is short and consistent: an exact logo, legible typography of specified content, an exact hex value, and the same character or product appearing consistently across a set of images.

Each has a deterministic remedy that lives outside the model. The logo and the type are composited in code, from the actual asset files, which is both pixel-exact and free. An exact hex is reachable by generating with the palette approximately right and then applying a constrained colour transform in post, or by generating on a flat ground you replace. Product consistency across a set is handled by generating the scene and compositing a photograph of the real product, or by keeping the product region masked and unedited.

Flowchart: Prompt + reference + seed → Model generates scene only; Model generates scene only → Palette check ΔE < 6?; Palette check ΔE < 6? → no; no → Constrained colour transform; Palette check ΔE < 6? → yes; yes → Composite layer; Constrained colour transform → Composite layer; Composite layer → Logo, type, product from real assets; Logo, type, product from real assets → Final asset.

The pipeline that ships in most brand-facing products has this shape: the model produces the part that is expensive to make and tolerant of variation, and everything with an exact specification is drawn deterministically on top. Teams that skip the composite step and try to make the model render the wordmark — the brand's name set in its own fixed lettering, the part of a logo that is text — spend weeks discovering that a model which draws four correct letters out of six is not close to succeeding, since a wordmark with a wrong letter is worse than no wordmark.

None of this addresses aesthetic judgement. A reference image at strength 0.6 with a fixed seed and a composited logo will still produce images a designer dislikes, and there is no parameter for taste. What the controls buy is a system where a rejection can be traced to a cause and a change can be evaluated, which is a precondition for improving anything and is also the precondition for the multiplier from the previous chapter coming down.

There is a second thing they buy, and it is the reason the next chapter is possible. A generation you can reproduce is a generation you can compare against later — the same prompt, the same reference, the same seed, rendered again in six months. Without that, a claim that the output has drifted is an argument between two people's memories of what last quarter's images looked like, and the provider is under no obligation to keep the model underneath you the same.

Image generation and editing APIs — read the current version at https://daviddominguez.dev/learn/en/image-generation-and-editing-apis/a-brand-look-is-built-from-references-seeds-and-constraints-not-adject

Back to top