Skip to main content

Extend the borders of card scans for printing — continues the existing border pattern without re-encoding the original image data

Project description

cardbleed

CI PyPI License: MIT

Extends the borders of card scans so a printed and cut card doesn't end up with a border that is too thin. The extension continues whatever border the card already has (holofoil speckle, solid colors, gradients), and the original image data is never re-encoded: PNG and WebP pixels stay bit-identical, and JPEGs are extended by splicing DCT coefficient blocks around the untouched originals.


input, 400×550

output, cardbleed demo_card.png -e 24

The demo card is generated by a script (examples/make_demo.py), so the repository contains no copyrighted scans. It has the traits that make real scans annoying: a speckled border, a brightness gradient across it, a scanner-bloom line at the very edge, and an inner frame line. Bloom is trimmed and the frame line is detected automatically, so sampling never crosses into it.

Install

uv tool install cardbleed        # or: pipx install cardbleed
uvx cardbleed card.png           # or run once without installing

Until the first PyPI release, install from GitHub instead: uv tool install git+https://github.com/ErikBavenstrand/cardbleed

Usage

cardbleed card.png --compare              # extend 16px, write a comparison sheet
cardbleed ./cards/ -e 2.5mm --recursive   # batch a folder, mm-based sizing
cardbleed card.jpg -e 20 --fix-aspect     # pad to the 63x88 ratio, then extend
cardbleed card.png --target 69x94mm       # pad to an exact final size

Outputs are written next to the input (or to --out-dir) with an _ext suffix. Inputs are never overwritten. --compare also writes a side-by-side sheet with the original boundary marked, which makes it easy to check the seam.

Modes

Zoomed left-edge detail, one panel per setting: smart, pattern, naive, mirror, soft.

  • --mode smart (default) resamples the border band stochastically. Speckle is re-randomized in both directions, so nothing streaks or repeats, at the cost of some texture structure.
  • --mode pattern keeps structure intact: every output line is a real contiguous border line, and each outward pass is shifted along the edge by a random offset. If the border has a repeating pattern, detected by autocorrelation, the continuation and the offsets snap to its period so the pattern stays in phase. This is usually the best choice for holo borders. With --shuffle 0 it degrades to a plain deterministic mirror.
  • --mode naive replicates the outermost line straight outward (plus noise and smudge). Mostly useful as a baseline; it streaks on textured borders.

The gallery variants above, for reference:


--mode pattern

--mode naive

--smudge 2.5 --noise 0.8

--compare sheet

Format handling

Format What happens to the original data
PNG re-serialized losslessly; pixels bit-identical
WebP written as lossless WebP; decoded pixels preserved exactly
JPEG original quantized DCT blocks are copied bit-exact into a larger coefficient grid; only the new border blocks are encoded, using the file's own quantization tables

For JPEG the extension amounts have to align to the MCU grid (8 or 16 px). The remainder is shifted between opposite edges, so the final dimensions are still exactly what you asked for.

Options

cardbleed --help has the full reference. The ones worth knowing:

Flag Default Meaning
-e, --extend 16 Amount per edge, px or mm (2.5mm); per-edge overrides via --left etc.
--fix-aspect off Pad the short axis to the card ratio (--card-size, default 63x88 mm) before extending
--target none Pad to an exact final size instead, e.g. 69x94mm
--mode smart smart, pattern, or naive (see above)
-k, --sample 12 Band depth to sample from; clamped at detected inner border structure
--trim auto Scanner-bloom lines to cut per edge
--shuffle 48 How far along the edge texture may be borrowed from
--noise, --smudge 0.35, 0.6 Added grain (relative to the border's own) and ramped blur
--seed 0 Output is deterministic per file

How it works

Each edge is analyzed on the original image: bloom lines are trimmed and the sampling band is clamped before inner border structure. The border is split into a smooth tone component, which is continued outward mirrored so gradients stay seam-continuous, and a texture residual, which is resampled according to the selected mode. Noise matched to the border's measured grain and a ramped blur are applied on top. Corners are filled in two passes so they inherit synthesized side texture. All randomness ramps in from zero at the seam, so the first synthesized line is an exact continuation of the edge.

Development

git clone https://github.com/ErikBavenstrand/cardbleed && cd cardbleed
uv run cardbleed --selfcheck            # assertion suite (fixtures)
uv run cardbleed --selfcheck scan.png   # plus checks against a real scan
uv run --group dev ruff check src
uv run --group dev pyright

Module layout: synthesis.py (edge analysis and border synthesis), formats.py (format-preserving I/O, including the JPEG DCT path), sizing.py (px/mm/target/aspect math), process.py (per-file pipeline), cli.py, selfcheck.py.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cardbleed-0.1.0.tar.gz (3.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cardbleed-0.1.0-py3-none-any.whl (28.8 kB view details)

Uploaded Python 3

File details

Details for the file cardbleed-0.1.0.tar.gz.

File metadata

  • Download URL: cardbleed-0.1.0.tar.gz
  • Upload date:
  • Size: 3.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cardbleed-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0f42ec84abc106798ba27a1114f5cfd1fd0dfe6c38e13d75d384e1bb0c01ec5e
MD5 6b7a179283c6dca8e153b1001b8d7f50
BLAKE2b-256 39d58ab4777ff6394fa299d5bfd12e3e033980e639115d2dd03776e9653b4fa6

See more details on using hashes here.

Provenance

The following attestation bundles were made for cardbleed-0.1.0.tar.gz:

Publisher: release.yml on ErikBavenstrand/cardbleed

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cardbleed-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cardbleed-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 28.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cardbleed-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cc6dacbe9b39a5b2063c3d2c743c12a2e1f8937b9c8eb4831c2a0b65a50d3686
MD5 2f21e73d6ed4562a7481d9d0ed1ace5e
BLAKE2b-256 28f6fc2969cfd85df294829a15c2c64be6f98cda7fd3126a422041eb70975c80

See more details on using hashes here.

Provenance

The following attestation bundles were made for cardbleed-0.1.0-py3-none-any.whl:

Publisher: release.yml on ErikBavenstrand/cardbleed

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page