nanoraster
0.7.1

Render for LLMs

Size, encode, and annotate renders for multimodal models — pixel-based billing, lossless input, and the annotations that carry spatial context.

Open Markdown

A render sent to a multimodal model faces different constraints than one sent to a person. The provider bills the model by the pixel. The model reads compression artifacts as if they were geometry, and it cannot infer orientation or physical size from shading alone.

1. Bytes are free, pixels are billed

The major vision APIs convert an image to tokens from its pixel dimensions alone. The encoded file size never enters the bill. A 5 KB lossy WebP and a 30 KB lossless WebP of the same 768×432 render cost identical tokens on every provider below.

ProviderImage tokensReference
OpenAI⌈width/32⌉ × ⌈height/32⌉ patchesImages and vision
Anthropic⌈width/28⌉ × ⌈height/28⌉ visual tokensVision
Geminifixed per-image budget, set by media resolutionImage understanding

The documented base formulas apply to images small enough to skip provider-side resizing. Some models add multipliers, or detail and resolution settings, that scale the result; the linked pages carry the per-model rules. Under them, the default 768×432 render costs 336 patches on OpenAI and 448 visual tokens on Anthropic. Width and height are the only cost lever the renderer controls. Halve both and the bill roughly quarters; shrink the file and nothing changes.

2. Send lossless input

Because bytes are free, lossy compression can only lose information the model might need. WebP's default quality of 1 encodes lossless, so an explicit format: 'webp' with no quality sends the model exactly the rendered pixels. Anthropic's vision guidance warns that lossy artifacts can degrade model performance while they save nothing on tokens. Use lossy WebP, quality below 1, only when upload latency matters more than fidelity.

3. Annotate for spatial reasoning

A model that reads a render has no camera, no ruler, and no filename. The three annotations put that context into the pixels:

  • axes draws a camera-aware XYZ indicator, so the model knows which way the part is oriented.
  • scaleBar draws physical size in model units; without it a gearbox and a wristwatch gear read identically.
  • label names the subject or view, so a multi-image prompt stays attributable. The renderer draws the label only when you set it.
import { renderImage } from 'nanoraster';const image = await renderImage(glb, {  format: 'webp',  background: '#101418',  axes: true,  scaleBar: true,  label: 'gear',});

Rendering…

 

Annotated output needs at least 192 pixels on both axes. The mechanics of each overlay live in Format and annotate. For the strongest spatial evidence, send several labelled orthogonal views from one batch call. The shared label and axes let the model reconcile the views into one part.

On this page