v0.2.2 — blank renders fail loud
A blank render is now an error instead of a success.
0.2.1 renders correctly, so nobody is broken today. What this release adds is that the next scene-setup defect fails loudly rather than returning a well-formed PNG of nothing — which is exactly how #14 reached a user.
Why this, and not just the clip fix
Fixing the clip planes in 0.2.1 removed one cause of an empty scene. It did nothing to make an empty scene detectable. The render path had no output postcondition at all: the import succeeded, Blender exited 0, a well-formed PNG landed on disk, and a frame containing nothing was indistinguishable from a good one at every layer. Hidden geometry, a misaimed camera, an import that yields nothing, or dead lights would each have reached a user the same silent way.
What changed
render_ldraw rejects any view whose largest per-channel value range is at or below BLANK_FRAME_MAX_SPREAD (24).
- Per view, before stitching. One blank view beside one good one stitches into an image full of contrast, so the same check applied to the combined result would miss half the failure.
- Extrema, not a count of differing pixels. Extrema does not depend on how much of the frame the model fills, so a small part rendered at high resolution cannot read as blank.
- No new dependency — Pillow was already required.
Measured separation is ~34x with nothing in between: a blank frame scores 6 (cycles sampling noise only), the sparsest legitimate render measured — model covering just 1% of the frame — scores 207.
Behaviour change
render_ldraw can now raise LDrawRenderError where it previously returned a path to a blank image. A caller that assumed it always got a file back has a new error path to handle. Patch level regardless, because a blank image was never a correct result.
Verification
The guard was seen to fail before being trusted: deleting it makes both rejection tests fail with DID NOT RAISE while the controls stay green, and moving the threshold to 0 is caught by the real blank fixture. Reverting the 0.2.1 clip fix and rendering through real Blender raises 2 of 2 view(s) rendered blank.