JPEG-Obscura Project Index

Complete implementation of reversible JPEG region scrambling. v0.5 through v2 multi-region complete, tested, and deployed to production.

Known Issues

Boundary row corruption between adjacent regions (open, 2026-08-31) — visible scattered-block and boundary-line artifacts in v2-MR samples that the reported mean-Δ metrics didn't surface. Root cause not yet confirmed in code.

Quick Links

Core design & requirements — Concept, use cases, phased roadmap

v0.5 detailed spec — Implementation design, test plan

Version History

v0.5: Pixel-Domain Permutation

v0.5 implementation | test results | lessons learned

v1: Pixel-Domain Permutation + XOR Diffusion

v1 design | v1 complete | v1 checkpoint

v1 lessons

v1.5: DCT-Domain Permutation (Lossless)

v1.5 planning | v1.5 complete

✅ DELIVERED: 8× accuracy improvement (1.2 bytes vs v1's 10 bytes)

✅ Samples: 9 files deployed to WebDAV/samples1_v1_5

v2: XMP Metadata Embedding Infrastructure

v2 planning | v2 complete

✅ DELIVERED: Self-contained files with embedded metadata

✅ Samples: 9 files deployed to WebDAV/samples2_v2

v2 Multi-Region: 4-5 Independent Regions Per Image

v2-MR implementation

✅ DELIVERED: Multiple independent encrypted regions per image

⚠️ Quality: 1.09-2.54 bytes mean Δ per region — : this metric did not catch a real boundary-row defect visible on inspection

✅ Samples: 9 files deployed to WebDAV/samples3_v2_multi

Comprehensive Lessons Learned

Complete session lessons — v1.5, v2, multi-region (5 major sections, 50+ lessons)

Quick Highlights

Float Precision Loss: XOR on float32 values isn't self-inverse (24-bit mantissa < 32-bit int range)

DCT Domain: Permutation works on floats; diffusion doesn't (precision loss)

Graceful Fallback: If APP15/XMP not preserved, fallback to external metadata

Multi-Region Keys: salt_with_idx = base_salt + bytes([region_index]) ensures unique keys

Repository

Git: ~/py/jpeg-obscura

Main commits:

• v1.5-implementation (a44bfe2): DCT permutation core

• v2-implementation (35dcbdbe): XMP metadata embedding

• 8a20b8e: v2 multi-region sample generation

Samples

Three WebDAV Directories

1. samples1_v1_5: 9 files (v1.5 single-region)

2. samples2_v2: 9 files (v2 single-region with metadata)

3. samples3_v2_multi: 9 files (v2 multi-region)

Each Sample Set Includes

palace_*: Buckingham Palace facade (5 or 1 region)

detail_*: Architectural stonework (5 or 1 region)

subject_*: Center composition (4 or 1 region)

Files per set: original, scrambled, restored

Quality Metrics

v0.5: 0.23 bytes mean Δ (permutation only)

v1: 9.8 bytes mean Δ (permutation + XOR diffusion in pixel domain)

v1.5: 1.2 bytes mean Δ (DCT permutation only, 8× improvement)

v2: 1.2 bytes mean Δ (same DCT core + metadata infrastructure)

v2-MR: 1.09-2.54 bytes per region (mean — see Known Issues re: outlier blocks this hides)

Security

Permutation: 10^23,000+ possible arrangements (unchanged)

KDF: scrypt N=32768 (~0.1s per attempt)

Per-region: Unique key via region index in salt + passphrase

Next Steps (Future Versions)

v2.1: Reliable APP15/XMP preservation (libjpeg-turbo integration)

v2.1: Fix boundary row corruption (see Known Issues)

v3: GPU acceleration, streaming API, performance optimization

Repository Contents

Source: src/jpeg_obscura/ (8 core modules + CLI)

Tests: test_*.py

Samples: samples/ (v1.5, v2, v2-MR generation scripts)

Documentation: This notes system (not git)

created 2026-08-31  ·  tags ideas, image-processing, jpeg, crypto  ·  updated 2026-08-31  ·  version 2