imgcraft 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -72
- package/package.json +25 -7
package/README.md
CHANGED
|
@@ -1,98 +1,153 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://imgcraft-docs.vercel.app/logo.png" height="80" alt="imgcraft" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/imgcraft"><img src="https://img.shields.io/npm/v/imgcraft.svg" alt="npm version"></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/imgcraft"><img src="https://img.shields.io/npm/dm/imgcraft.svg" alt="downloads"></a>
|
|
8
|
+
<a href="https://github.com/ajithonmain/imgcraft/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/imgcraft.svg" alt="license"></a>
|
|
9
|
+
<a href="https://github.com/ajithonmain/imgcraft/actions"><img src="https://img.shields.io/badge/tests-65%20passing-brightgreen.svg" alt="tests"></a>
|
|
10
|
+
</p>
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
[](https://github.com/ajithonmain/imgcraft/blob/main/LICENSE)
|
|
7
|
-
[](https://github.com/ajithonmain/imgcraft/actions)
|
|
12
|
+
---
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
Chainable image processing for Node.js and the browser — with AI ops built in.
|
|
15
|
+
|
|
16
|
+
imgcraft converts images between formats, resizes, crops, removes backgrounds, upscales, and more — via a fluent chainable API. It runs natively in Node.js using sharp, and in the browser via WebAssembly. A hosted REST API is also available at `https://imgcraft-api.imgcraft.workers.dev`.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
10
19
|
|
|
11
20
|
```sh
|
|
12
21
|
npm install imgcraft
|
|
13
22
|
```
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## Usage
|
|
24
|
+
## Examples
|
|
18
25
|
|
|
19
26
|
```ts
|
|
20
27
|
import { img, batch } from 'imgcraft'
|
|
21
28
|
|
|
22
|
-
//
|
|
23
|
-
const
|
|
29
|
+
// Resize and convert
|
|
30
|
+
const buffer = await img('photo.jpg')
|
|
24
31
|
.resize(800, 600)
|
|
25
32
|
.webp({ quality: 85 })
|
|
26
33
|
.toBuffer()
|
|
27
34
|
|
|
28
|
-
//
|
|
29
|
-
const
|
|
30
|
-
.resize(400)
|
|
35
|
+
// Remove background (no API key needed — runs locally)
|
|
36
|
+
const buffer = await img('portrait.jpg')
|
|
31
37
|
.removeBackground()
|
|
32
|
-
.
|
|
38
|
+
.png()
|
|
39
|
+
.toBuffer()
|
|
33
40
|
|
|
34
|
-
//
|
|
35
|
-
await
|
|
41
|
+
// Chain multiple transforms
|
|
42
|
+
const buffer = await img('input.png')
|
|
36
43
|
.resize(1200)
|
|
44
|
+
.sharpen()
|
|
45
|
+
.removeBackground()
|
|
46
|
+
.upscale(2)
|
|
47
|
+
.webp({ quality: 90 })
|
|
48
|
+
.toBuffer()
|
|
49
|
+
|
|
50
|
+
// Batch process with concurrency control
|
|
51
|
+
await batch(['a.jpg', 'b.jpg', 'c.jpg'], { concurrency: 4 })
|
|
52
|
+
.resize(800)
|
|
37
53
|
.webp()
|
|
38
54
|
.toDir('./output')
|
|
55
|
+
|
|
56
|
+
// Browser (WASM — same API)
|
|
57
|
+
const result = await img(file)
|
|
58
|
+
.resize(400)
|
|
59
|
+
.grayscale()
|
|
60
|
+
.toDataURL()
|
|
61
|
+
|
|
62
|
+
// Read metadata
|
|
63
|
+
const meta = await img('photo.jpg').meta()
|
|
64
|
+
// { width: 3024, height: 4032, format: 'jpeg', size: 3621944, hasAlpha: false }
|
|
65
|
+
|
|
66
|
+
// REST API
|
|
67
|
+
const form = new FormData()
|
|
68
|
+
form.append('image', file)
|
|
69
|
+
form.append('ops', JSON.stringify([
|
|
70
|
+
{ op: 'resize', width: 800 },
|
|
71
|
+
{ op: 'format', format: 'webp', quality: 85 }
|
|
72
|
+
]))
|
|
73
|
+
const res = await fetch('https://imgcraft-api.imgcraft.workers.dev/transform', {
|
|
74
|
+
method: 'POST', body: form
|
|
75
|
+
})
|
|
76
|
+
const blob = await res.blob()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Supported operations
|
|
80
|
+
|
|
81
|
+
**Transforms**
|
|
82
|
+
- `resize(width?, height?, options?)` — fit modes: cover, contain, fill, inside, outside
|
|
83
|
+
- `crop(left, top, width, height)` — extract a region
|
|
84
|
+
- `rotate(angle)` — 0, 90, 180, 270 degrees
|
|
85
|
+
- `flip()` — vertical flip
|
|
86
|
+
- `flop()` — horizontal flip
|
|
87
|
+
|
|
88
|
+
**Colour**
|
|
89
|
+
- `grayscale()` — convert to greyscale
|
|
90
|
+
- `tint(colour)` — apply colour tint
|
|
91
|
+
- `negate()` — invert colours
|
|
92
|
+
- `brightness(factor)` — adjust brightness
|
|
93
|
+
- `contrast(factor)` — adjust contrast
|
|
94
|
+
- `saturation(factor)` — adjust saturation
|
|
95
|
+
|
|
96
|
+
**Filters**
|
|
97
|
+
- `blur(sigma?)` — Gaussian blur
|
|
98
|
+
- `sharpen(options?)` — unsharp mask
|
|
99
|
+
- `median(size?)` — median filter
|
|
100
|
+
|
|
101
|
+
**Format & output**
|
|
102
|
+
- `format(type)` — jpeg, png, webp, avif
|
|
103
|
+
- `quality(1–100)` — output quality
|
|
104
|
+
- `jpeg(options?)` — JPEG-specific options
|
|
105
|
+
- `png(options?)` — PNG-specific options
|
|
106
|
+
- `webp(options?)` — WebP-specific options
|
|
107
|
+
- `avif(options?)` — AVIF-specific options
|
|
108
|
+
|
|
109
|
+
**Compositing**
|
|
110
|
+
- `composite(input, options?)` — overlay/watermark (base64 data URI input)
|
|
111
|
+
|
|
112
|
+
**Metadata**
|
|
113
|
+
- `meta()` — read width, height, format, size, hasAlpha, channels
|
|
114
|
+
- `stripMeta()` — remove EXIF and ICC data
|
|
115
|
+
|
|
116
|
+
**AI operations** *(Node.js only — lazy loaded, no API key required)*
|
|
117
|
+
- `removeBackground()` — subject isolation via ONNX model
|
|
118
|
+
- `smartCrop(options?)` — subject-aware crop via TensorFlow coco-ssd
|
|
119
|
+
- `upscale(2 | 4)` — ESRGAN super-resolution upscaling
|
|
120
|
+
|
|
121
|
+
**Output**
|
|
122
|
+
- `toBuffer()` — `Buffer` (Node.js) / `Uint8Array` (browser)
|
|
123
|
+
- `toFile(path)` — write to disk (Node.js only)
|
|
124
|
+
- `toStream()` — `ReadableStream<Uint8Array>`
|
|
125
|
+
- `toDataURL()` — base64 data URI (browser)
|
|
126
|
+
|
|
127
|
+
**Batch**
|
|
128
|
+
- `batch(inputs[], options?)` — process multiple images
|
|
129
|
+
- `.toBuffers()` — array of results
|
|
130
|
+
- `.toDir(path)` — write all to directory
|
|
131
|
+
- `.toFiles(paths[])` — 1:1 path mapping
|
|
132
|
+
|
|
133
|
+
## REST API
|
|
134
|
+
|
|
39
135
|
```
|
|
136
|
+
POST https://imgcraft-api.imgcraft.workers.dev/transform # process image
|
|
137
|
+
POST https://imgcraft-api.imgcraft.workers.dev/info # read metadata
|
|
138
|
+
GET https://imgcraft-api.imgcraft.workers.dev/health # status
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Rate limited to 60 requests per minute per IP. AI operations not available via REST API.
|
|
142
|
+
|
|
143
|
+
## Documentation
|
|
144
|
+
|
|
145
|
+
Visit **[imgcraft-docs.vercel.app](https://imgcraft-docs.vercel.app)** for complete API documentation, guides, and a live playground.
|
|
146
|
+
|
|
147
|
+
## Contributing
|
|
40
148
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
| Feature | Status |
|
|
44
|
-
|---|---|
|
|
45
|
-
| Node.js (sharp engine) | ✅ |
|
|
46
|
-
| Browser (WASM engine) | ✅ |
|
|
47
|
-
| AI ops (bg removal, smart crop, upscale) | ✅ |
|
|
48
|
-
| TypeScript strict | ✅ |
|
|
49
|
-
| Zero config | ✅ |
|
|
50
|
-
| Tree-shakeable ESM | ✅ |
|
|
51
|
-
|
|
52
|
-
## API
|
|
53
|
-
|
|
54
|
-
### Transform
|
|
55
|
-
|
|
56
|
-
| Method | Description |
|
|
57
|
-
|---|---|
|
|
58
|
-
| `.resize(w?, h?, opts?)` | Resize. `opts.fit`: cover / contain / fill / inside / outside |
|
|
59
|
-
| `.crop({ left, top, width, height })` | Extract a region |
|
|
60
|
-
| `.rotate(angle, opts?)` | Rotate by degrees |
|
|
61
|
-
| `.flip()` | Flip vertically |
|
|
62
|
-
| `.flop()` | Flip horizontally |
|
|
63
|
-
| `.format(type, opts?)` | Set output format: jpeg / png / webp / avif / tiff |
|
|
64
|
-
| `.jpeg(opts?)` `.png(opts?)` `.webp(opts?)` `.avif(opts?)` | Format shorthands |
|
|
65
|
-
| `.quality(1–100)` | Set output quality |
|
|
66
|
-
| `.blur(sigma?)` | Gaussian blur |
|
|
67
|
-
| `.sharpen(opts?)` | Unsharp mask |
|
|
68
|
-
| `.median(size?)` | Median filter |
|
|
69
|
-
| `.grayscale()` | Convert to greyscale |
|
|
70
|
-
| `.tint({ r, g, b })` | Apply color tint |
|
|
71
|
-
| `.negate()` | Invert colors |
|
|
72
|
-
| `.brightness(value)` | Brightness multiplier (1 = no change) |
|
|
73
|
-
| `.contrast({ value })` | Contrast multiplier (1 = no change) |
|
|
74
|
-
| `.saturation(value)` | Saturation multiplier |
|
|
75
|
-
| `.composite(opts)` | Overlay / watermark |
|
|
76
|
-
| `.stripMeta()` | Remove EXIF and ICC metadata |
|
|
77
|
-
|
|
78
|
-
### AI
|
|
79
|
-
|
|
80
|
-
| Method | Description |
|
|
81
|
-
|---|---|
|
|
82
|
-
| `.removeBackground()` | ONNX-based bg removal, runs locally, no API key |
|
|
83
|
-
| `.smartCrop(subject)` | Face / object aware crop |
|
|
84
|
-
| `.upscale(factor)` | 2× or 4× via ESRGAN |
|
|
85
|
-
|
|
86
|
-
### Output
|
|
87
|
-
|
|
88
|
-
| Method | Returns |
|
|
89
|
-
|---|---|
|
|
90
|
-
| `.toBuffer()` | `Buffer` (Node) / `Uint8Array` (Browser) |
|
|
91
|
-
| `.toFile(path)` | `Promise<void>` — Node only |
|
|
92
|
-
| `.toStream()` | `ReadableStream<Uint8Array>` |
|
|
93
|
-
| `.toDataURL()` | `Promise<string>` — base64 data URI |
|
|
94
|
-
| `.meta()` | `Promise<MetadataResult>` — reads metadata, no processing |
|
|
149
|
+
Issues and pull requests welcome at [github.com/ajithonmain/imgcraft](https://github.com/ajithonmain/imgcraft).
|
|
95
150
|
|
|
96
151
|
## License
|
|
97
152
|
|
|
98
|
-
MIT
|
|
153
|
+
MIT © 2026 Ajith M Jose
|
package/package.json
CHANGED
|
@@ -1,26 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imgcraft",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Chainable image transform pipeline — Node + Browser WASM",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/ajithonmain/imgcraft.git"
|
|
8
|
+
"url": "git+https://github.com/ajithonmain/imgcraft.git"
|
|
9
9
|
},
|
|
10
10
|
"homepage": "https://imgcraft-docs.vercel.app",
|
|
11
11
|
"keywords": [
|
|
12
12
|
"image",
|
|
13
13
|
"image-processing",
|
|
14
|
+
"image-resize",
|
|
15
|
+
"image-compression",
|
|
14
16
|
"sharp",
|
|
15
|
-
"
|
|
16
|
-
"resize",
|
|
17
|
+
"sharp-alternative",
|
|
17
18
|
"webp",
|
|
18
19
|
"avif",
|
|
19
|
-
"
|
|
20
|
+
"jpeg",
|
|
21
|
+
"png",
|
|
20
22
|
"background-removal",
|
|
21
|
-
"
|
|
23
|
+
"remove-background",
|
|
24
|
+
"ai-image",
|
|
25
|
+
"upscale",
|
|
26
|
+
"smart-crop",
|
|
27
|
+
"wasm",
|
|
22
28
|
"browser",
|
|
23
|
-
"node"
|
|
29
|
+
"node",
|
|
30
|
+
"pipeline",
|
|
31
|
+
"chainable",
|
|
32
|
+
"thumbnail",
|
|
33
|
+
"crop",
|
|
34
|
+
"rotate",
|
|
35
|
+
"blur",
|
|
36
|
+
"watermark",
|
|
37
|
+
"batch",
|
|
38
|
+
"typescript",
|
|
39
|
+
"esm",
|
|
40
|
+
"image-transform",
|
|
41
|
+
"image-optimization"
|
|
24
42
|
],
|
|
25
43
|
"type": "module",
|
|
26
44
|
"main": "./dist/index.js",
|