scanmate-ink
The pixel and geometry kernel behind ScanMate: raster codec, ink separation, warps, homographies, FFT and the pipeline contracts.
A parallel port of @scanmate/ink, not a replacement for it. The
TypeScript remains the reference, and the only useful definition of "correct"
for this package is that it produces the same numbers — bit for bit — as the
TypeScript it parallels.
pip install scanmate-ink
from scanmate_ink import decode_image, ink_map, to_grayscale
page = decode_image("form.png")
ink = ink_map(to_grayscale(page))
HEIF — what a phone camera emits — needs a separate decoder wheel, so it is opt-in rather than a hard dependency of the numeric core:
pip install 'scanmate-ink[heif]'
What "parallel port" means here
Every numeric result is held to the TypeScript's own output by goldens generated
from the real @scanmate/ink build. The comparison is ==, not "close": a port
that is right to six places and wrong in the last bit produces a different
sample, and every downstream result diverges from there.
Three things genuinely differ between the two runtimes, none of them anybody's bug, and each is measured and pinned separately rather than folded into one tolerance:
| Disagreement | |
|---|---|
sin(±π/4) |
1 ULP, MSVC's libm vs glibc's |
Math.hypot vs math.hypot |
16% of inputs — hence scanmate_ink.hypot |
Math.round vs round |
every half-way case — hence js_round |
Two exports of the TypeScript are deliberately absent: resampleRaster and
blurRaster go through libvips, and Pillow's LANCZOS disagrees with libvips'
lanczos3 on 78.8% of pixels while libvips' blur is an integer approximation of a
Gaussian. A Python "equivalent" would be a different operation wearing the same
name. resize_gray and box_blur_raster are ScanMate's own resampler and
blur, are ported, and are bit-exact.
Requirements
Python 3.11 or newer. Fully typed (PEP 561), mypy --strict clean.
Release files for scanmate-ink 0.24.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| scanmate_ink-0.24.2.tar.gz | 111.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| scanmate_ink-0.24.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 196.3 kB
Release files / scanmate_ink-0.24.2.tar.gz
| Download URL | scanmate_ink-0.24.2.tar.gz |
|---|---|
| Size | 111.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
41328cc14f6784154b24be43ae094680abd649a5d72a15b417c6e3d3c4a6469e
|
|
BLAKE2b-256 checksum How to use checksums |
156b3c444a187be34f859543439c8db1b366d5f1b94f2369ea4fd88b92e59e81
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / scanmate_ink-0.24.2-py3-none-any.whl
| Download URL | scanmate_ink-0.24.2-py3-none-any.whl |
|---|---|
| Size | 84.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
577ef5c7d29fad1509c8e840049642fcf1dbbea6fa6004f21bdf43c8d8f18abf
|
|
BLAKE2b-256 checksum How to use checksums |
55dce195a7a2a4ddcaff1a1dba8c01921f3875d7ac707c4ce4448e15236a78b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|