Date: 2026-08-31 • Predecessor: v1-implementation (b6833c6) • Status: PLANNING PHASE
v1 achieves: mean Δ = 9.8 bytes (acceptable for security)
Limitation: restoration Δ higher than ideal due to JPEG re-encoding
Root cause: Diffuse → JPEG lossy → un-diffuse = artifacts cascade
Work on DCT coefficients (JPEG intermediate representation)
Avoid lossy requantization (operations lossless between blocks)
Result: Byte-exact restoration possible (target: <1.0 byte Δ)
Use jpegtran or mozjpeg for lossless DCT coefficient extraction
Parse JPEG structure and extract coefficients (8x8 blocks)
Apply Fisher-Yates permutation to DCT coefficient blocks
Key: perm_key (same as v1)
XOR each DCT coefficient with deterministic stream
Key: diffusion_key (same as v1)
Challenge: Coefficients are signed (-1024 to 1023), handle carefully
Reconstruct DCT blocks with permuted+diffused coefficients
NO re-quantization (use original QT values)
Load JPEG → extract DCT → un-diffuse → un-permute → rebuild JPEG
Use jpeglib Python bindings + subprocess jpegtran
Trade-off: Not optimal performance, but fast to implement
Allows focused development on algorithm, not FFI complexity
Problem: DCT range is -1024 to 1023 (signed 11-bit)
Option a: Convert to unsigned, XOR, convert back (cleanest)
Option b: XOR only low 8 bits, preserve sign
Option c: XOR as 16-bit signed integer
Recommendation: Option (a) is cleanest but verify performance impact
Problem: DC (index 0) has range 0-255; AC has -127 to 127
Option a: Handle DC/AC separately (different streams)
Option b: Treat all uniformly (simpler)
Recommendation: Option (a) for better security
Key insight: Work directly on quantized coefficients
Benefit: Avoid floating-point, preserve precision
Verification: Confirm jpegtran preserves quantized coefficients
• Restore doesn't need external --salt/--region parameters
• Self-contained JPEG files (portable)
• Simpler CLI (metadata auto-detection)
CLI auto-detects APP15 metadata; falls back to external params
v0.5/v1 files still work (but need external params)
v1.5 files easier to use (embedded metadata)
✓ DCT coefficient round-trip (JPEG → DCT → JPEG → DCT)
✓ Permutation of coefficient blocks
✓ Diffusion of coefficients
✓ Self-inverse properties
✓ Full scramble → restore round-trip (target mean Δ < 1.0 byte)
✓ APP15 metadata embedding and extraction
✓ Backward compatibility (restore v0.5/v1 files)
✓ Compare v0.5/v1/v1.5 samples side-by-side
✓ Target: v1.5 Δ < 1.0 byte (vs v1's 8.7-9.2 bytes)
Phase 1: Tooling evaluation (0.5 day)
Phase 2: Coefficient access (0.5 day)
Phase 3: Permutation in coefficient domain (0.5 day)
Phase 4: Coefficient diffusion (0.5 day)
Phase 5: Metadata embedding (0.5 day)
Phase 6: Full integration (0.5 day)
Phase 7: Testing & validation (1 day)
JPEG structure complexity (many edge cases)
jpegtran bindings availability and stability
Coefficient representation (overflow handling)
Start with simple uncompressed JPEGs
Use existing v1 samples for extensive testing
Have backup plan (libjpeg-turbo if jpegtran unavailable)
✓ Byte-exact restoration (mean Δ < 1.0 byte)
✓ Backward compatibility with v0.5/v1
✓ Auto-detection working
✓ APP15 metadata embedding
✓ Sample demonstrations
✓ Performance comparable to v1 (~1 second per 4K)
Coefficient-domain permutation + diffusion (lossless within quantization)
Accepts boundary-ring lossy for chroma-subsampling/MCU alignment
Rigorous coefficient precision (no overflow fallback)
Exact MCU/restart-marker alignment (true lossless everywhere)
Progressive JPEG support
□ Confirm JPEG tooling approach (jpegtran vs libjpeg-turbo)
□ Decide coefficient representation (handle signed integers)
□ Design APP15 format
□ Confirm target restoration Δ < 1.0 byte achievable