coolscan3: use the padded pass stride for multi-sample scans

Summary

coolscan3 already sizes each READ from the padded single-pass transfer length. When hardware multi-sampling is enabled, the scanner returns each pass at that padded stride. The averaging loop instead located passes two and later from the unpadded RGB payload length.

At 4000 dpi with a 3946-pixel, 16-bit RGB line, the payload is 23,676 bytes and the padded pass is 24,064 bytes. The old indexing started each later pass 388 bytes too early per pass. That mixed padding into the line and averaged shifted copies into the output, which appeared as horizontal ghosting.

This patch records the padded single-pass length before multiplying the READ size by the sample count. The 8-bit and 16-bit extraction paths now use that same stride. Single-sample scans and models without block padding keep their existing layout.

The scanner-free test covers odd-width 8-bit rows, the LS-5000 full-width geometry, and a synthetic four-pass buffer with sentinel-filled padding. Correct indexing reconstructs every source pixel; the old payload stride reads the sentinel instead.

Hardware evidence

Tested with a Nikon Super Coolscan LS-5000 ED, firmware 1.03. Its SA-21 has the solderless SA-30 conversion.

Before this fix, a 4000 dpi RGB 4x capture showed repeated image energy at the exact offsets predicted by the 388-byte stride error. After the fix, the ghost-comb metric was 0.0000, and 4x versus 1x correlation was 0.999 to 1.000 at lag zero. A fresh 37-frame roll then passed the same alignment and smear checks.

Verification

  • The focused stride helper and regression test compile under strict C99 with -Wall -Wextra -pedantic -Werror.
  • The coolscan3 convenience library and shared module linked in the prepared macOS build.
  • Diff, whitespace, final-newline, and UTF-8 checks passed.
  • The patch is based directly on master and does not depend on draft MR !937.

No scanner was accessed during the final release checks.

Merge request reports

Loading