Skip to main content

Walsh-hadamard transform

PyPI Python versions CI Coverage License: MIT

Compressing images with a Hadamard transform

Description

From Wikipedia: The Hadamard transform (also known as the Walsh–Hadamard transform, Hadamard–Rademacher–Walsh transform, Walsh transform, or Walsh–Fourier transform) is an example of a generalized class of Fourier transforms. It performs an orthogonal, symmetric, involutive, linear operation on 2m real numbers (or complex numbers, although the Hadamard matrices themselves are purely real).

The Hadamard transform can be regarded as being built out of size-2 discrete Fourier transforms (DFTs), and is in fact equivalent to a multidimensional DFT of size 2 × 2 × ⋯ × 2 × 2. It decomposes an arbitrary input vector into a superposition of Walsh functions.

The transform is named for the French mathematician Jacques Hadamard, the German-American mathematician Hans Rademacher, and the American mathematician Joseph L. Walsh.

The Hadamard transform is also used in data encryption, as well as many signal processing and data compression algorithms, such as JPEG XR and MPEG-4 AVC. In video compression applications, it is usually used in the form of the sum of absolute transformed differences. It is also a crucial part of Grover's algorithm and Shor's algorithm in quantum computing.

Acknowledgement

This code is partially based on the solution from ktisha/python2012

Installation

Requires Python 3.10 or newer.

pip install walsh

or, with uv:

uv add walsh          # into a project
uv tool install walsh # just the command line tool

The example script additionally needs matplotlib and Pillow, which are the demo extra: pip install "walsh[demo]".

Development

uv.lock is committed, so a checkout reproduces exactly the environment CI uses:

uv sync --group dev --all-extras

--group dev brings in pytest, ruff and mypy; --all-extras adds the demo extra so examples/roundtrip.py runs too. Without uv:

pip install -e ".[demo]" -r requirements-dev.txt

How to run

Command line

walsh compress data/image.bmp data/transformed.cim
walsh extract  data/transformed.cim data/recreated.bmp

compress accepts --packed-block-size (how many low-frequency coefficients per axis to keep -- lower is smaller and lossier), --y-block-size, --chroma-block-size and --coeff-removal. Add -v/-vv for progress logging, and see walsh --help for the full list.

As a library

from walsh import Task

Task().with_action("compress").with_input("data/image.bmp").with_output("out.cim").run()
Task().with_action("extract").with_input("out.cim").with_output("back.bmp").run()

Example

examples/roundtrip.py compresses the sample image, restores it, and plots both images with their histograms side by side (needs the demo extra):

python examples/roundtrip.py

Requirements

The package itself needs only numpy -- BMP parsing is done by hand with struct. matplotlib and Pillow are needed only by the example script, and are declared as the demo extra. Versions are pinned in pyproject.toml; requirements.txt, requirements-demo.txt and requirements-dev.txt mirror them for plain pip install -r workflows.

Development commands

uv run pytest                          # test suite
uv run pytest --cov --cov-report=term-missing   # with coverage
uv run ruff check .                    # lint
uv run ruff format .                   # format
uv run mypy                            # strict type check
uv build                               # sdist + wheel into dist/

CI runs exactly these on every pull request, plus the test suite against Python 3.10 through 3.14.

Coverage

Coverage is measured with branch coverage on, and CI enforces a floor of 90% on every supported Python version. A pull request that drops below it fails the test jobs, which are required checks on master — so the badge above states what is actually guaranteed rather than a number that could drift.

Coverage is opt-in locally (--cov) so a plain pytest stays fast; CI always passes it.

Releasing

The version in pyproject.toml is the single source of truth. To cut a release, bump it, add the matching ## [x.y.z] section to CHANGELOG.md, and merge to master. The release workflow then tags v<version>, creates a GitHub Release with those notes, and publishes the sdist and wheel to PyPI using Trusted Publishing — no API token is stored in this repository.

Merges that do not change the version are a no-op, since PyPI permanently refuses to accept the same version twice.

File format

compress writes a .cim file: an atypical, project-specific container, so most commercial tools will not be able to read it. It stores the image dimensions, three block-layout descriptions (Y, Cb, Cr), and the retained Walsh-Hadamard coefficients as little-endian int16.

Effects

https://raw.githubusercontent.com/oskar-j/walsh-hadamard-transform/master/doc/sample_usage.jpg

Download files

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

Source Distribution

walsh-0.1.2.tar.gz (24.8 kB view details)

Uploaded Source

Built Distribution

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

walsh-0.1.2-py3-none-any.whl (16.7 kB view details)

Uploaded Python 3

File details

Details for the file walsh-0.1.2.tar.gz.

File metadata

  • Download URL: walsh-0.1.2.tar.gz
  • Upload date:
  • Size: 24.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for walsh-0.1.2.tar.gz
Algorithm Hash digest
SHA256 616d085a43881f744e7546206a446903fb3ece17f35bd4b89af97a5f0d5f9c81
MD5 19736bdbdc0c7b1b011fca76ef96c668
BLAKE2b-256 2dfe10c3f9b244682c4587de5a6e897ab2d62b8945193b95b069405760649ff4

See more details on using hashes here.

Provenance

The following attestation bundles were made for walsh-0.1.2.tar.gz:

Publisher: release.yml on oskar-j/walsh-hadamard-transform

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

File details

Details for the file walsh-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: walsh-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 16.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for walsh-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2142c34960ecf387b027666a6f9a1170269e5719378253107ef3e05970e29fa2
MD5 68b6d96080c8a2c74ea8cc9b961649f5
BLAKE2b-256 b70cfa92e24b693e628ee0c218ee7d861de4b39c77ab8909abfffd6be6fa7a26

See more details on using hashes here.

Provenance

The following attestation bundles were made for walsh-0.1.2-py3-none-any.whl:

Publisher: release.yml on oskar-j/walsh-hadamard-transform

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