tenma / image
Image size and scaled WebP copies on Tenma, decoded off the event loop by a native plugin, with limits against decompression bombs.
Requires
- php: >=8.5
Requires (Dev)
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^13.3
- tenma/stubs: ^0.2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-10-31 21:41:05 UTC
README
Image size and scaled WebP copies on Tenma. A native plugin decodes, scales and encodes on threads of its own, so a request that converts an image waits in its fiber while the server goes on. Meant for untrusted bytes, such as pictures downloaded from elsewhere: hard limits apply before anything is decoded.
use Tenma\Image\Picture; [$width, $height, $extension] = Picture::measure($bytes); // [1200, 1800, 'jpg'] $webp = Picture::webp($bytes, 640); // 640 px wide, aspect ratio kept
Picture::measure($bytes)reads the header alone and returns width, height and the file extension:jpg,png,webporgif. It runs on the worker thread and takes no fiber.Picture::webp($bytes, $width)scales down to$width(never up), keeps the aspect ratio and writes lossy WebP of quality 82; an image with alpha keeps it, a GIF gives its first frame. It runs on the plugin's thread pool, one thread per core, and must be called in a fiber (a request, orThreading\Task).- Both throw
RuntimeExceptionwith a message startingimage:for bytes that are no supported image or that exceed a limit.
Limits
| Limit | Value | Checked |
|---|---|---|
| Input | 32 MB | before the bytes are read |
| Pixels | 40 megapixels | from the header, before decoding |
| Decoder heap | 512 MB | by the decoder while it decodes |
| WebP side | 16383 px | by the encoder (a limit of the format) |
A file of a few bytes whose header claims 50000 by 50000 pixels fails at the second limit. EXIF orientation is not applied: the pixels come out as stored.
Install
composer require tenma/image vendor/bin/tenma-image install
The install downloads the plugin of this version for the machine, checks it against its SHA-256 and adds it to
tenma.json.
Platforms: macOS arm64, Linux x64 and arm64.
Develop
cd plugin && cargo test && cargo build --release && mkdir -p ../lib cp target/release/libtenma_image.dylib ../lib/tenma_image.plugin # .so on Linux cd .. && composer test && composer stan
The PHP tests run the plugin under a real tenma and skip when tenma or the plugin is missing.
License
The package: MIT or Apache-2.0, at your option. The plugin links libwebp (BSD-3-Clause with a patent grant),
built from source; its license is in licenses/libwebp.txt. The Rust crates it is built from are MIT or
Apache-2.0.