simdra 0.1.0

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.
@@ -0,0 +1,546 @@
1
+ import type { ResampleKernelName, BlurPrecisionName } from '../../zig/simdra.zig';
2
+ /** Output formats stb_image_write can encode (plus `raw` for decoded pixels). */
3
+ export type ImageFormat = 'png' | 'jpeg' | 'bmp' | 'raw';
4
+ /** Sharp-shaped resampling kernel. simdra implements all eight in
5
+ * `effects/SmResampler.zig` so each name maps to its own filter. */
6
+ export type ResizeKernel = ResampleKernelName;
7
+ /** Sharp's `fit` modes. */
8
+ export type ResizeFit = 'cover' | 'contain' | 'fill' | 'inside' | 'outside';
9
+ /** Sharp's `position`. Anchor strings + gravity aliases + content-aware
10
+ * strategies. `'centre'` and `'center'` are equivalent (sharp parity). */
11
+ export type ResizePosition = 'centre' | 'center' | 'top' | 'right' | 'bottom' | 'left' | 'top right' | 'right top' | 'right bottom' | 'bottom right' | 'bottom left' | 'left bottom' | 'left top' | 'top left' | 'north' | 'east' | 'south' | 'west' | 'northeast' | 'southeast' | 'southwest' | 'northwest' | 'entropy' | 'attention';
12
+ export interface BackgroundColor {
13
+ r: number;
14
+ g: number;
15
+ b: number;
16
+ alpha?: number;
17
+ }
18
+ export type BackgroundInput = string | BackgroundColor;
19
+ export interface ResizeOptions {
20
+ width?: number;
21
+ height?: number;
22
+ fit?: ResizeFit;
23
+ position?: ResizePosition;
24
+ background?: BackgroundInput;
25
+ kernel?: ResizeKernel;
26
+ withoutEnlargement?: boolean;
27
+ withoutReduction?: boolean;
28
+ /** Accepted for sharp parity but has no effect — simdra has no
29
+ * shrink-on-load decoder integration. */
30
+ fastShrinkOnLoad?: boolean;
31
+ }
32
+ export type ExtendWithMode = 'background' | 'copy' | 'repeat' | 'mirror';
33
+ /** Sharp's extend() argument: per-edge counts + fill mode + background. */
34
+ export interface ExtendOptions {
35
+ top?: number;
36
+ right?: number;
37
+ bottom?: number;
38
+ left?: number;
39
+ extendWith?: ExtendWithMode;
40
+ background?: BackgroundInput;
41
+ }
42
+ export interface ExtractRegion {
43
+ left: number;
44
+ top: number;
45
+ width: number;
46
+ height: number;
47
+ }
48
+ export interface TrimOptions {
49
+ background?: BackgroundInput;
50
+ /** Allowed per-channel difference from `background`; default 10. */
51
+ threshold?: number;
52
+ /** Accepted for sharp parity — silently ignored (libvips-specific
53
+ * hint that doesn't map to our threshold metric). */
54
+ lineArt?: boolean;
55
+ }
56
+ /** Sharp's composite blend mode strings (libvips/cairo names). Mapped
57
+ * internally to simdra's HTML5-shaped enum. `dest` is identity (no
58
+ * draw). `clear` and `saturate` throw — simdra has no equivalent. */
59
+ export type CompositeBlend = 'clear' | 'source' | 'over' | 'in' | 'out' | 'atop' | 'dest' | 'dest-over' | 'dest-in' | 'dest-out' | 'dest-atop' | 'xor' | 'add' | 'saturate' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'colour-dodge' | 'color-dodge' | 'colour-burn' | 'color-burn' | 'hard-light' | 'soft-light' | 'difference' | 'exclusion';
60
+ /** Channel index or sharp-style channel name. */
61
+ export type ChannelSelector = 0 | 1 | 2 | 3 | 'red' | 'green' | 'blue' | 'alpha';
62
+ /** Bitwise band-boolean op for `bandbool()`. `eor` is libvips's name
63
+ * for XOR; both `xor` and `eor` are accepted at the JS layer. */
64
+ export type BandBoolOp = 'and' | 'or' | 'eor' | 'xor';
65
+ /** Sharp's gravity strings for composite placement. Same set as
66
+ * `ResizePosition` minus the content-aware strategies. */
67
+ export type CompositeGravity = 'centre' | 'center' | 'top' | 'right' | 'bottom' | 'left' | 'top right' | 'right top' | 'top left' | 'left top' | 'bottom right' | 'right bottom' | 'bottom left' | 'left bottom' | 'north' | 'east' | 'south' | 'west' | 'northeast' | 'southeast' | 'southwest' | 'northwest';
68
+ /** Sharp-style raw-pixel descriptor — sibling of `input`, not nested.
69
+ * When set, `input` is treated as raw RGBA bytes of the given dims. */
70
+ export interface CompositeRawDescriptor {
71
+ width: number;
72
+ height: number;
73
+ /** Currently must be `4` (RGBA). 1-channel grey, 2-channel grey+alpha,
74
+ * and 3-channel RGB inputs are rejected — the blend kernels operate
75
+ * on RGBA8 only. */
76
+ channels: number;
77
+ }
78
+ /** "Create" input for a composite overlay — a flat-colour rectangle
79
+ * built on the fly. Mirrors sharp's `{ input: { create: ... } }`. */
80
+ export interface CompositeCreateInput {
81
+ width: number;
82
+ height: number;
83
+ channels: 3 | 4;
84
+ background: BackgroundInput;
85
+ }
86
+ export type CompositeOverlayInput = Uint8Array | ArrayBuffer | Blob | ReadableStream<Uint8Array> | Response | {
87
+ create: CompositeCreateInput;
88
+ };
89
+ export interface CompositeImage {
90
+ /** Encoded image bytes, a stream/blob/response producing them, or a
91
+ * `{ create }` flat-colour rectangle. To pass raw RGBA pixels, set
92
+ * `input` to the byte buffer AND provide a sibling `raw: {width,
93
+ * height, channels}` (sharp parity). */
94
+ input: CompositeOverlayInput;
95
+ /** Sharp-style raw-pixel descriptor — sibling of `input`. When set,
96
+ * `input` is interpreted as RGBA bytes of the given dimensions
97
+ * rather than as encoded image bytes. */
98
+ raw?: CompositeRawDescriptor;
99
+ /** Blend mode (libvips/cairo name); default `'over'` (source-over). */
100
+ blend?: CompositeBlend;
101
+ /** Anchor for placement when `top`/`left` aren't given. Default
102
+ * `'centre'`. Ignored when both `top` and `left` are provided. */
103
+ gravity?: CompositeGravity;
104
+ /** Explicit pixel offset from the top edge. Pairs with `left` to
105
+ * override `gravity`. */
106
+ top?: number;
107
+ /** Explicit pixel offset from the left edge. Pairs with `top` to
108
+ * override `gravity`. */
109
+ left?: number;
110
+ /** Tile the overlay across the base bitmap. */
111
+ tile?: boolean;
112
+ /** Sharp's premultiplied flag — accepted for compatibility but not
113
+ * applied: simdra always uses non-premultiplied bytes at the
114
+ * bitmap layer. The blend math is done in-channel by the canvas
115
+ * blit kernels, which is the libvips-equivalent semantic. */
116
+ premultiplied?: boolean;
117
+ /** Accepted but ignored — simdra doesn't parse EXIF orientation. */
118
+ autoOrient?: boolean;
119
+ /** Accepted but ignored — simdra doesn't decode multi-frame inputs
120
+ * in the composite path. */
121
+ animated?: boolean;
122
+ /** Accepted but ignored — DPI is meaningful only for vector inputs
123
+ * (SVG/PDF) we don't decode. */
124
+ density?: number;
125
+ }
126
+ /** Per-call PNG options scoped to what stb_image_write exposes. */
127
+ export interface PngOptions {
128
+ /** stb's compression level (0 = fastest/largest, 9 = slowest/smallest).
129
+ * Wraps stb's process-global `stbi_write_png_compression_level` under
130
+ * a mutex on the Zig side, so concurrent encodes from different
131
+ * pthreads (native build) don't race on the level. */
132
+ compressionLevel?: number;
133
+ }
134
+ /** Per-call JPEG options scoped to what stb_image_write exposes. */
135
+ export interface JpegOptions {
136
+ /** HTML5-style 0.0–1.0 quality. Mapped to stb's 1–100 scale internally. */
137
+ quality?: number;
138
+ }
139
+ /** Source-format names returned from `metadata().format` (signature sniff). */
140
+ export type ImageFormatName = 'png' | 'jpeg' | 'bmp' | 'gif' | 'unknown';
141
+ /** Output info attached to `toBuffer({ resolveWithObject: true })`. Shape
142
+ * is intentionally narrower than sharp's — only fields that have an
143
+ * honest answer with stb_image_write's encoders are populated.
144
+ * `premultiplied`, crop offsets, attention focal points, animation
145
+ * metadata, and `textAutofitDpi` are libvips features and are not set. */
146
+ export interface OutputInfo {
147
+ format: ImageFormat;
148
+ size: number;
149
+ width: number;
150
+ height: number;
151
+ /** PNG = 4 (RGBA preserved), JPEG = 3 (alpha dropped — JPEG can't store
152
+ * alpha), BMP = 4 (32-bit V4 with alpha mask), raw = 4 (RGBA pixels). */
153
+ channels: number;
154
+ }
155
+ /** Options for the `toBuffer()` terminal. */
156
+ export interface ToBufferOptions {
157
+ /** When `true`, the terminal resolves with `{ data, info }` instead of
158
+ * just `data`. Mirrors sharp's option of the same name. */
159
+ resolveWithObject?: boolean;
160
+ }
161
+ /**
162
+ * Header-only metadata, mirroring sharp's `metadata()` semantics — populated
163
+ * from stb_image's `stbi_info_from_memory` + `stbi_is_16_bit_from_memory`
164
+ * fast path with no pixel decode and no allocation.
165
+ *
166
+ * The fields are limited to what stb_image's public API actually exposes;
167
+ * sharp's libvips-backed extras (ICC, EXIF, density, orientation, pages,
168
+ * isProgressive, …) are not surfaced because the decoder doesn't read them.
169
+ */
170
+ export interface Metadata {
171
+ /** Container detected by signature sniff. `'unknown'` if no match. */
172
+ format: ImageFormatName;
173
+ /** Pixel width as stored in the file header. */
174
+ width: number;
175
+ /** Pixel height as stored in the file header. */
176
+ height: number;
177
+ /** Source channel count: 1 grey, 2 grey+alpha, 3 RGB, 4 RGBA. */
178
+ channels: number;
179
+ /** True iff `channels === 2 || channels === 4`. */
180
+ hasAlpha: boolean;
181
+ /** Bits per channel sample (8 or 16) per stb_image. */
182
+ bitsPerSample: number;
183
+ /** Total input size in bytes (sharp parity for `Buffer` / stream input). */
184
+ size: number;
185
+ }
186
+ export type MicroSharpInput = Uint8Array | ArrayBuffer | Blob | ReadableStream<Uint8Array> | Response;
187
+ /** Sharp's affine `interpolator` option. Mapped to simdra's two
188
+ * bitmap-direct samplers (nearest / bilinear). The libvips-only
189
+ * kernels (`nohalo`, `lbb`, `vsqbs`) collapse to `bilinear` — they
190
+ * exist in libvips for very-precise resamplers we don't ship. */
191
+ export type AffineInterpolator = 'nearest' | 'bilinear' | 'bicubic' | 'nohalo' | 'lbb' | 'vsqbs';
192
+ export interface RotateOptions {
193
+ background?: BackgroundInput;
194
+ }
195
+ /** Sharp's `blur(opts)` argument set. Bare `sigma` number is also
196
+ * accepted in the method signature. `precision` defaults to
197
+ * `'integer'` (matches sharp). */
198
+ export interface BlurOptions {
199
+ sigma?: number;
200
+ precision?: BlurPrecisionName;
201
+ minAmplitude?: number;
202
+ }
203
+ /** Sharp's `sharpen(opts)` argument set. */
204
+ export interface SharpenOptions {
205
+ sigma?: number;
206
+ m1?: number;
207
+ m2?: number;
208
+ x1?: number;
209
+ y2?: number;
210
+ y3?: number;
211
+ }
212
+ /** Sharp's `convolve(kernel)` argument. `kernel` is row-major and must
213
+ * have `width * height` entries. `scale` defaults to the sum of
214
+ * kernel values; `offset` defaults to 0. */
215
+ export interface ConvolveKernel {
216
+ width: number;
217
+ height: number;
218
+ kernel: ArrayLike<number>;
219
+ scale?: number;
220
+ offset?: number;
221
+ }
222
+ export interface NegateOptions {
223
+ /** Whether to negate the alpha channel. Sharp default: `true`. */
224
+ alpha?: boolean;
225
+ }
226
+ export interface ThresholdOptions {
227
+ /** Convert to single-channel greyscale before thresholding (sharp
228
+ * default: `true`). When `false`, threshold is applied per RGB
229
+ * channel. */
230
+ greyscale?: boolean;
231
+ /** Alternative spelling for `greyscale` (sharp parity). */
232
+ grayscale?: boolean;
233
+ }
234
+ export interface FlattenOptions {
235
+ /** Background colour to merge alpha against. Sharp default `#000000`. */
236
+ background?: BackgroundInput;
237
+ }
238
+ export type BooleanOperator = 'and' | 'or' | 'eor';
239
+ export interface BooleanOptions {
240
+ /** Sharp's raw-pixel descriptor — sibling of `operand`. When set,
241
+ * the operand bytes are interpreted as RGBA / RGB / grey of the
242
+ * given dimensions rather than encoded image bytes. */
243
+ raw?: CompositeRawDescriptor;
244
+ }
245
+ export interface NormaliseOptions {
246
+ /** Percentile below which luma is clipped to 0. Sharp default 1. */
247
+ lower?: number;
248
+ /** Percentile above which luma is clipped to 255. Sharp default 99. */
249
+ upper?: number;
250
+ }
251
+ export interface ClaheOptions {
252
+ /** Tile width in pixels. Required. */
253
+ width: number;
254
+ /** Tile height in pixels. Required. */
255
+ height: number;
256
+ /** Contrast-clip slope. Sharp default 3; 0 disables clipping. */
257
+ maxSlope?: number;
258
+ }
259
+ export interface ModulateOptions {
260
+ /** Multiplier on V (HSV value). Default 1. */
261
+ brightness?: number;
262
+ /** Multiplier on S (HSV saturation). Default 1. */
263
+ saturation?: number;
264
+ /** Hue rotation in degrees. Default 0. */
265
+ hue?: number;
266
+ /** Additive offset on V (luminance). Default 0. */
267
+ lightness?: number;
268
+ }
269
+ /** Sharp's `recomb(inputMatrix)` matrix shape: 3×3 (RGB-only) or 4×4
270
+ * (full RGBA). Accepts row-major flat lists too. */
271
+ export type RecombMatrix = readonly [
272
+ readonly [number, number, number],
273
+ readonly [number, number, number],
274
+ readonly [number, number, number]
275
+ ] | readonly [
276
+ readonly [number, number, number, number],
277
+ readonly [number, number, number, number],
278
+ readonly [number, number, number, number],
279
+ readonly [number, number, number, number]
280
+ ] | ArrayLike<number>;
281
+ export interface AffineOptions {
282
+ background?: BackgroundInput;
283
+ idx?: number;
284
+ idy?: number;
285
+ odx?: number;
286
+ ody?: number;
287
+ interpolator?: AffineInterpolator;
288
+ }
289
+ /** Sharp's `affine(matrix, ...)` — matrix is a length-4 array
290
+ * `[a, b, c, d]` (row-major: `[[a, b], [c, d]]`) or a 2×2 nested
291
+ * form `[[a, b], [c, d]]`. */
292
+ export type AffineMatrix = readonly [number, number, number, number] | readonly [readonly [number, number], readonly [number, number]];
293
+ export declare class MicroSharpPipeline {
294
+ private readonly input;
295
+ private materialized;
296
+ private outputFormat;
297
+ private jpegQuality;
298
+ private pngCompressionLevel;
299
+ private readonly ops;
300
+ /** Recorded `pipelineColourspace`. `'b-w'`/`'grey16'` injects a leading
301
+ * greyscale at apply time; other recognised values are no-ops on our
302
+ * RGBA8 sRGB pipeline (documented in COMPATIBILITY.md). */
303
+ private pipelineColourspaceSetting;
304
+ /** Recorded `toColourspace`. Same semantics as the pipeline knob, but
305
+ * the greyscale (when triggered) runs *after* all queued ops. */
306
+ private toColourspaceSetting;
307
+ constructor(input: MicroSharpInput);
308
+ /**
309
+ * Sharp-shaped resize. Three call forms:
310
+ * .resize(width, height, opts?)
311
+ * .resize(width, opts?) — auto-scales height from source aspect
312
+ * .resize({ width, height, ...opts })
313
+ *
314
+ * Per sharp: only one resize op survives per pipeline; subsequent
315
+ * `.resize()` calls replace the recorded op rather than appending.
316
+ */
317
+ resize(widthOrOpts?: number | (ResizeOptions & {
318
+ width?: number;
319
+ height?: number;
320
+ }) | null, heightOrOpts?: number | ResizeOptions | null, opts?: ResizeOptions): this;
321
+ /** Pad / extrude the image. Sharp accepts a number (all four edges)
322
+ * or a per-edge object with optional `extendWith` and `background`. */
323
+ extend(opts: number | ExtendOptions): this;
324
+ /** Crop a sub-rectangle. Validated against the *current* bitmap at
325
+ * apply time, not at queue time. */
326
+ extract(region: ExtractRegion): this;
327
+ /** Trim background-coloured edges. Default background = top-left
328
+ * pixel of the working bitmap (sharp parity); default threshold = 10. */
329
+ trim(opts?: TrimOptions): this;
330
+ /** Composite one or more overlays onto the working bitmap. Each
331
+ * entry's `input` is materialized at apply time (so streams, blobs,
332
+ * and responses work for overlays just like they do for the
333
+ * pipeline's primary input). Overlays are drawn in array order;
334
+ * later entries can blend over earlier ones. */
335
+ composite(images: CompositeImage[]): this;
336
+ /** Strip alpha — sets α=255 on every pixel. Sharp's docs describe
337
+ * this as "the output image is a 3 channel image without an alpha
338
+ * channel"; in microsharp the buffer remains 4-channel for
339
+ * pipeline-shape invariance, but the result is visibly identical
340
+ * (all pixels fully opaque). */
341
+ removeAlpha(): this;
342
+ /** Sharp's `ensureAlpha([alpha])`. Microsharp bitmaps always carry
343
+ * an alpha channel, so this is a no-op without an argument. With
344
+ * an explicit `alpha` (0..1) the channel is set to that constant
345
+ * level — useful right after `removeAlpha` to set a non-opaque
346
+ * uniform alpha, or to force a known transparency level on a
347
+ * decoded source. */
348
+ ensureAlpha(alpha?: number): this;
349
+ /** Extract a single channel as a greyscale image. `channel` accepts
350
+ * the integer index 0/1/2/3 or sharp's string names
351
+ * 'red'/'green'/'blue'/'alpha'. The result is RGB = chosen channel,
352
+ * α = 255. */
353
+ extractChannel(channel: ChannelSelector): this;
354
+ /** Per-pixel bitwise op across R, G, B channels — produces a
355
+ * greyscale image where each pixel is `(R op G op B)` broadcast.
356
+ * Accepts sharp's `'and'` / `'or'` / `'eor'` (libvips name for
357
+ * XOR); plain `'xor'` is also accepted. */
358
+ bandbool(op: BandBoolOp): this;
359
+ /** Sharp's `tint(colour)` — recolour using the given RGB tint while
360
+ * preserving the per-pixel luminance pattern. Alpha is unchanged
361
+ * (sharp spec). The colour can be a CSS string or
362
+ * `{ r, g, b, alpha? }` object; the alpha component is parsed for
363
+ * compatibility but ignored — the tint operation is RGB-only. */
364
+ tint(colour: BackgroundInput): this;
365
+ /** Sharp's `rotate([angle], [opts])`. With no arguments this is the
366
+ * back-compat alias for `autoOrient()`. With a finite angle it
367
+ * rotates by that many degrees clockwise, padding with `background`
368
+ * (default opaque black). Multiples of 90° are byte-exact (lossless
369
+ * index permutation); other angles sample through bilinear
370
+ * interpolation against the source-bbox AABB. Sharp parity:
371
+ * multi-page input is not supported — simdra decodes one frame. */
372
+ rotate(angle?: number, opts?: RotateOptions): this;
373
+ /** Sharp's `autoOrient()` — read the EXIF Orientation tag from the
374
+ * input bytes and apply the corresponding rotation / mirror. simdra
375
+ * parses Orientation only (no full EXIF library); the tag is read
376
+ * by `SmBitmap.peekOrientation` against the materialised input
377
+ * bytes at apply time. Missing / malformed EXIF → no-op. */
378
+ autoOrient(): this;
379
+ /** Sharp's `flip([on])` — mirror vertically (top↔bottom). */
380
+ flip(on?: boolean): this;
381
+ /** Sharp's `flop([on])` — mirror horizontally (left↔right). */
382
+ flop(on?: boolean): this;
383
+ /** Sharp's `affine(matrix, [opts])`. `matrix` is `[a, b, c, d]`
384
+ * (`[[a, b], [c, d]]`) — the linear part of `F(x, y) = M·(x+idx,
385
+ * y+idy) + (odx, ody)`. Output dims = forward bbox of the input
386
+ * rectangle; the gap is padded with `background` (default opaque
387
+ * black). `interpolator` accepts sharp/libvips kernel names; the
388
+ * three high-precision kernels libvips ships (`nohalo`/`lbb`/
389
+ * `vsqbs`) collapse to `bilinear` here — see COMPATIBILITY.md. */
390
+ affine(matrix: AffineMatrix, opts?: AffineOptions): this;
391
+ /** Sharp's `blur([opts])`.
392
+ * - No args / `true`: fast 3×3 box blur.
393
+ * - `false`: no-op (records nothing).
394
+ * - bare `sigma` number: Gaussian blur with the chosen sigma.
395
+ * - `{ sigma, precision, minAmplitude }`: same with explicit
396
+ * working-precision and kernel-amplitude cutoff.
397
+ * `precision` defaults to `'integer'`; `minAmplitude` to `0.2`
398
+ * (sharp's defaults). Sigma must be in [0.3, 1000]. */
399
+ blur(opts?: number | boolean | BlurOptions): this;
400
+ /** Sharp's `sharpen([opts], [flat], [jagged])`.
401
+ * - No args: fast 3×3 unsharp kernel `[[0,-1,0],[-1,5,-1],[0,-1,0]]`.
402
+ * - `{ sigma, m1, m2, x1, y2, y3 }`: libvips USM with the flat /
403
+ * jagged piecewise gain. Per-channel in 8-bit sRGB (sharp's
404
+ * LAB-L pipeline isn't available — documented 🟡 in COMPATIBILITY).
405
+ * - Deprecated 2-positional form `sharpen(sigma, flat, jagged)`:
406
+ * surfaces with `flat = m1`, `jagged = m2`. Sharp parity. */
407
+ sharpen(opts?: number | SharpenOptions, flat?: number, jagged?: number): this;
408
+ /** Sharp's `median([size])`. Square `size × size` window per RGB
409
+ * channel; α preserved. `size` defaults to 3 and must be odd. */
410
+ median(size?: number): this;
411
+ /** Sharp's `dilate([width])`. Foreground expansion by a separable
412
+ * `(2·width+1)`-square max-window. `width` defaults to 1. */
413
+ dilate(width?: number): this;
414
+ /** Sharp's `erode([width])`. Foreground shrinking — same shape as
415
+ * `dilate`, opposite kernel direction. */
416
+ erode(width?: number): this;
417
+ /** Sharp's `convolve(kernel)`. `kernel.kernel` length must equal
418
+ * `width · height`; both dims must be odd. `scale` defaults to the
419
+ * sum of kernel values; `offset` defaults to 0. Edge mode is
420
+ * clamp (libvips's default). */
421
+ convolve(spec: ConvolveKernel): this;
422
+ /** Sharp's `gamma([gamma], [gammaOut])`. Applies a single LUT
423
+ * `(in/255)^(gIn/gOut)·255` per RGB channel; α preserved. Sharp's
424
+ * pre-/post-resize coupling collapses to a single pass without an
425
+ * intervening resize — documented 🟡 in COMPATIBILITY.md. Both
426
+ * values must be in [1.0, 3.0]; `gOut` defaults to `gIn`. */
427
+ gamma(g?: number, gOut?: number): this;
428
+ /** Sharp's `negate([opts])`. RGB inverted; α negated when
429
+ * `opts.alpha !== false` (sharp default `true`). */
430
+ negate(opts?: NegateOptions): this;
431
+ /** Sharp's `linear([a], [b])`. Per-channel `a·C + b` with output
432
+ * clipped to [0, 255]. Both arguments accept a single number (RGB
433
+ * broadcast, alpha untouched), a length-3 array (RGB), or a
434
+ * length-4 array (RGBA). Defaults: `a=1`, `b=0` per channel. */
435
+ linear(a?: number | ArrayLike<number>, b?: number | ArrayLike<number>): this;
436
+ /** Sharp's `threshold([t], [opts])`. `t` defaults to 128; sharp
437
+ * accepts 0..255. With `greyscale=true` (default), Rec.601 luma is
438
+ * computed first and broadcast. */
439
+ threshold(t?: number, opts?: ThresholdOptions): this;
440
+ /** Sharp's `recomb(matrix)`. 3×3 (RGB only, α preserved) or 4×4
441
+ * (full RGBA) row-major colour matrix. Accepts nested form
442
+ * `[[a,b,c],[d,e,f],[g,h,i]]` or flat `[a,b,c,d,e,f,g,h,i]`. */
443
+ recomb(matrix: RecombMatrix): this;
444
+ /** Sharp's `flatten([opts])`. Alpha-blend onto an opaque background
445
+ * and drop alpha. Buffer remains 4-channel for pipeline-shape
446
+ * invariance (α=255 across the result). */
447
+ flatten(opts?: FlattenOptions): this;
448
+ /** Sharp's `unflatten()`. Every pixel where `R=G=B=255` becomes
449
+ * fully transparent (α=0); other pixels are unchanged. */
450
+ unflatten(): this;
451
+ /** Sharp's `boolean(operand, operator, [opts])`. Per-pixel bitwise
452
+ * `and` / `or` / `eor` (libvips name for XOR) across all four
453
+ * RGBA bands between this bitmap and `operand`. The operand is
454
+ * materialised at apply time (encoded image bytes by default;
455
+ * `opts.raw` for pre-decoded pixels — same shape as `joinChannel`). */
456
+ boolean(operand: CompositeOverlayInput, operator: BooleanOperator | 'xor', opts?: BooleanOptions): this;
457
+ /** Sharp's `normalise([opts])`. Stretch the luma percentile range
458
+ * `[lower, upper]` to `[0, 255]` and broadcast the same affine map
459
+ * to all RGB channels. α preserved. Defaults `lower: 1`, `upper: 99`. */
460
+ normalise(opts?: NormaliseOptions): this;
461
+ /** Alternative spelling of `normalise()` (sharp parity). */
462
+ normalize(opts?: NormaliseOptions): this;
463
+ /** Sharp's `clahe({ width, height, maxSlope? })`. Tile-based local
464
+ * histogram equalisation with bilinear interpolation between tile
465
+ * centres. `maxSlope` defaults to 3 (sharp parity); 0 disables the
466
+ * contrast clip and reduces to plain AHE. */
467
+ clahe(opts: ClaheOptions): this;
468
+ /** Sharp's `modulate({ brightness, saturation, hue, lightness })`.
469
+ * Applied in HSV space (sharp uses LCh; documented 🟡 in
470
+ * COMPATIBILITY.md). All four arguments are optional. α preserved. */
471
+ modulate(opts?: ModulateOptions): this;
472
+ /** Sharp's `greyscale([on])`. `on` defaults to `true`; passing `false`
473
+ * records nothing (sharp parity). Computes Rec.601 luma in 8-bit
474
+ * sRGB space — for a true linear-space conversion sharp recommends
475
+ * chaining a future `gamma()` op. */
476
+ greyscale(on?: boolean): this;
477
+ /** Alternative spelling of `greyscale()` (sharp parity). */
478
+ grayscale(on?: boolean): this;
479
+ /** Sharp's `pipelineColourspace([cs])`. Records the requested input
480
+ * colourspace; `b-w` / `grey16` triggers a leading greyscale so the
481
+ * rest of the pipeline runs on luma values. Other recognised libvips
482
+ * colourspace names are accepted as no-ops because simdra has no
483
+ * 16-bit / LAB / CMYK pipeline (documented in COMPATIBILITY.md).
484
+ * Unrecognised strings throw `RangeError`. */
485
+ pipelineColourspace(cs?: string): this;
486
+ /** Alternative spelling of `pipelineColourspace()` (sharp parity). */
487
+ pipelineColorspace(cs?: string): this;
488
+ /** Sharp's `toColourspace([cs])`. Records the requested output
489
+ * colourspace; `b-w` / `grey16` triggers a tail greyscale (buffer
490
+ * stays 4-channel for pipeline-shape invariance). All other
491
+ * recognised libvips colourspace names are 8-bit sRGB passthrough
492
+ * no-ops. Unrecognised strings throw `RangeError`. */
493
+ toColourspace(cs?: string): this;
494
+ /** Alternative spelling of `toColourspace()` (sharp parity). */
495
+ toColorspace(cs?: string): this;
496
+ /** Sharp's `joinChannel(image, options?)` — replace this bitmap's
497
+ * alpha channel with Rec.601 luma of the joined image's RGB.
498
+ *
499
+ * Microsharp's always-RGBA model can't grow beyond 4 channels, so
500
+ * we handle the common case (single mask image → new alpha) rather
501
+ * than libvips's full N-band append. Multi-image arrays and
502
+ * multi-band joins beyond RGBA aren't supported: pass a single
503
+ * Buffer/typed-array, or a `{ raw: { width, height, channels: 1|3|4 } }`
504
+ * options descriptor for pre-decoded mask pixels.
505
+ *
506
+ * Greyscale (1-channel) and grey+alpha (1- or 4-channel with
507
+ * R=G=B) masks round-trip exactly: luma collapses to R. RGB masks
508
+ * are converted via `0.299·R + 0.587·G + 0.114·B`. */
509
+ joinChannel(image: CompositeOverlayInput | CompositeOverlayInput[], options?: {
510
+ raw?: {
511
+ width: number;
512
+ height: number;
513
+ channels: number;
514
+ };
515
+ }): this;
516
+ png(opts?: PngOptions): this;
517
+ /** `quality` is the HTML5 0.0–1.0 range; default 0.92 (Chromium default).
518
+ * Accepts either a bare number or sharp's `{ quality }` object form. */
519
+ jpeg(opts?: number | JpegOptions): this;
520
+ /** 32-bit BMP V4 (stb's `comp=4` path; preserves alpha via BI_BITFIELDS). */
521
+ bmp(): this;
522
+ /** Raw RGBA pixel data. Channel ordering is RGBA, top-to-bottom, no
523
+ * padding (forced 4-channel by the stb_image decode path). */
524
+ raw(): this;
525
+ /** Force output format. Sharp accepts an object with an `id` attribute
526
+ * for libvips-specific format options; we accept the string only. */
527
+ toFormat(format: ImageFormat): this;
528
+ toBuffer(opts: ToBufferOptions & {
529
+ resolveWithObject: true;
530
+ }): Promise<{
531
+ data: Uint8Array;
532
+ info: OutputInfo;
533
+ }>;
534
+ toBuffer(opts?: ToBufferOptions): Promise<Uint8Array>;
535
+ private encodeBitmap;
536
+ metadata(): Promise<Metadata>;
537
+ private getInput;
538
+ /** Run each queued op in order. Each op consumes the previous bitmap
539
+ * and returns a fresh one; the consumed bitmap is released
540
+ * immediately to keep peak memory bounded. Async because
541
+ * `composite` may need to await overlay materialization (decode
542
+ * bytes, drain a stream, etc.). */
543
+ private applyOps;
544
+ private runOp;
545
+ }
546
+ export declare function microsharp(input: MicroSharpInput): MicroSharpPipeline;