@standardagents/sip 0.10.0-dev

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 ADDED
@@ -0,0 +1,170 @@
1
+ # @standardagents/sip
2
+
3
+ **S**mall **I**mage **P**rocessor - Ultra memory-efficient image processing for Cloudflare Workers.
4
+
5
+ ## Features
6
+
7
+ - **Format Detection**: Probe images for format and dimensions without decoding
8
+ - **Scanline Resize**: Memory-efficient bilinear interpolation using only 2 rows at a time
9
+ - **Multi-format Input**: JPEG, PNG, WebP, AVIF
10
+ - **JPEG Output**: Always outputs JPEG with configurable quality
11
+ - **Size Control**: Resize to target dimensions and/or file size
12
+ - **Streaming WASM** (optional): DCT-scaled JPEG decoding for <1MB peak memory on any image size
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pnpm add @standardagents/sip
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ```typescript
23
+ import { sip } from '@standardagents/sip';
24
+
25
+ // Process an image
26
+ const result = await sip.process(imageBuffer, {
27
+ maxWidth: 2048,
28
+ maxHeight: 2048,
29
+ maxBytes: 1.5 * 1024 * 1024, // 1.5MB target
30
+ quality: 85,
31
+ });
32
+
33
+ console.log(result.width, result.height); // Output dimensions
34
+ console.log(result.mimeType); // 'image/jpeg'
35
+ console.log(result.originalFormat); // 'png', 'jpeg', etc.
36
+
37
+ // Get the output
38
+ const jpegBlob = new Blob([result.data], { type: 'image/jpeg' });
39
+ ```
40
+
41
+ ### Probe Only
42
+
43
+ Get image info without decoding:
44
+
45
+ ```typescript
46
+ import { sip } from '@standardagents/sip';
47
+
48
+ const info = sip.probe(imageBuffer);
49
+ console.log(info.format); // 'jpeg' | 'png' | 'webp' | 'avif'
50
+ console.log(info.width, info.height);
51
+ console.log(info.hasAlpha);
52
+ ```
53
+
54
+ ## API
55
+
56
+ ### `sip.process(input, options)`
57
+
58
+ Process an image: decode, resize, and encode to JPEG.
59
+
60
+ **Parameters:**
61
+ - `input: ArrayBuffer` - Input image data
62
+ - `options: ProcessOptions` - Processing options
63
+
64
+ **Options:**
65
+ - `maxWidth?: number` - Maximum output width (default: 4096)
66
+ - `maxHeight?: number` - Maximum output height (default: 4096)
67
+ - `maxBytes?: number` - Target output size in bytes (default: 1.5MB)
68
+ - `quality?: number` - JPEG quality 1-100 (default: 85)
69
+
70
+ **Returns:** `ProcessResult`
71
+ - `data: ArrayBuffer` - JPEG image data
72
+ - `width: number` - Output width
73
+ - `height: number` - Output height
74
+ - `mimeType: 'image/jpeg'` - Always JPEG
75
+ - `originalFormat: ImageFormat` - Original input format
76
+
77
+ ### `sip.probe(input)`
78
+
79
+ Get format and dimensions without decoding.
80
+
81
+ **Parameters:**
82
+ - `input: ArrayBuffer | Uint8Array` - Image data
83
+
84
+ **Returns:** `ProbeResult`
85
+ - `format: 'jpeg' | 'png' | 'webp' | 'avif' | 'unknown'`
86
+ - `width: number`
87
+ - `height: number`
88
+ - `hasAlpha: boolean`
89
+
90
+ ## Memory Efficiency
91
+
92
+ The library has two processing modes:
93
+
94
+ ### Standard Mode (Default)
95
+
96
+ Uses `@jsquash/*` packages for decode/encode with scanline-based resize:
97
+ - Only 2 rows in memory during resize
98
+ - Full image decoded to memory first
99
+ - Works for images that fit in Worker memory (~128MB limit)
100
+
101
+ ### Streaming WASM Mode (Optional)
102
+
103
+ For JPEG images when WASM is built, uses ultra-efficient streaming:
104
+ - **DCT Scaling**: Decode JPEG at 1/2, 1/4, or 1/8 scale directly during decompression
105
+ - **Scanline Processing**: Never holds the full image in memory
106
+ - **Peak Memory**: ~50KB for any image size
107
+
108
+ Memory comparison for a 25MP (6800x3900) image:
109
+
110
+ | Mode | Peak Memory |
111
+ |------|-------------|
112
+ | Standard (@jsquash) | ~107MB |
113
+ | Streaming WASM (1/4 scale) | ~50KB |
114
+
115
+ ## Building WASM Module
116
+
117
+ The WASM module is optional. Without it, sip falls back to standard processing.
118
+
119
+ ### Prerequisites
120
+
121
+ - [Emscripten](https://emscripten.org/docs/getting_started/downloads.html)
122
+ - CMake
123
+ - Make
124
+
125
+ ### Build
126
+
127
+ ```bash
128
+ # Install Emscripten (if not already)
129
+ git clone https://github.com/emscripten-core/emsdk.git
130
+ cd emsdk && ./emsdk install latest && ./emsdk activate latest
131
+ source ./emsdk_env.sh
132
+
133
+ # Build WASM
134
+ cd packages/sip
135
+ pnpm build:wasm
136
+ ```
137
+
138
+ This downloads libjpeg-turbo, compiles it to WASM, and generates:
139
+ - `dist/sip.js` - Emscripten loader
140
+ - `dist/sip.wasm` - WebAssembly binary
141
+
142
+ ### Using WASM
143
+
144
+ To enable streaming mode, register the WASM loader before processing:
145
+
146
+ ```typescript
147
+ import { sip } from '@standardagents/sip';
148
+ import createSipModule from '@standardagents/sip/dist/sip.js';
149
+
150
+ // Register WASM loader (once at startup)
151
+ globalThis.__SIP_WASM_LOADER__ = async () => createSipModule();
152
+
153
+ // Now sip.process() will use streaming for JPEG
154
+ const result = await sip.process(jpegBuffer, { maxWidth: 2048 });
155
+ ```
156
+
157
+ ## Architecture
158
+
159
+ ```
160
+ Input → [Probe] → [Decode*] → [Resize] → [Encode*] → Output
161
+ ↓ ↓ ↓
162
+ WASM: DCT Scanline WASM: Scanline
163
+ Scaling Bilinear JPEG Encode
164
+ ```
165
+
166
+ *When WASM is available, decode and encode process one row at a time.
167
+
168
+ ## License
169
+
170
+ UNLICENSED - Proprietary