Metadata-Version: 2.4
Name: imagestego
Version: 2.7.1
Summary: Multimedia Obfuscation & Steganography Toolkit (image & audio steganography with Reed-Solomon error correction)
Author-email: Equinox_Wangstu <wangstu@126.com>
License: MIT
Keywords: steganography,obfuscation,image,video,encryption
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Multimedia :: Graphics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: Pillow>=9.0
Requires-Dist: cryptography>=41.0
Requires-Dist: scipy>=1.10
Requires-Dist: moviepy>=2.0
Provides-Extra: gui
Requires-Dist: pywebio; extra == "gui"
Provides-Extra: purepix
Requires-Dist: purepix>=0.3.0; extra == "purepix"
Provides-Extra: progress
Requires-Dist: tqdm; extra == "progress"
Provides-Extra: f5
Requires-Dist: jpegio>=0.2.8; extra == "f5"
Provides-Extra: speed
Requires-Dist: reedsolo>=1.7; extra == "speed"
Requires-Dist: numba>=0.58; extra == "speed"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Dynamic: license-file

# ImageStego

Multimedia Obfuscation & Steganography Toolkit — a Python library for image/video obfuscation and message hiding.

## Features

### Obfuscation (Image / GIF / MP4)

| Algorithm | Description |
|-----------|-------------|
| Pixel Scramble | Pseudo-random pixel permutation |
| Block Scramble | Block-level shuffling |
| Arnold Cat Map | Classic chaotic map transform |
| Baker's Map | Baker's map + optional XOR encryption |
| Henon Map | Henon chaotic system |
| Logistic Map | Logistic chaotic sequence |
| DNA Encoding | DNA-based pixel encoding |
| Spiral Scan | Spiral-order pixel rearrangement |

### Steganography

| Method | Description |
|--------|-------------|
| LSB | Least Significant Bit embedding |
| LSB Edge | Full-image LSB with optional seeded position shuffling |
| DCT | Frequency-domain (DCT coefficient) embedding |
| DWT | Wavelet-domain (Haar DWT) embedding |
| PVD | Pixel Value Differencing |
| Spread Spectrum | QIM-based spread spectrum |
| Audio LSB | Integer PCM WAV embedding (8/16/32-bit) |

All steganography methods support **Fernet encryption**, **timestamps**, and optional **Reed–Solomon correction** (`ecc_nsym=0..254`). Use the same seed, password, correction setting and method-specific extraction parameters when reading a message.

Image steganography outputs must use PNG, BMP or TIFF. Keep the original downloaded file: resizing, recompression and editing can destroy the message. RS does not protect the length header or guarantee recovery beyond its correction capacity. DCT/DWT/QIM may visibly alter saturated carriers to keep embedded bits recoverable.

Legacy compatibility: extract old PVD files with `seed=None`, because earlier versions ignored the seed. Old `lsb_edge(seed=None)` files used an unrecoverable random ordering; the new default is deterministic. Explicit seeded LSB Edge layouts remain compatible.

## Installation

```bash
pip install imagestego
```

Optional dependencies:

```bash
pip install "imagestego[gui]"       # Web GUI (PyWebIO)
pip install "imagestego[purepix]"   # PurePix image tools (Python >= 3.10)
pip install "imagestego[progress]"  # Progress bars (tqdm)
```

PurePix adds PNG/BMP/QOI/PPM carrier conversion and RGB PSNR / global-luminance SSIM comparison. Large images are measured using thumbnails up to 1024×1024, marked as estimates. Conversion is for preparing carriers, not re-encoding stego outputs: restoration metadata may be lost even when pixels are unchanged.

The native toolbox also offers aspect-preserving resize, crop, 90° rotation, mirroring, thresholding and Bayer ordered dithering through PurePix's own implementations. Preparation uses 8-bit RGB/RGBA and exports a new PNG of at most 4 million pixels; sources are limited to 16 million pixels. Resize targets the longest side (1–2000 pixels). Nearest-neighbor geometry retains alpha; bilinear resize is restricted to RGB to avoid transparent-edge fringes. Thresholding and dithering produce grayscale and discard alpha. These operations are for preparing carriers **before embedding**, not editing existing stego files.

Read-only histogram/edge analysis uses native per-channel histograms, including alpha, and Sobel luminance edges. Histograms use at most 512×512 nearest-neighbor samples; edges use at most 256×256, without upscaling. The GUI marks sampled statistics, plots channel distributions, and downloads complete 256-bin counts/statistics as JSON plus the edge PNG. Edge previews ignore alpha. Neither texture nor histogram statistics are security, capacity or robustness scores. The local APIs are `imagestego.image_tools.prepare_with_purepix(...)` and `analyze_with_purepix(...)`; they do not overwrite existing output files.

## Quick Start

### Obfuscation

```python
from imagestego import pixel_obfuscate, pixel_deobfuscate

# Encrypt
pixel_obfuscate("input.png", "encrypted.png", seed=42)

# Decrypt
pixel_deobfuscate("encrypted.png", "restored.png", seed=42)
```

### Multi-layer Pipeline

```python
from imagestego import ObfuscationPipeline

pipeline = ObfuscationPipeline()
pipeline.add_layer("arnold", iterations=30)
pipeline.add_layer("bakers", iterations=10, password="secret")
pipeline.add_layer("dna")

sidecar = pipeline.encrypt("input.png", "output.png")
# Generates output.png + output.layers.json

pipeline.decrypt("output.png", "restored.png", sidecar=sidecar, passwords={1: "secret"})
```

Keep both the output image and its layer JSON. New sidecars do not store passwords; supply them by original zero-based layer index. The CLI and GUI prompt for required passwords separately. Obfuscation is not cryptographic protection, and wrong obfuscation passwords may produce an incorrect image without an authentication error.

### Steganography

```python
from imagestego import lsb_embed_message, lsb_extract_message

# Hide a message
lsb_embed_message("cover.png", "Hello World", "stego.png", password="key123")

# Extract
result = lsb_extract_message("stego.png", password="key123")
print(result["message"])
```

### Batch Processing

```python
from imagestego.batch_processor import batch_obfuscate

result = batch_obfuscate(
    input_dir="./images",
    output_dir="./output",
    method="arnold",
    params={"iterations": 20},
    max_workers=4,
)
print(result)  # Total=10, Success=10, Failed=0
```

### Batch Steganography and Algorithm Comparison

The GUI's **批量隐写 / 提取** tool accepts 1–20 static images, up to 50 MiB each and 100 MiB total. A batch uses one method and one set of parameters; embedding uses the same message for every image. Files run serially, and a failed image does not stop the rest. Each successful embed must pass an immediate extraction self-check before download.

Download the ZIP to keep successful PNGs or extracted UTF-8 text, extraction profiles, and `report.json`. Archive names are numeric; original upload names appear only as report labels. Failed items have no artifacts. Reports and profiles contain neither passwords nor message bodies; extracted TXT files do contain the message. Downloads are limited to 200 MiB of uncompressed artifacts. Keep successful outputs unchanged and use separate extraction batches for different settings.

The **算法对比台** runs the six image methods on the same carrier and message, using shared seed/password/ECC settings and each method's own defaults. It reports actual capacity, required payload bits, embedding plus extraction-check time, and optional PurePix quality metrics. Over-capacity methods fail independently. Quality measurement is excluded from timing; a missing or failed metric does not invalidate a verified output. Single-run timings depend on system load and caching, and image quality is not a robustness score or an automatic recommendation.

Both tools are also available as local Python APIs:

```python
from imagestego.stego_tools import run_stego_batch, compare_stego_methods

# The output directory must already exist.
rows = run_stego_batch(
    [{"name": "cover.png", "path": "cover.png"}], "./output",
    method="lsb", operation="embed", message="Hello", settings={"seed": 42},
)
comparison = compare_stego_methods("cover.png", "./output", message="Hello", seed=42)
```

### Continuous Processing Workbench

The **连续处理工作台** runs up to eight editable PurePix preparation steps, followed by image-message embedding and immediate extraction verification. Add, edit, move or delete resize/crop/rotation/mirror/threshold/dither steps; the empty chain embeds directly. Only the final prepared carrier and verified stego image are offered, alongside extraction settings, a processing report and a reusable step template. Native PurePix preparation results also have a **用此结果继续隐写** button: the result transfers in memory without downloading and uploading it again.

Preparation is strictly **before** embedding and may destroy existing hidden data or restoration metadata. Inputs are limited to 50 MiB / 16 million pixels, each native step to 4 million output pixels, and retained artifacts to 100 MiB. Crop coordinates refer to the current step's input. Geometry preserves alpha where supported, but threshold/dither discard it and embedding always uses RGB. Quality compares the final prepared carrier against its stego output, not the original unprocessed image. Failed chains remove their intermediate artifacts and allow retries with retained uploads and parameters.

Processing templates are strict UTF-8 JSON, at most 32 KiB, with format `imagestego-processing-chain`, version `1`, `steps`, `method`, embedding `params`, `include_timestamp` and `password_required`. They contain no passwords, messages, filenames, upload bytes or paths; they are not extraction profiles. Import replaces the method and steps, while the user supplies the message and any required password separately. Unknown fields, non-object parameters, duplicate keys and invalid numbers are rejected.

```python
from imagestego.processing_chain import run_processing_chain

result = run_processing_chain(
    "cover.png", "./output", method="lsb", message="Hello",
    steps=[{"operation": "resize", "params": {"max_side": 1024}}],
)
# result contains output_path, prepared_path, profile_path, template_path and report_path.
```

### File Attachments

The **文件附件隐写** tool hides or extracts opaque file bytes using the six image methods and their existing optional password encryption and RS correction. Attachments may be empty, but cannot exceed 1 MiB; actual carrier capacity is often much lower. A canonical JSON/base64 envelope adds approximately one third to the file size, plus metadata, timestamp, encryption and correction overhead. Exact bit requirements are checked before embedding. No compression, archive unpacking, file preview or execution occurs. Ordinary legacy text is not silently interpreted as an attachment; legacy text steganography remains unchanged.

Download the verified PNG and its existing extraction profile, then import that profile in the attachment tool and supply the password separately. Extracted filenames are Unicode-normalized, stripped of directory components, controls and Windows-unsafe characters/device names, and bounded to 180 UTF-8 bytes. They are browser suggestions only: local output paths are independently generated `.bin` files. Invalid envelopes, wrong passwords and checksum failures yield no attachment download. Never run untrusted downloaded files.

The v1 wire envelope is `ImageStego-Attachment:1\n` followed by compact, key-sorted UTF-8 JSON containing `format`, `version`, `name`, `size`, `sha256` and base64 `data`. The checksum is SHA-256 over the UTF-8 magic, canonical metadata (`format`, `name`, `size`, `version`), a NUL byte, and raw file bytes. It detects corruption of content and metadata, **not authenticity**; an adversary can recalculate an unkeyed checksum. Optional outer Fernet encryption authenticates the payload. Profiles never contain the filename, checksum, attachment bytes or password.

```python
from imagestego.attachments import run_attachment_item

embedded = run_attachment_item(
    "cover.png", "./output", method="lsb", operation="embed",
    file_bytes=b"example attachment", suggested_name="note.txt", password="example-password",
)
extracted = run_attachment_item(
    embedded["output_path"], "./output", method="lsb", operation="extract",
    password="example-password",
)
# extracted["output_path"] holds bytes; extracted["name"] is a suggested download name only.
```

### Controlled Robustness Lab

The **受控抗损实验室** first embeds a known message and validates a mandatory unmodified control. Each selected mutation independently starts from that same embedded baseline, never from the previous mutation or the original cover:

- JPEG re-encoding: integer quality 30–100, fixed 4:4:4 sampling; quality 100 is still lossy.
- Round-trip resizing: `0 < scale <= 1`, LANCZOS reduction followed by restoration to the exact original width and height; scale 1 is an identity control.
- Independent RGB Gaussian noise: standard deviation 0–20, deterministic PCG64 seed 0–4294967295, nearest-even rounding and clipping to 0–255; zero noise is an identity control.

Input is limited to 4 million pixels / 50 MiB; artifact and ZIP limits are 100 MiB. A row distinguishes exact message recovery, message mismatch, extraction failure, experiment creation failure or skipped work. Quality is measured **against the unmodified embedded baseline**, using optional PurePix RGB PSNR and global-luminance SSIM, with thumbnails up to 1024×1024 explicitly marked. This is not a security score, a stable performance benchmark, a BER estimate or a general robustness guarantee. Editing ECC or other settings reruns embedding and the experiments; RS still does not protect the length header.

ZIP names are numeric. `001.png` and `001.params.json` appear only when the baseline validates; mutated files remain downloadable even if extraction fails and are explicitly labeled experimental, not trustworthy stego outputs. A failed baseline gives a report-only ZIP. Reports contain parameters, measured outcomes and timings, but no passwords, message text, decoded text or internal paths. Infinite PSNR is serialized as the string `"Infinity"`.

```python
from imagestego.robustness import run_robustness_lab

result = run_robustness_lab(
    "cover.png", "./output", method="lsb", message="Known test message",
    experiments=["jpeg", "resize_roundtrip", "noise"],
    jpeg_quality=90, resize_scale=0.75, noise_sigma=2.0, noise_seed=7,
)
# result has rows, report, artifacts (archive-name -> local path) and work_dir.
```

All three APIs require an existing output directory. Successful files remain caller-owned; use an outer `tempfile.TemporaryDirectory()` when results should be temporary. The GUI cleans its temporary files after capturing downloads, and files remain local unless explicitly shared by the user.

### Extraction Profiles

After a single-file embed, download both the original PNG/WAV and its `.params.json` profile. In the single-file or batch tool's first form, import the JSON to switch to extraction and prefill the method, seed, ECC and required method-specific settings. Passwords must be entered separately. Single-file profiles support WAV; batch and comparison tools support images only.

Profiles are strict UTF-8 JSON, at most 16 KiB. They contain only a format/version marker, method, extraction settings and a `password_required` flag. They never store passwords, message bodies or carrier identity; they are reusable settings, not authentication or proof that a carrier is intact. DCT/DWT embedding strength is omitted because extraction does not need it; spread-spectrum strength is retained. Unknown fields, duplicate JSON keys and unsupported versions are rejected. Pipeline `.layers.json` files and ZIP archives are not extraction profiles.

## CLI

```bash
imagestego          # Interactive CLI
imagestego-gui      # Web GUI (requires pywebio)
```

The GUI binds to `127.0.0.1:8080` with local static assets and debug mode disabled. From a source checkout, use `python -m imagestego.gui`. It provides capacity checks, immediate embed/extract self-checks, retained-input retries, password-masked pipeline editors and a graph fit-to-view control. MP4 processing keeps decoded RGB frames lossless, but source compression and audio transcoding can still lose information.

## Requirements

- Python >= 3.9
- numpy, Pillow, cryptography, scipy, moviepy

## License

MIT
