Skip to content

Codebase audit improvements + programmatic before/after previews for all operations#6

Merged
subwaymatch merged 3 commits into
mainfrom
claude/codebase-review-previews-qggyf1
Jul 10, 2026
Merged

Codebase audit improvements + programmatic before/after previews for all operations#6
subwaymatch merged 3 commits into
mainfrom
claude/codebase-review-previews-qggyf1

Conversation

@subwaymatch

Copy link
Copy Markdown
Owner

Summary

This PR delivers a codebase audit with fixes, and restores the old README's before/after sample images — now generated programmatically for every operation.

Audit improvements

  • Removed the matplotlib dependency. It was installed (~40 MB with transitive deps) for exactly two functions. layeris.color.hsv now provides pure-NumPy rgb_to_hsv/hsv_to_rgb that are bit-identical to matplotlib's implementations (verified on random and adversarial inputs). Runtime deps are now just NumPy, Pillow, Requests.
  • from_url hardening: request timeout + raise_for_status(), so a 404 raises a clear HTTPError instead of a cryptic image-decoding failure.
  • EXIF orientation is applied on load, so phone/camera photos open upright.
  • Input validation with actionable errors: constructor rejects non-float dtypes and bad shapes; blend opacity must be in [0, 1]; curve validates channel letters and control-point count; resize rejects non-positive sizes; malformed hex colours raise ValueError (and #rgb shorthand is now supported).
  • Packaging fixes: added the [dev] extra that the README referenced but didn't exist; refreshed requirements.txt (was pinned to 2019 versions inconsistent with pyproject.toml); replaced the deprecated Image.LANCZOS alias; version bumped to 0.4.0.
  • CI: GitHub Actions workflow running the test matrix on Python 3.10–3.13 plus a preview-generation smoke test.
  • Tests: suite grew from 141 to 187, covering the HSV port (known values, roundtrip, hue wrap), hex parsing, and all new validation paths.

Programmatic before/after previews

  • scripts/generate_previews.py regenerates the whole gallery deterministically with python scripts/generate_previews.py. A single operations table drives:
    • docs/previews/*.jpg — 24 side-by-side before/after composites (left = input, right = result), one per operation: 9 adjustments, all 14 blend modes, and a chained pipeline;
    • docs/index.html — a static gallery page, ready for GitHub Pages (enable Settings → Pages → Deploy from a branch → /docs);
    • the README gallery markdown (--markdown), so snippets, descriptions, and images can't drift apart.
  • Previews reuse the original demo photo and the old README's blend colours; darken-group modes are applied to a grayscale base, mirroring the original sample images.
  • README now shows every operation with its description, snippet, and before/after image, plus regeneration instructions.

Test plan

  • pytest — 187 passed (run with matplotlib uninstalled to prove the dependency is gone)
  • HSV port verified bit-identical to matplotlib.colors on random arrays, primaries, grays, and boundary values
  • python scripts/generate_previews.py run twice — byte-identical output (deterministic)
  • docs/index.html rendered in headless Chromium and visually inspected
  • CI workflow added (will run on this PR's branch after merge to main; pull_request events run it immediately)

🤖 Generated with Claude Code

https://claude.ai/code/session_01KHVMC2EHFz4h5oiFTuD2Hs


Generated by Claude Code

claude added 3 commits July 10, 2026 14:11
- Port rgb_to_hsv/hsv_to_rgb to pure NumPy (bit-identical to the
  matplotlib implementation) in layeris.color.hsv; matplotlib was a
  ~40MB install pulled in for those two functions only
- Harden LayerImage.from_url: request timeout + raise_for_status so
  HTTP errors fail clearly instead of as image-decoding errors
- Apply EXIF orientation on load so photos open upright
- Validate constructor input (float dtype, HxWx3|4 shape), blend
  opacity range, curve channels/control points, and resize dimensions
  with actionable error messages
- Support #rgb shorthand hex colours and reject malformed hex strings
- Use Image.Resampling.LANCZOS (Pillow>=9.1) instead of deprecated alias
- Add __repr__, simplify channel_adjust via ND np.interp
- Add [dev] extra (README referenced it but it did not exist), refresh
  stale requirements.txt (pinned 2019 versions), bump version to 0.4.0
- Extend test suite from 141 to 187 tests covering all of the above

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHVMC2EHFz4h5oiFTuD2Hs
- scripts/generate_previews.py renders a side-by-side before/after
  JPEG for every operation (9 adjustments, 14 blend modes, chaining)
  using layeris itself; one operations table drives the images, the
  docs/index.html static gallery (GitHub Pages ready via /docs), and
  the README markdown (--markdown)
- Previews use the original demo photo and the old README's blend
  colours; darken-group modes apply to a grayscale base as in the
  original samples; output is deterministic
- GitHub Actions workflow runs the test matrix (3.10-3.13) plus a
  preview-generation smoke test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHVMC2EHFz4h5oiFTuD2Hs
The operation gallery section is emitted by
scripts/generate_previews.py --markdown, so snippets, descriptions and
images stay in sync with the generator. Also documents the [dev]
extra, the lighter dependency footprint, and how to publish the
docs gallery with GitHub Pages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHVMC2EHFz4h5oiFTuD2Hs
@subwaymatch subwaymatch merged commit 172d338 into main Jul 10, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants