visualtoprompt.com

What an image description generator actually writes: nine slots, 95 words, one line

It does not look at your picture and describe it. It measures a 192 × 192 grid, compares each number against fixed thresholds, and fills nine slots from a vocabulary it can never step outside — 95 entries in total.

Nine slots in a three-by-three grid; the centre one is marked in blue.
Nine slots in a three-by-three grid; the centre one is marked in blue.

An AI image describer writes nine fixed phrases, one per slot, each chosen by comparing a single measured number against a hard-coded threshold, then adds up to four colour names. That is the whole output. The vocabulary behind it is closed: 95 entries taken from the source of this site’s writer — 42 phrases in the describer, 18 template fragments in the formatter, 35 colour names. We pushed 81 generated prompts, 1,937 words, back through that list: not one word came from anywhere else.

That is the useful thing to know about an image describer. It is not a summariser that occasionally misses. It is a nine-position switchboard, and every position has a number behind it that you can read back.

Here is a real output, from a 640 × 360 night photograph of fireworks, at the longest setting:

widescreen 16:9 composition, dark, low-key lighting, dominant palette of navy, grey, slate, silver,
vivid, saturated colour, cool blue colour temperature, medium contrast, highly detailed with
intricate texture, light falling on the centre with darker edges, brighter upper half,
moody and dramatic atmosphere --ar 16:9

Nine slots, nine numbers. The same code, run 200 times on the same file, produced one description — no variation at all. Below: what the vocabulary is, where each phrase flips, and what the describer is structurally unable to say.

The vocabulary is closed at 95 entries

The writer is a chain of if/else comparisons over measured numbers, and every string it can emit is written literally in the source. Collect them all and you get the complete set of things this describer is able to say:

Every literal string the describer and the formatter can produce, plus the 35 named colours.
SourceEntriesWhat it covers
src/describe.js42Eight framings, four exposures, three contrasts, four saturation states, five colour temperatures, three detail levels, three lighting distributions, two verticals, four moods, one subject, four hue hints, one fallback (“mixed tones”)
src/compose.js18Fixed template fragments: “composition”, “dominant palette of”, “masterpiece, best quality,”, “The dominant colours are”, the model names, the length names
src/palette.js35Named colours from black to cream, found by nearest-neighbour distance
Total, de-duplicated95Nothing outside this set can appear in any output

We checked that claim rather than asserting it: 81 prompts (three real images × four target formats × three length settings, plus every synthetic sweep below) were split into words and matched against the vocabulary. 1,937 words, zero misses.

Which of those entries get used, and how often, is a separate question: counted across 480 lines from forty real photographs, 13,736 word tokens came from 98 distinct words, and not one popularity or recency word appeared in any of them. For that ranking — and for why a trend cannot come out of a closed vocabulary — see what this tool can and cannot rank when you ask it for a trending photo prompt.

The consequence is worth stating plainly. A describer with a closed vocabulary of adjectives, colour names and geometric ratios cannot name an object, a person, a place, a time of day, an art style, a camera, a lens, or the text in your screenshot — not because it failed to spot them, but because those words do not exist in it. If you are waiting for the description to mention “a dog”, no amount of cropping will produce it.

Nine slots, one number each

Each slot is decided by exactly one comparison, or in two cases by a ratio between two regions. Value column is the real night photograph above:

Slot, the number behind it, the thresholds in the source, and what this image measured.
SlotDecided byThresholdsMeasuredPhrase it chose
framingaspect ratio2.2 / 1.7 / 1.4 / 1.15 / 0.9 / 0.7 / 0.551.7778widescreen 16:9
exposuremean luminance175 / 130 / 8034.51dark, low-key lighting
contraststd dev of luminance68 / 3846.93medium contrast
saturationmono ratio, then mean saturation0.85; 0.45 / 0.220.0117vivid, saturated colour
temperaturemean R − mean B±14 / ±5−43.93cool blue colour temperature
detailmean gradient15 / 722.50highly detailed with intricate texture
distributioncentre vs border, ×1.181.1860.25 / 29.58light falling on the centre with darker edges
verticaltop vs bottom, ×1.21.243.23 / 25.50brighter upper half
moodluminance, contrast, temperature150 / 95 / 68 / ±534.51moody and dramatic atmosphere
palettemerged colour bucketstop 4 of 5—navy, grey, slate, silver

Mood is the only slot that reads three numbers, and the only one whose thresholds (“95”, “150”) sit inside another slot’s bands rather than on their edges. That has a measurable consequence, shown further down.

Where exactly the wording flips

Every comparison in the writer is a plain >, with one exception: framing uses >=. So a value sitting precisely on a threshold falls to the lower phrase almost everywhere, and to the higher one for aspect ratio. We fed the writer values just below, exactly on, and just above each line:

Boundary probes: the writer is a pure function of the numbers, so these are its exact answers at each line.
LineJust belowExactly onJust above
meanL = 8079.99 → dark, low-key80 → dark, low-key80.01 → moderate, slightly dim
meanL = 130129.99 → moderate130 → moderate130.01 → well-lit, balanced
meanL = 175174.99 → well-lit175 → well-lit175.01 → bright, high-key
stdL = 3837.99 → soft, low contrast38 → soft, low contrast38.01 → medium contrast
stdL = 6867.99 → medium68 → medium68.01 → high contrast
edge = 76.99 → clean and minimal7 → clean and minimal7.01 → moderate detail
edge = 1514.99 → moderate15 → moderate15.01 → highly detailed
monoRatio = 0.850.849 → moderately saturated0.85 → moderately saturated0.851 → monochrome, black and white
meanSat = 0.450.449 → moderately saturated0.45 → moderately saturated0.451 → vivid, saturated
centre / border = 1.18117.99 → evenly lit118 → evenly lit118.01 → light on the centre
top / bottom = 1.2119.99 → (no phrase)120 → (no phrase)120.01 → brighter upper half
ar = 2.22.19 → widescreen 16:92.2 → ultra-wide panoramic2.21 → ultra-wide panoramic

That table is also a diagnosis tool. If the writer calls your photo “dark, low-key lighting”, you know the measured mean luminance is 80 or lower, not roughly 80 — the number is exact at the boundary.

Four things we pushed through it on real pixels

Numbers fed straight to the writer prove the branches; synthetic 192 × 192 images prove the measurements behave the same way on actual pixel data. Four of them are worth reporting:

Synthetic images built so that one measured number moves and the rest stay put. All at 192 × 192.
What we builtWhat it measuredWhat it wrote
Two flat halves, 90 / 166stdL = 38.00 exactlysoft, low contrast — the strict > holds on real pixels too
Vertical stripes, ±14, period 8edge = 6.78clean and minimal, smooth surfaces — visible texture, still under the 7 line
10% of pixels vivid red, rest greymonoRatio = 0.8999monochrome, black and white, and subject = “black and white photograph”
15% of pixels vivid red, rest greymonoRatio = 0.8499muted, desaturated tones — subject slot goes back to empty
Grey with R − B = +6monoRatio = 1.00, dt = +6“monochrome, black and white” and “slightly warm tone”, in the same prompt
Bright centre 128, border 100ratio 1.28light falling on the centre with darker edges
Centre 118, border 100ratio 1.18evenly lit — the phrase disappears at the line

Two of those deserve a second look. The first: an image with 10% of its pixels vividly red is still described as a black and white photograph. The mono test counts pixels whose HSV saturation is under 0.10, and it takes more than 85% of them to trigger the monochrome branch — so a largely grey picture with a pop of colour gets the monochrome phrase, and the subject slot fills in with “black and white photograph”. Push the coloured share to 15% and both disappear at once.

The second is the mirror image of it. On the way up, “vivid, saturated colour” needs a mean HSV saturation above 0.45, and a grey pixel contributes zero. We raised the share of fully saturated pixels one point at a time: at 81% the mean is 0.4457 and the phrase is still “moderately saturated”; at 82% it reads 0.4512 and the phrase becomes “vivid”. More than four fifths of the frame has to be strongly coloured before the describer will call the image vivid.

The R − B = +6 row shows something else about the design: the slots are independent. Nothing reconciles them, so a grey image with a slight warm cast is reported as monochrome and warm in the same sentence. That is not a bug in the measurement — both numbers are right — it is what you get when nine separate comparisons never consult each other.

Read the description backwards

Because each phrase comes from a band, you can take any output and recover the range its numbers must have fallen in. We verified each band at both endpoints:

Phrase → the range the measured number must sit in. Both endpoints checked against the writer.
PhraseNumberRange it guarantees
dark, low-key lightingmean L0 – 80
moderate, slightly dim lightingmean L80 – 130
well-lit, balanced exposuremean L130 – 175
bright, high-key lightingmean L175 – 255
soft, low contraststd dev L0 – 38
medium contraststd dev L38 – 68
high contraststd dev L68 – 127.5
clean and minimal, smooth surfacesedge0 – 7
moderate detail and textureedge7 – 15
highly detailed with intricate textureedgeabove 15
cool blue colour temperaturemean R − Bbelow −14
neutral colour temperaturemean R − B−5 – +5
warm golden colour temperaturemean R − Babove +14

So “moderate detail and texture” is not a vague compliment. It means the mean gradient across the 192 × 192 grid landed between 7 and 15 — and that a nudge in either direction, a crop or a blur, will move it.

How many different descriptions exist

Multiply the options per slot and the nine slots look like they span 207,360 combinations. They do not, because mood is not a free slot: it reads the same luminance, contrast and temperature that already decided three other slots. Splitting those three numbers into their finest bands gives 90 combinations, and only 76 of them produce a distinct (exposure, contrast, temperature, mood) four-tuple. Mood is fully determined once you know the other three, so:

76 distinct four-tuples x 4 saturation x 3 detail x 3 distribution x 3 vertical x 8 framing
  = 65,664 reachable descriptions, out of 207,360 nominal  (31.67%)

Two thirds of the nominal space is unreachable. A dark, low-contrast, warm image, for instance, can only ever be “moody and dramatic” — there is no combination of the other eight slots that will let it be “bright and uplifting”. Worth knowing before you re-roll the output hoping for a different mood: on the same file, there is nothing to re-roll. Two hundred runs produced one description.

What it will never say

Three limits follow from the design, and they are the ones that matter when you are deciding whether to trust an output:

None of these are failures to fix. They are the reason the output is stable: the describer reports what it can measure and stays silent about the rest, instead of filling the gap with a guess that sounds right.

Which number decides which word

Nine measured numbers are read thirteen times to fill the ten slots and the subject line. Four of them are read twice — mean luminance, its standard deviation, the red–blue difference and the monochrome share — and the other five once each. To see what that is worth to you, we moved one number at a time to each of its other bands, left the other eight at their measured values, and rebuilt all twelve lines (four formats × three lengths) for each of forty real photographs: 720 moves, 8,640 rebuilt lines.

One number moved at a time, the other eight held at their measured values. Medians over forty photographs × twelve lines.
NumberBandsSlots it moves (share of its moves)Slots changedLines changed of 12Words changed
mean luminance4exposure 100%, mood 65%2128
std dev of luminance3contrast 100%, mood 33.8%144
monochrome share2subject 100%, saturation 100%21279
mean saturation3saturation 90%1100
mean R − mean B5temperature 100%, mood 41.3%11010
mean gradient3detail 100%188
centre over border3distribution 100%1520
top over bottom3vertical 100%126

Two rows deserve a second look. The monochrome share is the most expensive number in the table and the only one that always moves two slots: the same comparison fills the saturation phrase and switches the subject line on, so a single move costs a median of 79 words across the twelve lines, on all forty photographs. At the other end, mean saturation changed a median of ten lines and zero words — all three saturation phrases are three words long, so swapping one for another never changes the length of the sentence, however much it changes what it says.

Here is that asymmetry on one real file, a 640 × 360 photograph that measures a monochrome share of 1.00 and a mean saturation of 0.00:

p58, longest setting, Midjourney — as measured:
black and white photograph, widescreen 16:9 composition, dominant palette of grey, slate, silver, white, well-lit, balanced exposure, monochrome, black and white, neutral colour temperature, medium contrast, highly detailed with intricate texture, evenly lit, balanced, natural atmosphere --ar 16:9

mean saturation moved to 0.60, everything else unchanged:
black and white photograph, widescreen 16:9 composition, dominant palette of grey, slate, silver, white, well-lit, balanced exposure, monochrome, black and white, neutral colour temperature, medium contrast, highly detailed with intricate texture, evenly lit, balanced, natural atmosphere --ar 16:9
(byte-identical: 8 of the 80 saturation moves changed nothing at all)

monochrome share moved to 0.40, mean saturation left at 0.00:
widescreen 16:9 composition, well-lit, balanced exposure, dominant palette of grey, slate, silver, white, muted, desaturated tones, neutral colour temperature, medium contrast, highly detailed with intricate texture, evenly lit, balanced, natural atmosphere --ar 16:9

The writer tests the monochrome share before mean saturation, so on a picture that is already over 0.85 no saturation value can reach the phrase. It is the one place in the table where a number has a veto rather than a vote — and those 8 dead moves all come from the four photographs that are already monochrome.

Now read the same experiment from the other end: for each slot, how many of the eight numbers can move its wording on your picture. Structurally mood reads three numbers and saturation reads two, but what you actually get depends on the photograph.

Each slot: which numbers moved it, on how many of the forty photographs, and the median number of working handles.
SlotMoved byHandles (median)Range
framingnothing here — its number is the file’s own aspect ratio00
exposuremean luminance, 40 of 4011
saturationmonochrome share 40 of 40, mean saturation 36 of 4021–2
temperaturemean R − mean B, 40 of 4011
contraststd dev of luminance, 40 of 4011
detailmean gradient, 40 of 4011
distributioncentre over border, 40 of 4011
verticaltop over bottom, 40 of 4011
moodmean luminance 38 of 40, mean R − mean B 26 of 40, std dev of luminance 23 of 4021–3
subjectmonochrome share, 40 of 4011
palettenothing — it is read off merged colour buckets, not off any of the nine numbers00

Mood is the only slot with three handles, and they are not equal: mean luminance worked on 38 of the forty photographs, the red–blue difference on 26, and contrast on 23. On the median photograph two of the three move it, and on all forty at least one does. Two slots have no handle at all. Framing is decided by the file’s pixel dimensions, and every photograph in this batch is 16:9, so it never moved once in 720 attempts; the palette comes from colour buckets rather than from any measured number. For those two, no measurement you can nudge will help — you change the file, or you change the words.

That is the practical shape of it: nine numbers, thirteen reads, one lever per word — except mood, which has three, and framing and palette, which have none. When a phrase reads wrong, the lever is the number behind it, not the sentence around it.

Photo to prompt: forty photos, forty lines, eight switches and one colour list

Forty different photographs, run through a photo to prompt tool, produce forty different lines: all 780 pairs differ somewhere. The difference is not spread evenly. Eight of the nine slots are three-to-five-position switches, and the only fine-grained slot is the colour list — 37 different colour combinations across the forty files, built from just 20 of the 35 names in the table. In 9 of those 780 pairs two unrelated photographs came out with the same phrase in eight slots and differed in exactly one.

How many positions each slot actually has, counted over forty real photographs. “Most common” is the phrase that won most often, and how many of the forty files it won on.
SlotPositions usedMost common phraseFilesShare
framing1widescreen 16:940100%
exposure4moderate, slightly dim lighting1640%
contrast3medium contrast2870%
saturation4moderately saturated colour1742.5%
temperature5warm golden colour temperature1230%
detail3highly detailed with intricate texture2255%
distribution3evenly lit2152.5%
vertical3brighter upper half2255%
mood4moody and dramatic atmosphere1640%
colour list37charcoal, slate, grey, silver410%

One row is flat and it is worth saying why rather than hiding it: every one of the forty source files is a 16:9 frame, so framing had one position to be in and took it. Feed the same code a 3:4 phone photo and that row becomes the only one that moves — the aspect ratio is read off the file, not off the scene. The other eight rows are the ones that carry information about the picture.

Because those eight rows are coarse, two photographs that look nothing alike can land on the same words. Counted across all 780 pairs, this is how many of the nine slots changed:

Pairwise comparison of forty photographs, colour list excluded. 780 pairs, nine slots each. No pair differs in all nine, and none is identical.
Slots that differPairsShare of 780
191.2%
2253.2%
3769.7%
412916.5%
520225.9%
619224.6%
711114.2%
8364.6%

Of the nine pairs that differ in a single slot, four differ only in the vertical phrase, three only in the lighting distribution and two only in colour temperature. Here is the pair that differs in temperature, both files at the longest setting, Midjourney shape:

p476 (640 × 360, mean luminance 64.33, gradient 17.95):
widescreen 16:9 composition, dark, low-key lighting, dominant palette of charcoal, brown, cream, grey, muted, desaturated tones, warm golden colour temperature, medium contrast, highly detailed with intricate texture, light falling on the centre with darker edges, brighter upper half, moody and dramatic atmosphere --ar 16:9

q969 (800 × 450, mean luminance 72.75, gradient 19.92):
widescreen 16:9 composition, dark, low-key lighting, dominant palette of black, slate, charcoal, tan, muted, desaturated tones, neutral colour temperature, medium contrast, highly detailed with intricate texture, light falling on the centre with darker edges, brighter upper half, moody and dramatic atmosphere --ar 16:9

Nine phrases are identical. Two photographs, two different colour lists, and one switch flipped: the red–blue difference fell from +15.10, past the +14 line, to +2.87 inside the ±5 band, and the phrase went from warm golden to neutral. Nothing else in either line knows the two pictures are different.

The colour list is the only part of the line that is not a switch, and it is where most of the visible variety comes from. Twenty names did all the work across forty files: charcoal on 26, grey on 24, silver on 20, slate on 18, tan on 17, black on 8, brown on 7, white on 7. Five names were used by exactly one file each. That is also the honest limit of what an ai photo describer can tell two pictures apart by — a row of colour names is the finest instrument in the box, and it is still only four words long.

If you are going picture to prompt the other way round, the same table applies in reverse: change a colour name and you change the line by one to four words; change any of the eight switches and you change exactly one phrase, because each is decided by a single comparison. The aspect ratio is the exception — it is arithmetic, not a switch, and on a 3:4 phone photo it is the first thing to check.

Three things worth doing with that:

  1. Read the colour list first. It is the only slot with more than five positions — 37 combinations against three to five for every switch — so if two outputs look the same to you, the difference is almost certainly in the four colour names.
  2. Count the switches you disagree with. Eight slots, one threshold each, and the measured value behind every one of them is in the table above — if the line says medium contrast and you think it is high, the number to look at is the standard deviation, not the wording.
  3. Check the ratio before anything else on a vertical photo. framing is a phrase; the actual --ar value is computed separately and can disagree with it.

How to use that when the description is wrong

When a phrase reads wrong, the fix is upstream of the writer, because the writer has no opinion — it only has thresholds:

For what each measured field is and how it is computed, see what an image to prompt tool measures. For the order to work in when a phrase is wrong, see fixing a wrong image to prompt output; for turning a picture into something you can paste, see how to generate a prompt from an image; and for the pictures where this approach breaks down, see which images it handles badly.