Image to Prompt as Alt Text: What 480 Lines Actually Say
An image to prompt line is not alternative text. I measured every line this tool writes for forty real image files — 480 lines across four output shapes and three lengths. 408 of 480 (85%) run past a 125-character working cap. 0 of 480 both fit under that cap and name a subject, and 0 of 40 files can produce such a line. The cause is structural: the writer fills its slots with measurements taken from pixels, and the one slot that can name anything fires only on 4 of the 40 files, writing the same four-word phrase in 48 of the 480 lines. Shortening the line removes measured words; it never adds a subject.
What these numbers are. Forty real files — 39 photographs at 640 × 360 and one code screenshot at 800 × 450 — decoded on this machine, box-downsampled to the 192 × 192 grid the live tool measures on, then pushed through the same analyze → describe → compose path the browser runs. That is 4 shapes × 3 lengths = 12 grids of 40 lines each. I use 125 characters as a working cap for alternative text and report 150 and 200 as sensitivity checks; the cap is a measuring rule for this page, not a standard I am asserting. No model was called, no image was generated and no text from another site was used: every figure below comes from this repository’s source and this machine’s output.
Two conditions, and how the 480 lines meet them
Two conditions decide whether a line could stand in for alternative text: it has to be short, and it has to say what is in the picture. Both are measurable without guessing. Length is simply the character count of the composed line; naming a subject means the writer’s subject slot is non-empty. Here is the whole set first.
| Measure | Value |
|---|---|
| Minimum length | 90 characters |
| 10th percentile | 108 characters |
| 25th percentile | 179.8 characters |
| Median length | 216 characters |
| 75th percentile | 270.3 characters |
| 90th percentile | 306 characters |
| Maximum length | 357 characters |
| Mean length | 217.7 characters |
| Words, minimum / median / maximum | 14 / 29 / 47 |
| Lines over a 125-character cap | 408 / 480 (85%) |
| Lines over a 150-character cap | 404 / 480 (84.2%) |
| Lines over a 200-character cap | 282 / 480 (58.8%) |
Raising the cap does not rescue the set. Moving from 125 to 150 characters recovers only 4 lines; even at 200 characters, 282 lines are still over. The median line is 216 characters and 29 words, and the longest is 357 characters. The shortest of all is 90 characters — still 14 words of measurement, not a phrase naming anything.
Broken down by shape and length, only two of the twelve grids ever come in under the cap, and neither does so completely.
| Shape | Length | Lines | Min | Median | Max | ≤ 125 |
|---|---|---|---|---|---|---|
| Midjourney | short | 40 | 157 | 170.5 | 205 | 0 / 40 |
| Midjourney | medium | 40 | 216 | 255 | 298 | 0 / 40 |
| Midjourney | long | 40 | 253 | 300.5 | 340 | 0 / 40 |
| Stable Diffusion | short | 40 | 174 | 187.5 | 222 | 0 / 40 |
| Stable Diffusion | medium | 40 | 233 | 272 | 315 | 0 / 40 |
| Stable Diffusion | long | 40 | 270 | 317.5 | 357 | 0 / 40 |
| Flux | short | 40 | 97 | 109 | 166 | 36 / 40 |
| Flux | medium | 40 | 179 | 198 | 260 | 0 / 40 |
| Flux | long | 40 | 222 | 261.5 | 329 | 0 / 40 |
| DALL·E | short | 40 | 90 | 102 | 145 | 36 / 40 |
| DALL·E | medium | 40 | 172 | 191 | 239 | 0 / 40 |
| DALL·E | long | 40 | 203 | 222 | 269 | 0 / 40 |
Exactly 0 of the 12 grids has all forty lines under the cap. The 72 short-enough lines are confined to two grids — 36 Flux/short and 36 DALL·E/short. Those two are the sentence shapes at their shortest setting, and they are short because the composer omits contrast, detail and light distribution at that length, not because it has become more concise about the subject.
Now the second condition. The writer sets d.subject in exactly one branch of src/describe.js, when monoRatio > 0.85, and the value it writes is always black and white photograph. On this corpus that happens on 4 of 40 files, producing 48 of 480 lines (10%). The other 36 files have no subject on any of their twelve lines — 432 lines with nothing named. All 48 subject phrases sit inside the first 125 characters of their lines, so trimming cannot even remove the only subject the writer ever produces.
The intersection of the two conditions is empty: 72 lines are short enough, 48 lines name a subject, and 0 of 480 do both. No grid contains one, and 0 of the 40 files can produce one. That is the answer to the question in the title, and it holds at every cap I tried.
Where the characters come from
If the line is too long, the obvious next question is what is filling it. The distribution is not centred near the cap; it is bimodal, with a small pile of very short sentence-shape lines and a large pile of long comma-list lines.
| Characters | Lines | Share |
|---|---|---|
| 0–49 | 0 | 0% |
| 50–74 | 0 | 0% |
| 75–99 | 15 | 3.1% |
| 100–124 | 57 | 11.9% |
| 125–149 | 4 | 0.8% |
| 150–174 | 31 | 6.5% |
| 175–199 | 91 | 19% |
| 200–224 | 61 | 12.7% |
| 225–249 | 60 | 12.5% |
| 250–299 | 103 | 21.5% |
| 300–349 | 55 | 11.5% |
| 350+ | 3 | 0.6% |
The single largest band is 250–299 characters with 103 lines (21.5%); only 15 lines (3.1%) fall below 100 characters. There is no band at all between 0 and 74 characters. A line from this tool is, by construction, a string of measurement phrases rather than a short caption.
To separate measured content from packaging, I listed the exact phrases src/compose.js writes for each shape and length, summed their lengths for every line, and called the remainder shell — the commas, sentence frames, quality prefix and ratio parameter that surround the measured values. Payload is therefore a count over real output, and shell is the arithmetic remainder of the real line.
| Shape | Length | Slot phrases | Payload | Shell | Shell share |
|---|---|---|---|---|---|
| Midjourney | short | 5 | 152.5 | 18 | 10.6% |
| Midjourney | medium | 8 | 231 | 24 | 9.6% |
| Midjourney | long | 10 | 273 | 28 | 9.4% |
| Stable Diffusion | short | 5 | 152.5 | 35 | 18.7% |
| Stable Diffusion | medium | 8 | 231 | 41 | 15.1% |
| Stable Diffusion | long | 10 | 273 | 45 | 14.2% |
| Flux | short | 3 | 71 | 38 | 35.3% |
| Flux | medium | 6 | 154 | 44 | 22.4% |
| Flux | long | 8 | 213.5 | 48 | 19.5% |
| DALL·E | short | 3 | 71 | 31 | 30.8% |
| DALL·E | medium | 6 | 154 | 37 | 19.6% |
| DALL·E | long | 7 | 183 | 39 | 17.7% |
Shell share runs from 9.4% (Midjourney, long) to 35.3% (Flux, short). In other words, even the most aggressively packaged line is still two-thirds measured adjectives. The comma-list shapes carry a shell of 18 to 45 characters; the two sentence shapes at short length carry 31 and 38 characters around a payload of only 71. Cutting the shell cannot bring a 273-character payload under a 125-character cap.
Those shell characters are not vague padding; they are fixed string literals in src/compose.js, and their lengths are constants.
| Literal | Characters | Where it appears |
|---|---|---|
masterpiece, best quality, | 27 | front of every Stable Diffusion line |
--ar | 6 | before the ratio on Midjourney lines |
dominant palette of | 20 | palette slot on the comma-list shapes |
composition | 12 | appended to the framing value |
, | 2 | glue between comma-list slots |
A | 2 | opener on the sentence shapes |
image. | 7 | first sentence of Flux |
The dominant colours are | 25 | Flux colour sentence |
with a palette of | 18 | DALL·E palette phrase |
What the line says instead of a subject
Alternative text is read by a person who cannot see the image; a line written for a generator is read by a parser. The difference shows up in the characters left in the output. I counted seven markers across all 480 lines, plus the subject facts already established.
| Marker | Lines out of 480 | Share |
|---|---|---|
Carries a --ar parameter | 120 | 25% |
Starts with masterpiece, best quality, | 120 | 25% |
| Ends with a full stop | 240 | 50% |
Starts with A | 240 | 50% |
| Contains a colon | 480 | 100% |
| Contains a comma | 480 | 100% |
| Contains a digit | 480 | 100% |
| Names a subject | 48 | 10% |
| Names no subject | 432 | 90% |
| Files with a subject | 4 / 40 | 10% |
| Files with no subject on any line | 36 / 40 | 90% |
| Both short enough and naming a subject | 0 | 0% |
The 120 parameter lines are all Midjourney; the 120 quality-tag lines are all Stable Diffusion; the 240 full-stop lines and 240 leading-A lines are Flux and DALL·E. Every one of the 480 lines contains a colon, a comma and a digit — not prose punctuation, but because all forty files are 16:9, so the ratio string 16:9 appears in every line. A reader who cannot see the picture would receive a ratio, an exposure band, a palette and a light distribution, and on 432 of the lines not a single word about what the picture depicts.
This is not a failure of wording. src/describe.js deliberately keeps its scene hint conservative: it comments that guessing “foliage” from a green histogram is exactly the kind of confident wrong answer the library tries not to produce. So the subject slot stays empty unless monochrome is measured, and the four files that do trigger it all receive the same phrase — black and white photograph — on each of their twelve lines. That is a statement about the pixels, not about the content of the photograph.
What trimming to 125 characters takes out
The obvious fix is to cut the line down. I tried two versions. A hard slice at 125 characters leaves 290 of the 408 over-cap lines ending in the middle of a word. Trimming on word boundaries instead — dropping whole words from the tail until the line fits — is cleaner, and here is what it costs.
| Measure | Before / result |
|---|---|
| Lines already at or under 125 (unchanged) | 72 / 480 |
| Words removed, median (min–max) | 12 (0–31) |
| Remaining characters, median (min–max) | 121 (90–125) |
Lines losing the --ar tail | 120 / 480 |
| Lines losing the mood phrase | 160 / 480 |
| Lines losing the palette label | 12 / 480 |
| Lines losing the subject phrase | 0 / 480 |
| Out-of-range lines, before → after | 120 → 0 |
| Out-of-range terms, before → after | 120 → 0 |
| Words removed, median: Midjourney / Stable Diffusion | 18 / 19 |
| Words removed, median: Flux / DALL·E | 10 / 9 |
The trimmed line is a different object. It has lost a median of 12 words, up to 31; the 160 lines that carried a mood phrase all lose it, because mood is written last in the long length; the ratio parameter disappears from all 120 Midjourney lines; and the palette label goes from 12 Flux lines. The subject is lost from 0 lines — it sits at the front, and on the other 432 lines there was none to lose. Nothing about the picture has been added.
One side effect is worth naming precisely. This site’s own weight parser flagged 120 lines before trimming and 0 after, because the only out-of-band term in the whole corpus is the Midjourney ratio tail, and trimming deletes it. That is a consequence of deletion, not a repair: the line is shorter, not better formed, and the parser’s silence says nothing about whether the text now describes the image.
Here are the two ends of the real output, verbatim, so the shape of the problem is visible without a summary.
shortest 90 characters / 14 words [DALL-E / short] A widescreen 16:9 image, well-lit, balanced exposure, with a palette of tan, brown, olive. longest 357 characters / 46 words [Stable Diffusion / long] masterpiece, best quality, widescreen 16:9 composition, moderate, slightly dim lighting, dominant palette of moss green, charcoal, tan, beige, moderately saturated colour, warm golden colour temperature, medium contrast, highly detailed with intricate texture, light falling on the centre with darker edges, brighter upper half, balanced, natural atmosphere
The 90-character line is the closest this corpus gets to a caption, and it is still a framing ratio, an exposure band and three colour names. The 357-character line is ten measured slots plus a 27-character quality prefix. Neither mentions a person, an object, a place or an action.
- Do not paste the line into an alt attribute unchanged. On this corpus 408 of 480 lines exceed the working cap, and 0 of 480 name a subject while staying under it.
- If you must shorten, trim on word boundaries. A hard slice at 125 characters ends 290 lines mid-word; word-boundary trimming leaves a median of 121 characters but removes up to 31 words and all 160 mood phrases.
- Write the subject yourself. The tool leaves it empty on 36 of 40 files, and on the 4 files where it does write one, the phrase is always black and white photograph.
Forty files, twelve grids, one 125-character cap
The forty files are the same corpus used elsewhere on this site: 39 stock photographs at 640 × 360 plus one 800 × 450 code screenshot, decoded locally, box-downsampled to 192 × 192, then measured and written by the identical analyze → describe → compose path the browser runs, across four output shapes and three lengths — 480 lines. Every count in this page was produced by one script and is on disk: prep/day46_alt.mjs writes prep/day46-alt.json and prep/day46-alt.log, and the verbatim run is in prep/day46-run.log. Source facts come from src/describe.js (the monoRatio > 0.85 subject branch) and src/compose.js (the four shapes, the three lengths and the fixed literals listed above). A number-by-number check is in prep/day46-number-audit.md.
Three limits on reading these figures. The corpus is 39 landscape photographs and one screenshot, and every one of them is 16:9; a set with other aspect ratios would change the length of individual lines slightly, but not the slot structure or the empty subject slot. The 125-character cap is a working threshold chosen for this measurement, which is why 150 and 200 are reported alongside it — the conclusion holds at all three. And no model was called, no image was generated and no video was produced: every statement here is about the words this tool writes, not about what any generator would do with them.
For the twelve slots the line is built from, see what an image to prompt tool measures. For how the same measurements are worded by each of the four output shapes, see the four lines side by side. For the cut points at which each phrase flips, see the cut-point table; for the closed vocabulary behind those phrases, see what the describer actually writes, and for the ratio parameter that ends up in the parser, see weighting a prompt and writing a negative.