PHPackages                             bnussbau/trmnl-pipeline-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. bnussbau/trmnl-pipeline-php

ActiveLibrary[Image &amp; Media](/categories/media)

bnussbau/trmnl-pipeline-php
===========================

Convert HTML content into optimized images for a range of e-ink devices.

0.8.0(3mo ago)01.7k↑42.9%3MITPHPPHP ^8.2CI passing

Since Sep 18Pushed 3mo agoCompare

[ Source](https://github.com/bnussbau/trmnl-pipeline-php)[ Packagist](https://packagist.org/packages/bnussbau/trmnl-pipeline-php)[ Docs](https://github.com/bnussbau/trmnl-pipeline-php)[ Fund](https://www.buymeacoffee.com/bnussbau)[ Fund](https://trmnl.com/?ref=laravel-trmnl)[ RSS](/packages/bnussbau-trmnl-pipeline-php/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (13)Used By (0)

TRMNL Pipeline PHP
==================

[](#trmnl-pipeline-php)

[![Latest Version on Packagist](https://camo.githubusercontent.com/a84fc4c45a2f5cd1599fd8ed64a2104be27fbf30062dbf76bc7af6e04ea3b9b4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f626e7573736261752f74726d6e6c2d706970656c696e652d7068702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bnussbau/trmnl-pipeline-php)[![License](https://camo.githubusercontent.com/f17af845a1e5bad11c971beba5672e88852da6215d493615c3c41a967c7ddc01/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652532302d4d49542d626c75653f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bnussbau/trmnl-pipeline-php)[![Tests](https://camo.githubusercontent.com/c68f29c593006dd3bec847e14987f20a130b80515f20e24dad7044176ed1fd32/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f626e7573736261752f74726d6e6c2d706970656c696e652d7068702f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/bnussbau/trmnl-pipeline-php/actions/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/c07b1a19d2d17c580f986440b1a1f2949d666395dfc70200e661ba25952d128e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f626e7573736261752f74726d6e6c2d706970656c696e652d7068702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bnussbau/trmnl-pipeline-php)

TRMNL Pipeline PHP provides a streamlined API, based on the pipeline pattern, for converting HTML content (or images) into optimized images for e-ink devices supported by the [TRMNL Models API](https://trmnl.com/api/models). The image processing pipeline includes features like scaling, rotation, grayscale conversion, color quantization, and format-specific optimizations. This package is used in [usetrmnl/byos\_laravel](https://github.com/usetrmnl/byos_laravel).

Command line wrapper for this package: [trmnl-pipeline-cmd](https://github.com/bnussbau/trmnl-pipeline-cmd)

[![image](https://private-user-images.githubusercontent.com/8931007/490802056-e84fc752-552e-4cb9-a1c0-aa2596176db7.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzQ3NDkyMDgsIm5iZiI6MTc3NDc0ODkwOCwicGF0aCI6Ii84OTMxMDA3LzQ5MDgwMjA1Ni1lODRmYzc1Mi01NTJlLTRjYjktYTFjMC1hYTI1OTYxNzZkYjcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDMyOSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAzMjlUMDE0ODI4WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZThhMjhlZDRlMTQ2NjA0Y2U4MDNiYzcwNGY1ZGQ4MzE5MmU4MDQ2Y2UxODFjM2FjOTRiMTUzYjhmNDBhMWIwMyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.DdeQJ531yLRMaCNv5kcp2_FtI_QjfUTcMcnFtT_hXnA)](https://private-user-images.githubusercontent.com/8931007/490802056-e84fc752-552e-4cb9-a1c0-aa2596176db7.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzQ3NDkyMDgsIm5iZiI6MTc3NDc0ODkwOCwicGF0aCI6Ii84OTMxMDA3LzQ5MDgwMjA1Ni1lODRmYzc1Mi01NTJlLTRjYjktYTFjMC1hYTI1OTYxNzZkYjcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDMyOSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAzMjlUMDE0ODI4WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZThhMjhlZDRlMTQ2NjA0Y2U4MDNiYzcwNGY1ZGQ4MzE5MmU4MDQ2Y2UxODFjM2FjOTRiMTUzYjhmNDBhMWIwMyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.DdeQJ531yLRMaCNv5kcp2_FtI_QjfUTcMcnFtT_hXnA)Features
--------

[](#features)

- **Browser Rendering**: HTML to image conversion using Spatie Browsershot
- **Image Processing**: Advanced image manipulation using ImageMagick
- **TRMNL Models API**: Automatic support for &gt;=12 different e-ink device models.

Requirements
------------

[](#requirements)

- PHP 8.2 or higher (PHP 8.4 + 8.5 are tested in CI)
- Imagick extension
- Spatie Browsershot (requires Node.js and Puppeteer -&gt; see [Browsershot Requirements](https://spatie.be/docs/browsershot/v4/requirements))

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require bnussbau/trmnl-pipeline-php
```

Usage
-----

[](#usage)

### With Model Configuration

[](#with-model-configuration)

Render HTML and convert to image compatible with the TRMNL OG model.

```
use Bnussbau\TrmnlPipeline\Model;
use Bnussbau\TrmnlPipeline\TrmnlPipeline;
use Bnussbau\TrmnlPipeline\Stages\ImageStage;
use Bnussbau\TrmnlPipeline\Stages\BrowserStage;

$html = file_get_contents('./tests/assets/framework2_og.html');

$image = new TrmnlPipeline()
    ->model(Model::OG)
    ->pipe(new BrowserStage()
        ->html($html))
    ->pipe(new ImageStage())
    ->process();

echo "Generated image: $image";
```

Generates PNG 800x480 8-bit Grayscale Gray 4c

### Image Processing Only

[](#image-processing-only)

```
use Bnussbau\TrmnlPipeline\Stages\ImageStage;
use Bnussbau\TrmnlPipeline\Model;

$imageStage = new ImageStage();
$imageStage->configureFromModel(Model::OG_BMP);

$result = $imageStage('./tests/assets/browsershot_og_1bit.png');
echo "Processed image: $result";
```

Generates BMP3 800x480 1-bit sRGB 2c

### Manual Configuration

[](#manual-configuration)

```
use Bnussbau\TrmnlPipeline\Model;
use Bnussbau\TrmnlPipeline\TrmnlPipeline;
use Bnussbau\TrmnlPipeline\Stages\ImageStage;
use Bnussbau\TrmnlPipeline\Stages\BrowserStage;

$html = file_get_contents('./tests/assets/framework2_og.html');

$image = new TrmnlPipeline()
    ->pipe(new BrowserStage()
        ->html($html))
    ->pipe(new ImageStage()
        ->format('png')
        ->width(800)
        ->height(600)
        ->rotation(90)
        ->colors(256)
        ->bitDepth(8))
    ->process();

echo "Generated image: $image";
```

### Setting the Browser Timezone (optional)

[](#setting-the-browser-timezone-optional)

You can control the timezone used by the headless browser when rendering your HTML by calling `timezone()` on `BrowserStage` with any valid PHP timezone identifier (e.g., `UTC`, `America/New_York`, `Europe/Berlin`).

Notes:

- The timezone is only applied when you explicitly call `timezone()`. If you don’t explicitly set the timezone, the browser will use the system timezone.
- This can be helpful when your HTML or scripts render time/date-dependent content.

Example:

```
use Bnussbau\TrmnlPipeline\Stages\BrowserStage;

$image = (new \Bnussbau\TrmnlPipeline\TrmnlPipeline())
    ->pipe((new BrowserStage())
        ->timezone('America/New_York')
        ->html('document.write(new Date().toString())'))
    ->pipe(new \Bnussbau\TrmnlPipeline\Stages\ImageStage())
    ->process();
```

### Browser Rendering on AWS Lambda

[](#browser-rendering-on-aws-lambda)

You can use different Browsershot implementations (like BrowsershotLambda) by passing an instance to the BrowserStage. See installation instructions and requirments for [stefanzweifel/sidecar-browsershot](https://github.com/stefanzweifel/sidecar-browsershot).

```
use Bnussbau\TrmnlPipeline\Model;
use Bnussbau\TrmnlPipeline\TrmnlPipeline;
use Bnussbau\TrmnlPipeline\Stages\BrowserStage;
use Bnussbau\TrmnlPipeline\Stages\ImageStage;
use Wnx\SidecarBrowsershot\BrowsershotLambda;

$html = file_get_contents('./tests/assets/framework2_og.html');

// Create your custom Browsershot instance (e.g., BrowsershotLambda)
$browsershotLambda = new BrowsershotLambda();

$image = new TrmnlPipeline()
    ->model(Model::OG)
    ->pipe(new BrowserStage($browsershotLambda)
        ->html($html))
    ->pipe(new ImageStage())
    ->process();

echo "Generated image: $image";
```

This allows you to use BrowsershotLambda or any other Browsershot implementation that extends `Spatie\Browsershot\Browsershot`.

### Testing with Fake Mode

[](#testing-with-fake-mode)

You can use the `fake()` method to prevent actual Browsershot and Imagick operations:

```
use Bnussbau\TrmnlPipeline\Model;
use Bnussbau\TrmnlPipeline\TrmnlPipeline;
use Bnussbau\TrmnlPipeline\Stages\BrowserStage;
use Bnussbau\TrmnlPipeline\Stages\ImageStage;

// Enable fake mode for testing
TrmnlPipeline::fake();

$html = 'Test Content';

$result = (new TrmnlPipeline())
    ->model(Model::OG)
    ->pipe(new BrowserStage()->html($html))
    ->pipe(new ImageStage())
    ->process();

echo "Mock image generated: $result";

// Disable fake mode when done
TrmnlPipeline::restore();
```

API Reference
-------------

[](#api-reference)

### Pipeline

[](#pipeline)

The main pipeline class that orchestrates the processing stages.

```
$pipeline = new Pipeline();
$pipeline->model(Model::OG_PNG); // Set model for automatic configuration
$pipeline->pipe(new BrowserStage()); // Add browser stage
$pipeline->pipe(new ImageStage()); // Add image stage
$result = $pipeline->process($payload); // Process payload
```

### BrowserStage

[](#browserstage)

Converts HTML or a URL to PNG images using Spatie Browsershot. You must provide content via either `html()` or `url()` (mutually exclusive).

- **`html(string $html)`** — Set HTML content to render (e.g. a template or string).
- **`url(string $url)`** — Set a URL to capture (e.g. `https://example.com`). Use this when you want to screenshot a live webpage instead of rendering HTML. If the page is not black-and-white or contains photos, combine with **`->dither()`** on `ImageStage` so the image is converted cleanly to the model’s limited palette; otherwise gradients and images can look harsh or banded.

```
$browserStage = new BrowserStage();
$browserStage
    ->html('Content')
    ->width(800)
    ->height(480)
    ->useDefaultDimensions() // force 800x480 e.g. in combination with Model to upscale image
    ->setBrowsershotOption('addStyleTag', json_encode(['content' => 'body{ color: red; }']));

$result = $browserStage(null);
```

Screenshot from URL with dithering (recommended for full-color or image-heavy pages):

```
$image = (new TrmnlPipeline())
    ->model(Model::OG)
    ->pipe((new BrowserStage())->url('https://example.com'))
    ->pipe((new ImageStage())->dither())
    ->process();
```

### ImageStage

[](#imagestage)

Processes images for e-ink display compatibility.

```
$imageStage = new ImageStage();
$imageStage
    ->format('png')
    ->width(800)
    ->height(480)
    ->offsetX(0)
    ->offsetY(0)
    ->rotation(0)
    ->colors(2)
    ->bitDepth(1)
    ->outputPath('/path/to/output.png');

$result = $imageStage('/path/to/input.png');
```

#### Dithering

[](#dithering)

Recommended for photos but not for images containing mostly text, where it can make edges and letters appear rough or unclear. Dithering converts a grayscale photo into only black and white pixels by using patterns or noise to simulate intermediate shades, creating the illusion of continuous tones through spatial averaging.

```
use Bnussbau\TrmnlPipeline\Stages\ImageStage;

(new ImageStage())
    ->dither()
    ->colors(2)
    ->bitDepth(1);
```

#### Color Support

[](#color-support)

The pipeline supports color images via palettes defined in `palettes.json`. Models can specify one or more palette IDs, and the first palette with a `colors` array will be automatically applied. Color palettes use RGB colorspace for quantization and support dithering.

**Example 1: Using Model Preset with Color Palette**

```
use Bnussbau\TrmnlPipeline\Model;
use Bnussbau\TrmnlPipeline\TrmnlPipeline;
use Bnussbau\TrmnlPipeline\Stages\BrowserStage;
use Bnussbau\TrmnlPipeline\Stages\ImageStage;

$html = file_get_contents('./tests/assets/color_6a_test.html');

// Inky Impression 13.3 model has color-6a palette (6 colors: red, green, blue, yellow, black, white)
$image = new TrmnlPipeline()
    ->model(Model::INKY_IMPRESSION_13_3)
    ->pipe(new BrowserStage()
        ->html($html))
    ->pipe(new ImageStage())
    ->process();

echo "Generated color image: $image";
```

**Example 2: Defining Color Palette as Array**

```
use Bnussbau\TrmnlPipeline\Stages\ImageStage;

// Define custom color palette (6 colors)
$colorPalette = [
    '#FF0000', // Red
    '#00FF00', // Green
    '#0000FF', // Blue
    '#FFFF00', // Yellow
    '#000000', // Black
    '#FFFFFF', // White
];

$imageStage = new ImageStage();
$imageStage
    ->format('png')
    ->colormap($colorPalette)
    ->dither(true); // Dithering works with color palettes (optional; only use for images)

$result = $imageStage('/path/to/input.png');
echo "Processed color image: $result";
```

### Model

[](#model)

Access device model configurations.

```
$model = Model::OG_PNG;
$data = $model->getData();

echo $model->getLabel(); // "TRMNL OG (1-bit)"
echo $model->getWidth(); // 800
echo $model->getHeight(); // 480
echo $model->getColors(); // 2
echo $model->getBitDepth(); // 1
```

Development
-----------

[](#development)

### Running Tests

[](#running-tests)

```
composer test
composer test-coverage
```

### Code Quality

[](#code-quality)

```
composer format
composer analyse
composer rector
```

License
-------

[](#license)

MIT License. See LICENSE file for details.

Contributing
------------

[](#contributing)

1. Create an issue to discuss your idea
2. Fork the repository
3. Create a feature branch
4. Make your changes
5. Add tests to maintain coverage
6. Run the test suite
7. Submit a pull request

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance82

Actively maintained with recent releases

Popularity22

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 88.2% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~14 days

Recently: every ~26 days

Total

11

Last Release

95d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/53653f306f20e3e075f9d9243a1daa101ae2f0f7fbd82329793e8e5acba6afba?d=identicon)[bnussbau](/maintainers/bnussbau)

---

Top Contributors

[![bnussbau](https://avatars.githubusercontent.com/u/8931007?v=4)](https://github.com/bnussbau "bnussbau (45 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

trmnltrmnlserverTRMNLbnussbautrmnl-pipeline-phpe-ink

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/bnussbau-trmnl-pipeline-php/health.svg)

```
[![Health](https://phpackages.com/badges/bnussbau-trmnl-pipeline-php/health.svg)](https://phpackages.com/packages/bnussbau-trmnl-pipeline-php)
```

###  Alternatives

[milon/barcode

Barcode generator like Qr Code, PDF417, C39, C39+, C39E, C39E+, C93, S25, S25+, I25, I25+, C128, C128A, C128B, C128C, 2-Digits UPC-Based Extention, 5-Digits UPC-Based Extention, EAN 8, EAN 13, UPC-A, UPC-E, MSI (Variation of Plessey code)

1.5k13.3M39](/packages/milon-barcode)[bkwld/croppa

Image thumbnail creation through specially formatted URLs for Laravel

510496.0k23](/packages/bkwld-croppa)[goat1000/svggraph

Generates SVG graphs

132849.6k3](/packages/goat1000-svggraph)[cohensive/embed

Media Embed (for Laravel or as a standalone).

120370.4k](/packages/cohensive-embed)[netresearch/rte-ckeditor-image

Image support in CKEditor for the TYPO3 ecosystem - by Netresearch

63991.3k4](/packages/netresearch-rte-ckeditor-image)[humanmade/tachyon-plugin

Rewrites WordPress image URLs to use Tachyon

87338.5k2](/packages/humanmade-tachyon-plugin)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
