Metadata-Version: 2.4
Name: seamop
Version: 0.4.1
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Topic :: Utilities
Requires-Dist: cyclopts>=4.22.2,<5
Requires-Dist: numpy>=1.20.0
Requires-Dist: pillow>=8.0.0
Requires-Dist: scipy>=1.7.0
Requires-Dist: pytest>=7.0.0 ; extra == 'dev'
Requires-Dist: pytest-benchmark>=4.0.0 ; extra == 'dev'
Requires-Dist: pytest-cov>=7.1.0 ; extra == 'dev'
Requires-Dist: mypy>=2.3.0 ; extra == 'dev'
Requires-Dist: ruff>=0.9.0 ; extra == 'dev'
Requires-Dist: pytest>=7.0.0 ; extra == 'test'
Requires-Dist: pytest-benchmark>=4.0.0 ; extra == 'test'
Requires-Dist: pytest-cov>=7.1.0 ; extra == 'test'
Provides-Extra: dev
Provides-Extra: test
License-File: LICENSE
Summary: A Python library and CLI for content-aware image resizing using seam carving.
Keywords: seam-carving,image-processing,computer-vision,image-resizing
Author: Albert Kenneth
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Project-URL: Homepage, https://github.com/okinealb/seamop
Project-URL: Issues, https://github.com/okinealb/seamop/issues
Project-URL: Repository, https://github.com/okinealb/seamop.git

# SeamOp

[![CI](https://github.com/okinealb/seamop/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/okinealb/seamop/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

`seamop` is a Python library and command-line tool for content-aware image
resizing. It shrinks images by removing connected paths of low-energy pixels
instead of scaling every pixel or cropping a fixed region.

| Original (1428 × 968) | Resized (1000 × 900) |
| --- | --- |
| ![Original castle image](https://raw.githubusercontent.com/okinealb/seamop/main/examples/large.jpg) | ![Content-aware resized castle image](https://raw.githubusercontent.com/okinealb/seamop/main/examples/large_resized.jpg) |

The current beta supports shrinking by seam removal. Enlargement and seam
insertion are not implemented.

## Installation

Install from PyPI:

```bash
python -m pip install seamop
```

For development, use the locked uv environment:

```bash
uv sync --extra dev --frozen
```

Compatible wheels include the compiled Rust engine. Installing from a source
distribution requires a Rust toolchain to build that engine.

## Command line

Resize the smaller example to 400 by 240 pixels:

```bash
seamop resize examples/medium.jpg 400 240
```

This writes `medium_resized_400x240.jpg` in the current directory. Use
`--output` to choose another path. Existing image outputs are not overwritten.

Preview the pixels that the same resize would remove:

```bash
seamop highlight examples/medium.jpg 400 240
```

Remove ten vertical seams:

```bash
seamop remove examples/medium.jpg --direction vertical --count 10
```

The default backward strategy uses gradient energy. Select pure forward energy
with `--strategy forward`; do not combine it with `--energy`.

Other commands and options are available through the built-in help:

```bash
seamop --help
seamop resize --help
seamop remove --help
seamop highlight --help
```

CLI dimensions use `WIDTH HEIGHT`.

## Python

`resize()` accepts a filesystem path, Pillow image, RGB `uint8` NumPy array, or
nested RGB integer list. It returns a new RGB `uint8` NumPy array without
mutating the input.

```python
from PIL import Image
import seamop

result = seamop.resize(
    "examples/medium.jpg",
    width=400,
    height=240,
)

Image.fromarray(result).save("medium_resized_400x240.jpg")
```

Use `plan()` when the carved result and preview must use the same seam
decisions:

```python
resize_plan = seamop.plan(
    "examples/medium.jpg",
    width=400,
    height=240,
)

preview = resize_plan.preview()
result = resize_plan.result()
```

Both output methods return independent arrays. Calling either method does not
change the plan.

The default strategy is backward seam carving with `GradientEnergy`. The
forward strategy can be selected explicitly:

```python
from seamop import CarvingStrategy

result = seamop.resize(
    "examples/medium.jpg",
    width=400,
    height=240,
    strategy=CarvingStrategy.FORWARD,
)
```

Backward carving also accepts built-in or custom energy callables through
`energy=`. Pure forward carving does not accept an energy callable.

The default gradient path and forward strategy run through the compiled Rust
engine. Sobel, Laplacian, and custom energy callables remain on the Python
path.

See the [Python API guide](docs/api.md) for input rules, custom energy methods,
errors, and the advanced seam-calculation interface.

## Documentation

- [Python API](docs/api.md)
- [Algorithm overview](docs/algorithm-overview.md)
- [Architecture](docs/architecture.md)
- [Design decisions](docs/design-decisions.md)
- [Benchmarking](docs/benchmarking.md)

## Development

Run the repository checks from the project root:

```bash
uv run --frozen ruff check src tests benchmarks
uv run --frozen ruff format --check src tests benchmarks
uv run --frozen mypy
uv run --frozen pytest --cov
uv run --frozen pytest --doctest-modules src/seamop
```

Benchmarks run separately:

```bash
uv run --frozen pytest benchmarks
```

## Limitations

- Only shrinking is supported.
- Width is reduced before height when both dimensions change.
- Results depend on the image and selected carving strategy and energy method.
- Large reductions can distort important content.

## License

[MIT](LICENSE)

