Skip to content

Commit 8a8f8c9

Browse files
committed
docs: rewrite README for current API
1 parent 6c8d51d commit 8a8f8c9

File tree

1 file changed

+132
-169
lines changed

1 file changed

+132
-169
lines changed

README.md

Lines changed: 132 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,213 +1,176 @@
1-
# Node bindings for [Imageflow](https://github.com/imazen/imageflow)
1+
# @imazen/imageflow
22

3-
[![Macos](https://github.com/imazen/imageflow-node/workflows/Test%20Macos/badge.svg)](https://github.com/imazen/imageflow-node/actions?query=workflow%3A%22Test+Macos%22) [![Linux](https://github.com/imazen/imageflow-node/workflows/Test%20Linux/badge.svg)](https://github.com/imazen/imageflow-node/actions?query=workflow%3A%22Test+Linux%22) [![Windows](https://github.com/imazen/imageflow-node/workflows/Test%20Windows/badge.svg)](https://github.com/imazen/imageflow-node/actions?query=workflow%3A%22Test+Windows%22)
3+
[![CI](https://github.com/imazen/imageflow-node/actions/workflows/ci.yml/badge.svg)](https://github.com/imazen/imageflow-node/actions/workflows/ci.yml)
4+
[![npm](https://img.shields.io/npm/v/@imazen/imageflow)](https://www.npmjs.com/package/@imazen/imageflow)
5+
[![license](https://img.shields.io/npm/l/@imazen/imageflow)](https://github.com/imazen/imageflow-node/blob/main/LICENSE)
46

5-
Quickly scale or modify images and optimize them for the web.
7+
Node.js bindings for [Imageflow](https://github.com/imazen/imageflow), a fast image optimization and manipulation library.
68

7-
If the AGPLv3 does not work for you, you can get a [commercial license](https://imageresizing.net/pricing) on a sliding scale. If you have more than 1 server doing image processing your savings should cover the cost.
9+
Supports Linux (x64, arm64), macOS (x64, Apple Silicon), and Windows (x64, arm64). Prebuilt native binaries are downloaded automatically on install.
810

9-
[API docs are here](https://imazen.github.io/imageflow-node/).
11+
[API docs](https://imazen.github.io/imageflow-node/) | [Imageflow](https://github.com/imazen/imageflow)
1012

11-
## Installation
13+
## Install
1214

1315
```bash
1416
npm install @imazen/imageflow
1517
```
1618

17-
## Usage
18-
19-
```js
20-
const {
21-
MozJPEG,
22-
Steps,
23-
FromURL,
24-
FromFile,
25-
FromStream,
26-
FromBuffer,
27-
} = require('@imazen/imageflow')
28-
const fs = require('fs')
29-
30-
let step = new Steps(new FromURL('https://jpeg.org/images/jpeg2000-home.jpg'))
31-
.constrainWithin(500, 500)
32-
.branch((step) =>
33-
step
34-
.constrainWithin(400, 400)
35-
.branch((step) =>
36-
step
37-
.constrainWithin(200, 200)
38-
.rotate90()
39-
.colorFilterGrayscaleFlat()
40-
.encode(new FromFile('./branch_2.jpg'), new MozJPEG(80))
41-
)
42-
.copyRectangle(
43-
(canvas) =>
44-
canvas.decode(
45-
new FromStream(fs.createReadStream('./test.jpg'))
46-
),
47-
{ x: 0, y: 0, w: 100, h: 100 },
48-
10,
49-
10
50-
)
51-
.encode(new FromFile('./branch.jpg'), new MozJPEG(80))
52-
)
53-
.constrainWithin(100, 100)
54-
.rotate180()
55-
step.encode(new FromBuffer(null, 'key'), new MozJPEG(80))
56-
.execute()
57-
.then(console.log)
58-
.catch(console.log)
19+
Requires Node.js 18+. ESM only.
20+
21+
## Quick start
22+
23+
```ts
24+
import { Steps, FromFile, FromBuffer, presets } from '@imazen/imageflow';
25+
26+
// Resize an image file
27+
await new Steps(new FromFile('input.jpg'))
28+
.constrainWithin(800, 600)
29+
.encode(new FromFile('output.jpg'), presets.mozjpeg(80))
30+
.execute();
5931
```
6032

61-
### Examples
33+
## Examples
6234

63-
1. Reading a file from disk. `FromFile` provide an easy method for reading and writing images to disk.
35+
### Resize and encode to buffer
6436

65-
```js
66-
const { MozJPEG, Steps, FromFile } = require('@imazen/imageflow')
37+
```ts
38+
import { Steps, FromBuffer, presets } from '@imazen/imageflow';
6739

68-
const output = await new Step(new FromFile('path/to/file'))
69-
.rotate180()
70-
.encode(new FromFile('./path/to/output/file'))
71-
.execute()
40+
const result = await new Steps(new FromBuffer(inputBytes))
41+
.constrainWithin(400, 400)
42+
.toBuffer(presets.mozjpeg(85), 'result')
43+
.execute();
44+
45+
const outputBytes = result.buffers.get('result');
7246
```
7347

74-
2. Reading from a stream. `FromStream` can read and write to a stream.
48+
### Stream processing
7549

76-
```js
77-
const { MozJPEG, Steps, FromStream } = require('@imazen/imageflow')
50+
```ts
51+
import { Steps, FromStream, presets } from '@imazen/imageflow';
52+
import { createReadStream, createWriteStream } from 'fs';
7853

79-
const output = await new Step(new FromStream(req))
80-
.constrainWithin(400, 400)
81-
.encode(new FromStream(res))
82-
.execute()
83-
res.end()
54+
await new Steps(new FromStream(createReadStream('photo.png')))
55+
.constrainWithin(1200, 1200)
56+
.toStream(presets.webpLossy(80), createWriteStream('photo.webp'))
57+
.execute();
8458
```
8559

86-
3. Reading from a url. `FromURL` can make a GET request to download and POST request to upload the image.
60+
### Fetch from URL
8761

88-
```js
89-
const { MozJPEG, Steps, FromURL } = require('@imazen/imageflow')
62+
```ts
63+
import { Steps, FromURL, FromFile, presets } from '@imazen/imageflow';
9064

91-
const output = await new Step(new FromURL('url to image'))
92-
.colorFilterGrayscaleFlat()
93-
.encode(new FromURL('url to image upload'))
94-
.execute()
65+
await new Steps(new FromURL('https://example.com/photo.jpg'))
66+
.constrainWithin(500, 500)
67+
.colorFilterGrayscaleFlat()
68+
.encode(new FromFile('gray.webp'), presets.webpLossy(75))
69+
.execute();
9570
```
9671

97-
4. Providing buffer. `FromBuffer` can read and provide the output buffer. To read the output a key should be provided, which used later to access buffer in the output.
72+
### Decode options
9873

99-
```js
100-
const { MozJPEG, Steps, FromBuffer } = require('@imazen/imageflow')
74+
```ts
75+
import { Steps, FromBuffer, DecodeOptions, presets } from '@imazen/imageflow';
10176

102-
const output = await new Step(new FromBuffer(getSomeBuffer()))
103-
.colorFilterGrayscaleFlat()
104-
.encode(new FromBuffer(null, 'key'))
105-
.execute()
106-
console.log(output.key)
77+
const result = await new Steps(
78+
new FromBuffer(jpegBytes),
79+
new DecodeOptions()
80+
.setJpegDownscaleHint(200, 200)
81+
.discardColorProfile()
82+
)
83+
.constrainWithin(200, 200)
84+
.toBuffer(presets.mozjpeg(80), 'thumb')
85+
.execute();
10786
```
10887

109-
5. Performing Batch operations. `branch`, `decode`, and `encode` are used together to perform batch operation. This example shows how to create varying size images from a single image.
110-
111-
```js
112-
const { MozJPEG, Steps, FromStream, FromFile } = require('@imazen/imageflow')
113-
114-
const test = new Steps(new FromStream(req))
115-
.constrainWithin(800, 800)
116-
.branch((step) => step.encode(new FromFile('large.jpg'), new MozJPEG()))
117-
.branch((step) =>
118-
step
119-
.constrainWithin(400, 400)
120-
.branch((step) =>
121-
step
122-
.constrainWithin(200, 200)
123-
.branch((step) =>
124-
step
125-
.constrainWithin(100, 100)
126-
.encode(new FromFile('tiny.jpg'), new MozJPEG())
127-
)
128-
.encode(new FromFile('small.jpg'), new MozJPEG())
129-
)
130-
.encode(new FromFile('medium.jpg'), new MozJPEG())
131-
)
132-
.execute()
133-
```
88+
### Branching (multiple outputs from one decode)
89+
90+
```ts
91+
import { Steps, FromFile, presets } from '@imazen/imageflow';
13492

135-
6. Example with complex graph of operations
136-
137-
```js
138-
const {
139-
MozJPEG,
140-
Steps,
141-
FromURL,
142-
FromFile,
143-
FromStream,
144-
FromBuffer,
145-
} = require('@imazen/imageflow')
146-
const fs = require('fs')
147-
148-
let step = new Steps(new FromURL('https://jpeg.org/images/jpeg2000-home.jpg'))
149-
.constraintWithin(500, 500)
150-
.branch((step) =>
151-
step
152-
.constraintWithin(400, 400)
153-
.branch((step) =>
154-
step
155-
.constraintWithin(200, 200)
156-
.rotate90()
157-
.colorFilterGrayscaleFlat()
158-
.encode(new FromFile('./branch_2.jpg'), new MozJPEG(80))
159-
)
160-
.copyRectangle(
161-
(canvas) =>
162-
canvas.decode(
163-
new FromStream(fs.createReadStream('./test.jpg'))
164-
),
165-
{ x: 0, y: 0, w: 100, h: 100 },
166-
10,
167-
10
168-
)
169-
.encode(new FromFile('./branch.jpg'), new MozJPEG(80))
170-
)
171-
.constraintWithin(100, 100)
172-
.rotate180()
173-
step.encode(new FromBuffer(null, 'key'), new MozJPEG(80))
174-
.execute()
175-
.then(console.log)
176-
.catch(console.log)
93+
await new Steps(new FromFile('original.jpg'))
94+
.constrainWithin(1200, 1200)
95+
.branch(s => s.encode(new FromFile('large.jpg'), presets.mozjpeg(85)))
96+
.branch(s => s
97+
.constrainWithin(400, 400)
98+
.encode(new FromFile('medium.jpg'), presets.mozjpeg(80))
99+
)
100+
.branch(s => s
101+
.constrainWithin(150, 150)
102+
.encode(new FromFile('thumb.jpg'), presets.mozjpeg(70))
103+
)
104+
.execute();
177105
```
178106

179-
7. Using query style commands
107+
### Query string commands
108+
109+
For simple resize/format operations without the builder API:
110+
111+
```ts
112+
import { Steps, FromBuffer, presets } from '@imazen/imageflow';
180113

181-
```js
182114
await new Steps().executeCommand(
183-
'width=100&height=100&mode=max',
184-
new FromBuffer(str),
185-
new FromBuffer(null, 'key')
186-
)
115+
'width=200&height=200&mode=max&format=webp',
116+
new FromBuffer(inputBytes),
117+
new FromBuffer(null, 'out')
118+
);
187119
```
188120

189-
8. Using Decode Options
121+
## Encoder presets
190122

191-
```js
192-
const output = await new Step(
193-
new FromBuffer(getSomeBuffer()),
194-
new DecodeOptions()
195-
.ignoreColorProfileError()
196-
.setJPEGDownscaleHint(100, 100)
197-
.setWebpDecoderHints(100, 100)
198-
.discardColorProfile()
199-
)
200-
.colorFilterGrayscaleFlat()
201-
.encode(new FromBuffer(null, 'key'))
202-
.execute()
203-
console.log(output.key)
123+
```ts
124+
import { presets } from '@imazen/imageflow';
125+
126+
presets.mozjpeg(quality, { progressive?: boolean })
127+
presets.libjpegTurbo(quality, { progressive?: boolean })
128+
presets.webpLossy(quality)
129+
presets.webpLossless()
130+
presets.lodepng({ maxDeflate?: boolean })
131+
presets.pngquant({ quality?: [min, max], speed?: number })
132+
presets.libpng({ maxDeflate?: boolean, matte?: Color })
133+
presets.gif()
204134
```
205135

206-
## Local Setup
136+
## Available operations
137+
138+
Fluent methods on `Steps`:
139+
140+
- `constrainWithin(w, h)` — scale down to fit
141+
- `encode(dest, preset)` / `toFile(preset, path)` / `toBuffer(preset, key)` / `toStream(preset, stream)`
142+
- `rotate90()` / `rotate180()` / `rotate270()`
143+
- `flipVertical()` / `flipHorizontal()`
144+
- `crop(x1, y1, x2, y2)` / `cropWhitespace(threshold, padding)`
145+
- `region(...)` / `regionPercent(...)`
146+
- `expandCanvas(...)` / `fillRect(...)`
147+
- `colorFilterGrayscaleFlat()` / `colorFilterSepia()` / `colorFilterInvert()` and others
148+
- `colorFilterBrightness(v)` / `colorFilterContrast(v)` / `colorFilterSaturation(v)` / `colorFilterAlpha(v)`
149+
- `whiteBalance(threshold)`
150+
- `watermark(source, gravity, fitPercent, opacity, fitBox?)`
151+
- `branch(fn)` — fork the pipeline for multiple outputs
152+
- `copyRectToCanvas(...)` / `drawImageExactTo(...)`
153+
154+
See the [API docs](https://imazen.github.io/imageflow-node/) for full details.
155+
156+
## License
157+
158+
[AGPLv3](https://github.com/imazen/imageflow-node/blob/main/LICENSE). Commercial licenses available at [imageresizing.net/pricing](https://imageresizing.net/pricing).
159+
160+
## Development
207161

208162
```bash
209163
git clone https://github.com/imazen/imageflow-node
210164
cd imageflow-node
211-
yarn
212-
yarn test
165+
npm install
166+
npm test # vitest — 110 tests including doctest examples
167+
npm run docs # typedoc — generates API reference in docs/
168+
```
169+
170+
Native module build (requires Rust toolchain):
171+
172+
```bash
173+
cd native
174+
cargo build
175+
cp target/debug/libimageflow_node.so index.node # .dylib on macOS, .dll on Windows
213176
```

0 commit comments

Comments
 (0)