mono/packages/media/cpp/docs/product.md

253 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# pm-image: Fast image resizing for CLI, servers, and Windows Explorer
**pm-image** is a native **C++** image toolkit built on **libvips** — the same high-performance engine behind tools like **Sharp** (Node.js). One binary gives you a **command-line interface**, an **HTTP REST** server, and **line-delimited JSON IPC** for automation. On Windows, optional **Explorer** integration adds right-click **resize** and **convert** workflows without opening another app.
Whether you batch photos for the web, power a local resize API, or shrink folders of RAW and HEIC files from the desktop, pm-image keeps pipelines predictable: **decode → process → encode**, with **Sharp-like** options (fit modes, quality, metadata stripping, smart crop) and optional **disk caching** so repeat jobs stay instant.
---
[Download - Windows - AMD 64](https://service.polymech.info/api/vfs/get/software/pm-image-resize/v1.zip?t=1776153671416&download=1) | [Source Code](https://git.polymech.info/polymech/mono/src/branch/master/packages/media)
## Who is this for?
- **Developers** who want a **single native binary** (no Node runtime) for resize jobs in scripts, CI, or sidecar services.
- **Windows power users** who want **context-menu** resize presets and JPG conversion from File Explorer.
- **Integrators** who need **REST** (`POST /v1/resize` as **JSON** with server paths, or **multipart** upload with the **resized image** returned in the body) or **IPC** (one JSON line per request) with the same JSON schema as the CLI for path-based jobs.
---
## How to resize images (quick start)
### 1. Command line — one file
Install or build **pm-image**, then run `resize` with input and output paths. By default, the image **fits inside** your max width and height **without enlarging** (unless you allow enlargement).
```bash
pm-image resize photo.jpg out.jpg --max-width 1920 --max-height 1080
```
- **Quality** (JPEG, WebP, AVIF): use `-q` / `quality` (for example `-q 85`).
- **Output format**: use the **destination extension** (`.webp`, `.avif`, `.jpg`) or `--format` when the path is ambiguous.
### 2. Fit modes — not every resize is “shrink to fit”
| Goal | What to use |
|------|-------------|
| **Fit inside a box** (keep aspect ratio, no crop) | Default behavior with `--max-width` / `--max-height`; optional `--fit inside` style semantics via `fit` in JSON. |
| **Square avatar or thumbnail (crop)** | Same `--max-width` and `--max-height` (e.g. 512), `--fit cover`, optional `--position attention` or `entropy` for smarter crops. |
| **Square with padding (no crop)** | `--fit contain` plus `--background '#rrggbb'` for letterboxing. |
| **Exact dimensions by stretching** | `--fit fill` (distorts if aspect ratios differ). |
Examples (see the package README for full flag lists):
```bash
# Thumbnail: 400×400 cover crop
pm-image resize in.jpg thumb.jpg --fit cover --max-width 400 --max-height 400
# Padded square on a dark canvas
pm-image resize wide.jpg square.jpg --fit contain --max-width 800 --max-height 800 --background '#111111'
```
### 3. Batch paths and folders
- Use **globs** (`*`, `?`, `**`) in the input to process many files in one invocation.
- Point output to a **directory** (often with a trailing `/` or `\`) or use **templates** like `${SRC_DIR}`, `${SRC_NAME}`, `${SRC_FILE_EXT}` to mirror or rename outputs per file.
```bash
pm-image resize './photos/**/*.jpg' ./out/
pm-image resize --src './shots/*.jpg' --dst '${SRC_DIR}/${SRC_NAME}_medium.jpg' --max-width 800
```
### 4. HTTP API
Start the server (`serve`). **`POST /v1/resize`** supports two modes:
- **JSON** (`Content-Type: application/json`): **`input`** and **`output`** paths on the machine running the server, plus the same resize fields as the CLI (`max_width`, `max_height`, `fit`, `quality`, glob batch, cache, …). Response is JSON (`ok`, and optionally `count` / `outputs` for batches).
- **Multipart upload** (`Content-Type: multipart/form-data`): send the image in a part named **`file`**, **`image`**, or **`upload`**. Add optional fields (`max_width`, `format`, …) as additional form parts. The **response body is the encoded image** (not JSON), with `Content-Type` set from the output format (default **JPEG** if `format` is omitted). Uploads do not use the on-disk output cache.
See the **[C++ README](../README.md)** (`serve` — HTTP REST) for `curl` examples.
### 5. Windows — resize from Explorer
After **`pm-image register-explorer`** (or the NSIS installer), use the **PM-Media** menu on images or folders for preset widths, **in place** or **copy**, plus **convert to JPG**. Override preset widths with `--widths` when registering.
### 6. Optional: Windows GUI
On Windows, `pm-image resize --ui` opens a **native** dialog to pick files and options (no `--src` / `--dst` with `--ui`).
---
## Features at a glance
- **libvips-backed** resizing, rotation, flip/flop, EXIF **autorotate**, metadata **strip** (defaults match common web workflows).
- **Formats**: JPEG, PNG, WebP, TIFF; **AVIF / HEIC** when your libvips build includes HEIF; other formats depend on libvips loaders/savers.
- **HTTP(S) URLs** as `input` (fetched via libcurl) for download-and-resize pipelines.
- **REST multipart** upload: resize without writing `input`/`output` paths — return the image directly to the client.
- **Output cache**: SHA-256 keyed by path, size, mtime, and options — cache hits skip re-encoding (JSON/CLI/IPC path-based jobs; not used for multipart upload responses).
For prerequisites, build steps, installer, and the full option tables, see the **[C++ README](../README.md)**.
---
## FAQ (questions and answers)
### What is pm-image?
**pm-image** is a CMake-built executable that exposes image resizing and related operations through **CLI**, **`serve` (REST)**, and **`ipc` (JSON lines)**. Processing uses **libvips**, aligned with a **Sharp-like** option model for familiarity.
### Is pm-image the same as Sharp?
No — **Sharp** is a **Node.js** library; **pm-image** is a **standalone native** program. Both lean on **libvips**, so concepts like `fit`, `position`, `kernel`, and quality map closely. See the READMEs “Sharp-like options” table for field names (`without_enlargement`, `strip_metadata`, etc.).
### How do I resize an image to an exact width?
Use **`--max-width`** (and optionally **`--max-height`**). The image scales **down** (or up if you allow enlargement) to respect those bounds and the chosen **`fit`** mode. For a fixed **width-only** workflow, set a large `max_height` or use JSON/`resize` options that match your desired behavior.
### How do I resize without losing quality?
**Resizing always re-encodes** for raster formats; “lossless” depends on format:
- For **JPEG**, use a high **`-q`** (e.g. 9095) and avoid repeated saves.
- For **PNG**, resizing may still recompress; use **PNG compression** settings as needed.
- Prefer **WebP** or **AVIF** with tuned **quality** for smaller files at a given visual fidelity.
**without enlargement** defaults to **true**, so small images are not upscaled unless you opt in.
### How do I batch resize images in a folder?
Use a **glob** for `input` and a **directory** or **template** for `output`. Multiple matches are processed in one command; see **Batch paths & cache** in the README for rules on trailing slashes and `${SRC_*}` variables.
### Can I resize images from URLs?
Yes. Pass an **`http://` or `https://`** URL as `input`. Redirects are followed; timeouts and redirect limits are configurable (`--url-timeout`, `--url-max-redirects`).
### Does pm-image work on Windows?
Yes. Use the **vips dev bundle** (`npm run setup:vips` from the package), build **pm-image**, and optionally install **NSIS** output for **`pm-image-setup.exe`**, PATH, DLLs, and Explorer scripts. **register-explorer** adds context menus for resize and convert.
### How does caching work?
When enabled, outputs are stored under a **cache directory** (default under the process working directory), keyed by a **SHA-256** hash of input identity, file metadata, and **all** resize options. Identical jobs reuse cached bytes without running libvips again.
### What is IPC for?
**ipc** accepts **one JSON object per line** over TCP (or a Unix socket on non-Windows), ideal for **local daemons** or tools that want a simple request/response channel without HTTP overhead.
### Where is the full API reference?
- **CLI**: `pm-image --help`, `pm-image resize --help`.
- **Library-level image API** (underlying engine): [libvips `VipsImage`](https://www.libvips.org/API/current/class.Image.html).
---
## Related documentation
## CLI examples
Paths below use Unix style; on Windows run `pm-image.exe` and use `.\` or full paths as needed.
### Help and version
```bash
pm-image --help
pm-image resize --help
pm-image -v
```
### `resize` — fit inside a box (default), write WebP / AVIF by extension
```bash
# Max 800×600, stay inside the box, Lanczos3 (default), write JPEG quality 85 (default)
pm-image resize photo.jpg out.jpg --max-width 800 --max-height 600
# Same, explicit quality
pm-image resize photo.jpg out.jpg --max-width 800 --max-height 600 -q 90
# WebP output (quality applies)
pm-image resize photo.jpg thumb.webp --max-width 400 --max-height 400 -q 82
# AVIF output (quality applies; needs HEIF/AVIF support in your libvips build)
pm-image resize photo.png out.avif --max-width 1200 --max-height 1200 -q 50
# Force output format when the path has no extension you trust
pm-image resize in.tif /tmp/out --format webp --max-width 512
```
### `resize` — square images (1:1)
Use the **same** `--max-width` and `--max-height` (that value is the square side in pixels). Pick **`--fit`**:
| `fit` | Result |
|-------|--------|
| **`cover`** | Fills the square; crops overflow (default crop: `--position centre`, or `attention` / `entropy` for smart crop). |
| **`contain`** | Full image inside the square; **letterboxing** on two sides if needed (`--background`). |
| **`fill`** | Stretches to the square (ignores aspect ratio). |
```bash
# 512×512 crop-to-square (avatars, thumbnails)
pm-image resize portrait.jpg avatar.jpg --fit cover --max-width 512 --max-height 512
# 1080×1080 WebP, smart crop on subject
pm-image resize product.png grid.webp --fit cover --max-width 1080 --max-height 1080 --position attention -q 85
# Square canvas, no crop — padded bands with a colour
pm-image resize panoramic.jpg square.jpg --fit contain --max-width 800 --max-height 800 --background '#111111'
# Exact square by stretching (rare)
pm-image resize any.jpg out.jpg --fit fill --max-width 256 --max-height 256
```
**REST / IPC JSON:** e.g. `"max_width": 512, "max_height": 512, "fit": "cover", "position": "attention"`.
### `resize` — cover (crop), contain (letterbox), rotate / flip
```bash
# Cover: fill 1200×630, crop centre (use --position attention for smart crop)
pm-image resize wide.jpg social.jpg --fit cover --max-width 1200 --max-height 630
# Contain: fit inside 800×600 canvas, letterbox with a background
pm-image resize logo.png padded.png --fit contain --max-width 800 --max-height 600 --background '#1a1a1a'
# EXIF autorotate (default), then rotate 90° CCW, vertical flip
pm-image resize img.jpg rotated.jpg --max-width 1024 --rotate 90 --flip
```
### `serve` — HTTP REST
```bash
# Default: http://127.0.0.1:8080 — GET /health, POST /v1/resize (JSON or multipart)
pm-image serve --host 127.0.0.1 -p 8080
```
**Multipart** (response = image bytes):
```bash
curl -s -o thumb.webp -X POST http://127.0.0.1:8080/v1/resize \
-F "file=@/path/in.png" \
-F "max_width=400" \
-F "format=webp"
```
**JSON** (paths must be readable/writable by the server process):
```bash
curl -s http://127.0.0.1:8080/health
curl -s -X POST http://127.0.0.1:8080/v1/resize \
-H 'Content-Type: application/json' \
-d '{"input":"/path/in.png","output":"/path/out.webp","max_width":400,"quality":80}'
```
Optional JSON: `"cache":false`, `"expand_glob":false`, `"cache_dir":"..."` — see **Batch paths & cache** in the [README](../README.md).
### `ipc` — one JSON line per connection (TCP; Unix socket on Linux/macOS)
```bash
pm-image ipc --host 127.0.0.1 -p 9333 --cache-dir ./cache/images
# elsewhere: send a single line, read one line back, e.g.
# {"input":"/tmp/a.jpg","output":"/tmp/b.webp","max_width":320,"format":"webp","cache":true}
```
Same JSON fields as REST (`input`, `output`, globs, `expand_glob`, `cache`, `cache_dir`, resize options).