ScanStudio 0.5.0-beta.1
Pre-releaseScanStudio 0.5.0-beta.1 is the first prerelease of the 0.5 line. The headline: when the roll detector cannot find your frames, the app now works with you instead of just refusing -- an automatic wider-gap retry, a plain-English explanation of what the film actually measures, and full manual frame placement as the last resort. This release exists because of the instrumented error reports several of you posted on #23 and #24: keep them coming.
Support levels are unchanged from 0.4.0-beta.1: macOS Apple Silicon is Beta (real-film validated, including this release's new detection paths live on real rolls); macOS Intel, Windows x64, and Linux x64 remain Preview (built and package-verified in CI, real-scanner validation pending).
Starting with this release, the standalone coolscanpy driver on PyPI ships in lockstep with the app -- 0.5.0-beta.1 bundles driver 0.2.0, and pip install coolscanpy gets the identical detection code. A release can no longer build with a driver PyPI does not have.
Everything that changed since 0.4.0-beta.1
Wide-gap recovery (#23, #24). Strips whose blank gaps run wider than the detector's window -- one reporter's payload measured a 14-row gap against the [3,12] accept window, with gap contrast riding the clear-film floor -- used to refuse outright. Detection now runs exactly as before, and only when it fails for lack of gaps does a second pass admit 13-20-row gaps as anchors. Everything it finds is flagged for review, capped at medium confidence, and can never scan unattended. Rolls the normal pass already handles are byte-for-byte unchanged -- replayed against every archived capture to prove it.
Plain-language failure diagnosis. A refusal now tells you what the film measures when the evidence clearly points at one cause: "this looks like half-frame film," "the blank strips between your frames measure about 0.5 mm -- too narrow," "the blank film is only slightly clearer than the frames -- could be fog or a dense base," "one edge of the film window looks partly blocked -- check the holder seating." The analyzer is structurally incapable of producing frames, so a wrong guess can never become a wrong crop, and it stays silent rather than speculating.
Manual frame placement. When detection genuinely cannot handle the film, the failure card offers "Place frames manually": the whole captured strip renders in an editor, you drag boundary lines onto it, and those frames flow through the normal approve-then-scan path. The scanner keeps every physical check it can still make -- each line is resolved against the scanner's own position readings using the same math the automatic path trusts (validated by feeding the automatic detector's own boundaries back through manual placement on every archived capture: exact agreement), frames taller than the scanner's fixed 38.7 mm capture window refuse at placement time instead of silently truncating, and a placement whose position data cannot be verified refuses with a plain sentence. Approvals are cryptographically tied to the exact placement they approved: a failed replacement can never inherit an old approval, approving a frame you were never shown is refused, and "use anyway" decisions die with the placement they were made for.
First preview after power-on no longer fails (found live during this release's own validation). After a cold start the scanner's preview stream changes its internal bookkeeping partway through the capture -- right past the film's end -- and the validator refused the whole preview with "index row framing mismatch." The exact shape is now recognized (and only that shape: corruption still refuses). If your very first preview after switching the scanner on ever failed this way, this was it.
A failed preview can no longer strand the scanner. When a preview failed at the validation stage, its background capture worker could be left holding the USB claim, making every later connection fail with a permissions error until the process was killed by hand. Every preview failure now tears that worker down before the error reaches you.
Partial-frame marker actually reaches the app. The bridge has always been able to mark a frame whose crop runs off the preview edge (common near a roll's start or end); the engine silently dropped the field. It now arrives, so partial frames can be shown as such.
C-41 derivative metadata corrected. Positive TIFFs and preview JPEGs embed a deterministic ICC profile compatible with Adobe RGB (1998); full-resolution positives carry the capture's real pixels-per-inch; downsampled previews no longer falsely claim capture resolution. Archival masters are never rewritten by this correction.
Capture receipts record real per-frame timing. An authoritative UTC start and measured duration per frame (metering through capture-quality checks), surviving every layer down to the app. Legacy receipts show timing as not recorded instead of inventing values.
Under the hood. The detection changes above went through four independent adversarial review rounds before landing; over twenty findings -- including one full rejection and rebuild of the manual-placement position math against real scanner position tables -- were fixed with committed regression tests. The archived-capture acceptance test now runs in the suite so synthetic-only blindness cannot recur. Suites at release: driver 1646, bridge 320, engine 523, app 456.
Known limits
- A recovered (wide-gap) roll previews and shows its frames but still requires your approval before scanning -- unattended scanning of recovered detections is deliberately not enabled yet.
- Manual placement caps frames at the scanner's single-pass capture window (38.7 mm). Panoramic frames need a future multi-window capture to be honest; today they refuse with an explanation instead of silently cropping.
- Raw DNG / linear TIFF export (#41) is built and under final review on its own branch; it ships in the next prerelease.