@gmitch215/tinyimg 1.0.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.
package/dist/wasm.d.ts ADDED
@@ -0,0 +1,367 @@
1
+ import { type BlobKind, type FaceBox, type ImageFormat, type ImageInfo, type RawImage, type Source } from './types.js';
2
+ /**
3
+ * The ABI version this wrapper understands.
4
+ *
5
+ * Bumped in lockstep with `TINYIMG_ABI_VERSION` in `include/tinyimg/tinyimg.h`. A module built against a
6
+ * different one is refused at load, because the alternative is misreading a struct field silently.
7
+ */
8
+ export declare const SUPPORTED_ABI = 1;
9
+ /**
10
+ * What an operation actually did, as counted by the module rather than claimed by its name.
11
+ *
12
+ * See {@link TinyImgModule.measure}.
13
+ */
14
+ export interface WorkCounters {
15
+ /** Samples the source carries, from its header. */
16
+ sourceSamples: number;
17
+ /** Samples the decoder produced. Against `sourceSamples` this is the reduction. */
18
+ decodedSamples: number;
19
+ /** Coefficient blocks read out of an entropy coded stream, which a scale cannot lower. */
20
+ blocks: number;
21
+ /** Inverse transforms performed. */
22
+ transforms: number;
23
+ /** Samples those transforms wrote. */
24
+ transformSamples: number;
25
+ /** `transformSamples / transforms`: 64 for a full block, 4 for a true quarter scale. */
26
+ samplesPerTransform: number;
27
+ /** Macroblocks reconstructed, for the codecs built out of them. */
28
+ macroblocks: number;
29
+ /** Macroblocks put through a loop filter. */
30
+ filtered: number;
31
+ /** Samples a resampler wrote. */
32
+ resampled: number;
33
+ /** Samples handed to an encoder. */
34
+ encoded: number;
35
+ /** Full passes made over an image. */
36
+ passes: number;
37
+ }
38
+ /** What {@link TinyImgModule.measure} hands back. */
39
+ export interface Measured<T> {
40
+ /** Whatever the measured body returned, unchanged. */
41
+ value: T;
42
+ /** What the module counted while it ran. */
43
+ work: WorkCounters;
44
+ }
45
+ /** Optional features a build may or may not contain, mirroring `enum TinyImageFeature`. */
46
+ export declare const Feature: {
47
+ /** SIMD128 was enabled at build time. */
48
+ readonly simd: number;
49
+ /** PNG decode and encode. */
50
+ readonly png: number;
51
+ /** JPEG decode and encode, baseline and progressive. */
52
+ readonly jpeg: number;
53
+ /** BMP decode and encode. */
54
+ readonly bmp: number;
55
+ /** GIF decode and encode. */
56
+ readonly gif: number;
57
+ /** TIFF decode and encode. */
58
+ readonly tiff: number;
59
+ /** WebP decode and encode, lossy and lossless. */
60
+ readonly webp: number;
61
+ /** AVIF container parse; probe answers and decode refuses. */
62
+ readonly avif: number;
63
+ /** Font loading and text drawing. */
64
+ readonly text: number;
65
+ /** Face detection through an LBP cascade. */
66
+ readonly detect: number;
67
+ /** ICC matrix and TRC color management. */
68
+ readonly icc: number;
69
+ };
70
+ /** The name of an optional feature; see {@link Feature}. */
71
+ export type FeatureName = keyof typeof Feature;
72
+ /**
73
+ * The module's exports, as far as this wrapper drives them.
74
+ *
75
+ * @internal
76
+ */
77
+ export interface TinyExports {
78
+ memory: WebAssembly.Memory;
79
+ tiny_init(): void;
80
+ tiny_version(): number;
81
+ tiny_abi_version(): number;
82
+ tiny_features(): number;
83
+ tiny_error_name(code: number): number;
84
+ tiny_work_reset(): void;
85
+ tiny_work_read(counter: number): number;
86
+ tiny_alloc(size: number): number;
87
+ tiny_free(pointer: number): void;
88
+ tiny_arena_reset(): void;
89
+ tiny_image_sizeof(): number;
90
+ tiny_image_info_sizeof(): number;
91
+ tiny_writer_sizeof(): number;
92
+ tiny_plan_sizeof(): number;
93
+ tiny_plan_resolution_sizeof(): number;
94
+ tiny_face_box_sizeof(): number;
95
+ tiny_image_probe(buffer: number, size: number, info: number): number;
96
+ tiny_image_destroy(image: number): number;
97
+ tiny_image_getwidth(image: number): number;
98
+ tiny_image_getheight(image: number): number;
99
+ tiny_image_getchannels(image: number): number;
100
+ tiny_image_getdata(image: number): number;
101
+ tiny_image_getsize(image: number): number;
102
+ tiny_image_getformat(image: number): number;
103
+ tiny_image_load(image: number, buffer: number, size: number): number;
104
+ tiny_image_load_scaled(image: number, buffer: number, size: number, maxWidth: number, maxHeight: number): number;
105
+ tiny_image_encode(image: number, format: number, opts: number, writer: number): number;
106
+ tiny_image_trim(image: number, tolerance: number): number;
107
+ tiny_image_rotate(image: number, degrees: number, background: number): number;
108
+ tiny_image_detect_faces(image: number, boxes: number, capacity: number, count: number): number;
109
+ tiny_writer_init(writer: number, initial: number): number;
110
+ tiny_writer_free(writer: number): void;
111
+ tiny_writer_data(writer: number): number;
112
+ tiny_writer_size(writer: number): number;
113
+ tiny_plan_init(plan: number, buffer: number, size: number): number;
114
+ tiny_plan_init_image(plan: number, image: number): number;
115
+ tiny_plan_set_fusion(plan: number, enabled: number): number;
116
+ tiny_plan_set_effort(plan: number, effort: number): number;
117
+ tiny_plan_background(plan: number, color: number): number;
118
+ tiny_plan_crop(plan: number, x: number, y: number, width: number, height: number): number;
119
+ tiny_plan_resize(plan: number, width: number, height: number): number;
120
+ tiny_plan_resize_with(plan: number, width: number, height: number, filter: number): number;
121
+ tiny_plan_fit(plan: number, width: number, height: number, mode: number, gravity: number): number;
122
+ tiny_plan_fit_with(plan: number, width: number, height: number, mode: number, gravity: number, filter: number): number;
123
+ tiny_plan_flip_horizontal(plan: number): number;
124
+ tiny_plan_flip_vertical(plan: number): number;
125
+ tiny_plan_rotate(plan: number, degrees: number): number;
126
+ tiny_plan_brightness(plan: number, factor: number): number;
127
+ tiny_plan_contrast(plan: number, factor: number): number;
128
+ tiny_plan_saturation(plan: number, factor: number): number;
129
+ tiny_plan_hue(plan: number, degrees: number): number;
130
+ tiny_plan_grayscale(plan: number): number;
131
+ tiny_plan_invert(plan: number): number;
132
+ tiny_plan_gamma(plan: number, gamma: number): number;
133
+ tiny_plan_blur(plan: number, radius: number): number;
134
+ tiny_plan_gaussian_blur(plan: number, sigma: number): number;
135
+ tiny_plan_effect(plan: number, kind: number, params: number): number;
136
+ tiny_plan_count(plan: number): number;
137
+ tiny_plan_resolve(plan: number, resolution: number): number;
138
+ tiny_plan_field(resolution: number, field: number): number;
139
+ tiny_plan_cost(plan: number): number;
140
+ tiny_encode_cost(format: number, width: number, height: number): number;
141
+ tiny_plan_run(plan: number, out: number): number;
142
+ tiny_plan_encode(plan: number, format: number, opts: number, writer: number): number;
143
+ tiny_blob_load(kind: number, id: number, data: number, size: number): number;
144
+ tiny_blob_free(kind: number, id: number): number;
145
+ tiny_blob_free_all(): void;
146
+ tiny_cascade_check(id: number): number;
147
+ }
148
+ /** Thrown when a module cannot be used, as opposed to a call on it failing. */
149
+ export declare class TinyImgLoadError extends Error {
150
+ /** Always `TinyImgLoadError`. */
151
+ readonly name = "TinyImgLoadError";
152
+ }
153
+ /**
154
+ * A loaded tinyimg module.
155
+ *
156
+ * One instance owns one linear memory, so a caller that wants isolation between concurrent requests
157
+ * loads more than one rather than sharing this. Sharing one is normally what you want on Workers:
158
+ * the module is compiled once at worker startup and the memory is reused, and the allocator hands
159
+ * every buffer back at the end of a call.
160
+ */
161
+ export declare class TinyImgModule {
162
+ /** @internal */
163
+ readonly exports: TinyExports;
164
+ private constructor();
165
+ /**
166
+ * Instantiates a compiled module.
167
+ *
168
+ * Takes a `WebAssembly.Module` rather than bytes because workerd refuses
169
+ * `WebAssembly.Module(bytes)` outright ("Wasm code generation disallowed by embedder"). On
170
+ * Workers the module comes from importing the wasm file, which the runtime compiles at worker
171
+ * startup:
172
+ *
173
+ * ```ts
174
+ * import wasm from '@gmitch215/tinyimg/tinyimg.wasm';
175
+ * import { TinyImgModule } from '@gmitch215/tinyimg';
176
+ *
177
+ * const tinyimg = TinyImgModule.load(wasm);
178
+ * ```
179
+ *
180
+ * @param module The compiled module.
181
+ * @return A loaded module ready to use.
182
+ * @throws TinyImgLoadError If the module is not tinyimg, or its ABI is one this wrapper does
183
+ * not understand.
184
+ */
185
+ static load(module: WebAssembly.Module): TinyImgModule;
186
+ /**
187
+ * Compiles and instantiates from bytes.
188
+ *
189
+ * The escape hatch from {@link load}, for node, bun and the browser, where compiling wasm at
190
+ * runtime is allowed. **It throws on Workers**, and that is the runtime's rule rather than this
191
+ * library's: import the wasm file there instead.
192
+ *
193
+ * @param source The module's bytes, in any shape {@link Source} accepts.
194
+ * @return A loaded module ready to use.
195
+ */
196
+ static loadBytes(source: Source): Promise<TinyImgModule>;
197
+ /** The library version, as `[major, minor, patch]`. */
198
+ get version(): [number, number, number];
199
+ /** The library version as `major.minor.patch`. */
200
+ get versionText(): string;
201
+ /** The module's ABI version. Always equal to {@link SUPPORTED_ABI} for a loaded module. */
202
+ get abi(): number;
203
+ /** The module's own linear memory. */
204
+ get memory(): WebAssembly.Memory;
205
+ /** Pages of linear memory the module currently holds. */
206
+ get pages(): number;
207
+ /**
208
+ * Whether a feature was compiled into this module.
209
+ *
210
+ * Worth checking before offering a format in a UI, rather than calling and handling a failure.
211
+ *
212
+ * @param name The feature to check.
213
+ * @return True when the build contains it.
214
+ */
215
+ has(name: FeatureName): boolean;
216
+ /** Every feature this build contains. */
217
+ get features(): FeatureName[];
218
+ /**
219
+ * Reads the name of an error code out of the module.
220
+ *
221
+ * @param code A negative `TinyImageError` value, or 0.
222
+ * @return The short name the module carries for it.
223
+ */
224
+ errorName(code: number): string;
225
+ /**
226
+ * Clears the work counters, then runs `body` and reports what it actually did.
227
+ *
228
+ * Every reduction this library performs is a claim that some work does not happen, and a
229
+ * label is not evidence: the quarter scale decode carried the word "reduced" through the API,
230
+ * the planner and the decoder while transforming whole blocks and averaging the result away.
231
+ * `samplesPerTransform` is the figure that catches that, reading 64 for a full block and 4 for
232
+ * a genuine quarter.
233
+ *
234
+ * The counters are a module-wide total, so nothing else may run against this module while
235
+ * `body` does.
236
+ *
237
+ * @param body The operation to measure. Its result is returned unchanged.
238
+ * @return The operation's result and the counters it produced.
239
+ * @example
240
+ * ```ts
241
+ * const { work } = await tinyimg.measure(() => image.pixels());
242
+ * console.log(work.samplesPerTransform, work.decodedSamples / work.sourceSamples);
243
+ * ```
244
+ */
245
+ measure<T>(body: () => T | Promise<T>): Promise<Measured<T>>;
246
+ /**
247
+ * Reads a file's header without decoding any pixels.
248
+ *
249
+ * Every format the library recognizes, including the ones it cannot decode: an AVIF answers
250
+ * fully here and fails with a specific error on decode.
251
+ *
252
+ * @param source The encoded image.
253
+ * @return What the header says.
254
+ */
255
+ probe(source: Source): Promise<ImageInfo>;
256
+ /**
257
+ * Decodes to raw pixels.
258
+ *
259
+ * The escape hatch below the transformation surface, for a caller who wants the samples
260
+ * themselves: a histogram, a hand-written kernel, or a comparison against another decoder.
261
+ * Prefer {@link transform} or {@link Image} when the answer is another image, because those let
262
+ * the planner decide what to decode and this decodes all of it.
263
+ *
264
+ * @param source The encoded image.
265
+ * @return The extent, the channel count and `width * height * channels` bytes, rows tightly
266
+ * packed.
267
+ */
268
+ decode(source: Source): Promise<RawImage>;
269
+ /**
270
+ * Hands the module a blob it will read later.
271
+ *
272
+ * Nothing large or optional is linked in: fonts, color profiles and detection cascades all
273
+ * arrive at runtime, and the module owns the bytes from here until {@link freeBlob}. Two ways to
274
+ * deliver one, and no code changes between them:
275
+ *
276
+ * ```ts
277
+ * // from a bucket, which costs one subrequest and no bundle bytes
278
+ * const font = await env.BLOBS.get('fonts/DejaVuSans.ttf');
279
+ * if (font) await tinyimg.loadBlob('font', 'sans', font.body);
280
+ *
281
+ * // or imported as a wrangler Data module, which costs bundle bytes and no latency
282
+ * import cascade from './lbp-frontalface.bin';
283
+ * await tinyimg.loadBlob('cascade', 'frontal', cascade);
284
+ * ```
285
+ *
286
+ * Loading over an existing kind and id replaces it. At most eight are resident at once.
287
+ *
288
+ * @param kind What the bytes are.
289
+ * @param id The name the module will find it by, at most 31 characters.
290
+ * @param source The bytes, in any shape {@link Source} accepts.
291
+ * @throws TinyImgError If all eight slots are taken, or a cascade does not parse.
292
+ */
293
+ loadBlob(kind: BlobKind, id: string, source: Source): Promise<void>;
294
+ /**
295
+ * Releases one resident blob.
296
+ *
297
+ * @param kind What to release.
298
+ * @param id The id it was loaded under, or omitted for the first blob of that kind.
299
+ * @return True when one was released.
300
+ */
301
+ freeBlob(kind: BlobKind, id?: string): boolean;
302
+ /** Releases every resident blob. */
303
+ freeBlobs(): void;
304
+ /**
305
+ * Finds the faces in an image.
306
+ *
307
+ * Needs at least one cascade loaded through {@link loadBlob}; with none it throws a
308
+ * {@link TinyImgBlobError} rather than reporting no faces, because the two mean different
309
+ * things. Runs every resident cascade and groups the results, so a frontal and a profile
310
+ * cascade together find both kinds of face and a face that fires both is one box.
311
+ *
312
+ * @param source The encoded image.
313
+ * @param limit Most boxes to return.
314
+ * @return The detections, ordered by confidence, in the source image's own coordinates.
315
+ */
316
+ detectFaces(source: Source, limit?: number): Promise<FaceBox[]>;
317
+ /**
318
+ * A view over the module's memory, taken fresh every time.
319
+ *
320
+ * Never cached: an allocation may grow memory, which detaches the old buffer and leaves any
321
+ * view over it throwing on every access.
322
+ *
323
+ * @internal
324
+ */
325
+ view(): DataView;
326
+ /** @internal */
327
+ bytes(): Uint8Array;
328
+ /** @internal */
329
+ alloc(size: number): number;
330
+ /** @internal */
331
+ free(pointer: number): void;
332
+ /** @internal */
333
+ copyIn(source: Uint8Array): number;
334
+ /**
335
+ * Copies bytes out of the module into a buffer the caller owns.
336
+ *
337
+ * The return type names a real `ArrayBuffer` rather than the `ArrayBufferLike` a view over
338
+ * linear memory carries, because this genuinely allocates one: without that a caller cannot
339
+ * hand the result to a `Blob` or a `Response` without a cast.
340
+ *
341
+ * @internal
342
+ */
343
+ copyOut(pointer: number, size: number): Uint8Array<ArrayBuffer>;
344
+ /** @internal */
345
+ readString(pointer: number): string;
346
+ /** @internal */
347
+ writeString(value: string): number;
348
+ /**
349
+ * Turns a negative result into the error it stands for.
350
+ *
351
+ * @internal
352
+ */
353
+ check(result: number, context: string): void;
354
+ /**
355
+ * Reads a container id back into its name.
356
+ *
357
+ * @internal
358
+ */
359
+ formatName(id: number): ImageFormat | 'unknown';
360
+ /**
361
+ * Turns a format name into the id the module uses.
362
+ *
363
+ * @internal
364
+ */
365
+ formatId(name: ImageFormat): number;
366
+ }
367
+ //# sourceMappingURL=wasm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../src/ts/wasm.ts"],"names":[],"mappings":"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"}
package/dist/wasm.js ADDED
@@ -0,0 +1,283 @@
1
+ import { Err, errorFor, readSource } from './types.js';
2
+ export const SUPPORTED_ABI = 1;
3
+ const Counter = {
4
+ sourceSamples: 0,
5
+ decodedSamples: 1,
6
+ blocks: 2,
7
+ transforms: 3,
8
+ transformSamples: 4,
9
+ macroblocks: 5,
10
+ filtered: 6,
11
+ resampled: 7,
12
+ encoded: 8,
13
+ passes: 9
14
+ };
15
+ export const Feature = {
16
+ simd: 1 << 0,
17
+ png: 1 << 1,
18
+ jpeg: 1 << 2,
19
+ bmp: 1 << 3,
20
+ gif: 1 << 4,
21
+ tiff: 1 << 5,
22
+ webp: 1 << 6,
23
+ avif: 1 << 7,
24
+ text: 1 << 8,
25
+ detect: 1 << 9,
26
+ icc: 1 << 10
27
+ };
28
+ const FORMATS = [
29
+ 'unknown',
30
+ 'png',
31
+ 'jpeg',
32
+ 'bmp',
33
+ 'gif',
34
+ 'tiff',
35
+ 'webp',
36
+ 'avif',
37
+ 'heif'
38
+ ];
39
+ const BLOB_KINDS = { font: 0, icc: 1, cascade: 2 };
40
+ export class TinyImgLoadError extends Error {
41
+ name = 'TinyImgLoadError';
42
+ }
43
+ export class TinyImgModule {
44
+ exports;
45
+ constructor(exports) {
46
+ this.exports = exports;
47
+ exports.tiny_init();
48
+ }
49
+ static load(module) {
50
+ const instance = new WebAssembly.Instance(module, {});
51
+ const exports = instance.exports;
52
+ if (typeof exports.tiny_abi_version !== 'function') {
53
+ throw new TinyImgLoadError('this module does not export tiny_abi_version; is it tinyimg?');
54
+ }
55
+ const abi = exports.tiny_abi_version();
56
+ if (abi !== SUPPORTED_ABI) {
57
+ throw new TinyImgLoadError(`module ABI ${abi} does not match the ${SUPPORTED_ABI} this wrapper understands`);
58
+ }
59
+ return new TinyImgModule(exports);
60
+ }
61
+ static async loadBytes(source) {
62
+ const bytes = await readSource(source);
63
+ const runtime = WebAssembly;
64
+ if (!runtime.compile) {
65
+ throw new TinyImgLoadError('this runtime does not allow compiling wasm from bytes; import the module instead');
66
+ }
67
+ return TinyImgModule.load(await runtime.compile(bytes));
68
+ }
69
+ get version() {
70
+ const packed = this.exports.tiny_version();
71
+ return [(packed >> 16) & 0xff, (packed >> 8) & 0xff, packed & 0xff];
72
+ }
73
+ get versionText() {
74
+ return this.version.join('.');
75
+ }
76
+ get abi() {
77
+ return this.exports.tiny_abi_version();
78
+ }
79
+ get memory() {
80
+ return this.exports.memory;
81
+ }
82
+ get pages() {
83
+ return this.exports.memory.buffer.byteLength / 65536;
84
+ }
85
+ has(name) {
86
+ return (this.exports.tiny_features() & Feature[name]) !== 0;
87
+ }
88
+ get features() {
89
+ const bits = this.exports.tiny_features();
90
+ return Object.keys(Feature).filter((name) => (bits & Feature[name]) !== 0);
91
+ }
92
+ errorName(code) {
93
+ return this.readString(this.exports.tiny_error_name(code));
94
+ }
95
+ async measure(body) {
96
+ this.exports.tiny_work_reset();
97
+ const value = await body();
98
+ const read = (counter) => this.exports.tiny_work_read(counter);
99
+ const transforms = read(Counter.transforms);
100
+ return {
101
+ value,
102
+ work: {
103
+ sourceSamples: read(Counter.sourceSamples),
104
+ decodedSamples: read(Counter.decodedSamples),
105
+ blocks: read(Counter.blocks),
106
+ transforms,
107
+ transformSamples: read(Counter.transformSamples),
108
+ samplesPerTransform: transforms ? read(Counter.transformSamples) / transforms : 0,
109
+ macroblocks: read(Counter.macroblocks),
110
+ filtered: read(Counter.filtered),
111
+ resampled: read(Counter.resampled),
112
+ encoded: read(Counter.encoded),
113
+ passes: read(Counter.passes)
114
+ }
115
+ };
116
+ }
117
+ async probe(source) {
118
+ const bytes = await readSource(source);
119
+ const buffer = this.copyIn(bytes);
120
+ const info = this.alloc(this.exports.tiny_image_info_sizeof());
121
+ try {
122
+ this.check(this.exports.tiny_image_probe(buffer, bytes.byteLength, info), 'probe the image');
123
+ const view = this.view();
124
+ return {
125
+ width: view.getUint32(info, true),
126
+ height: view.getUint32(info + 4, true),
127
+ frames: view.getUint32(info + 8, true),
128
+ format: FORMATS[view.getUint32(info + 12, true)] ?? 'unknown',
129
+ channels: view.getUint8(info + 16),
130
+ bitDepth: view.getUint8(info + 17),
131
+ hasAlpha: view.getUint8(info + 18) !== 0,
132
+ progressive: view.getUint8(info + 19) !== 0
133
+ };
134
+ }
135
+ finally {
136
+ this.free(info);
137
+ this.free(buffer);
138
+ }
139
+ }
140
+ async decode(source) {
141
+ const bytes = await readSource(source);
142
+ const buffer = this.copyIn(bytes);
143
+ const image = this.alloc(this.exports.tiny_image_sizeof());
144
+ try {
145
+ this.check(this.exports.tiny_image_load(image, buffer, bytes.byteLength), 'decode the image');
146
+ try {
147
+ return {
148
+ width: this.exports.tiny_image_getwidth(image),
149
+ height: this.exports.tiny_image_getheight(image),
150
+ channels: this.exports.tiny_image_getchannels(image),
151
+ pixels: this.copyOut(this.exports.tiny_image_getdata(image), this.exports.tiny_image_getsize(image))
152
+ };
153
+ }
154
+ finally {
155
+ this.exports.tiny_image_destroy(image);
156
+ }
157
+ }
158
+ finally {
159
+ this.free(image);
160
+ this.free(buffer);
161
+ }
162
+ }
163
+ async loadBlob(kind, id, source) {
164
+ const bytes = await readSource(source);
165
+ const data = this.copyIn(bytes);
166
+ const name = this.writeString(id);
167
+ try {
168
+ this.check(this.exports.tiny_blob_load(BLOB_KINDS[kind], name, data, bytes.byteLength), `load the ${kind} blob '${id}'`);
169
+ if (kind === 'cascade') {
170
+ this.check(this.exports.tiny_cascade_check(name), `parse the cascade blob '${id}'`);
171
+ }
172
+ }
173
+ finally {
174
+ this.free(name);
175
+ }
176
+ }
177
+ freeBlob(kind, id) {
178
+ const name = id === undefined ? 0 : this.writeString(id);
179
+ try {
180
+ return this.exports.tiny_blob_free(BLOB_KINDS[kind], name) === Err.ok;
181
+ }
182
+ finally {
183
+ if (name !== 0)
184
+ this.free(name);
185
+ }
186
+ }
187
+ freeBlobs() {
188
+ this.exports.tiny_blob_free_all();
189
+ }
190
+ async detectFaces(source, limit = 16) {
191
+ const bytes = await readSource(source);
192
+ const buffer = this.copyIn(bytes);
193
+ const image = this.alloc(this.exports.tiny_image_sizeof());
194
+ const stride = this.exports.tiny_face_box_sizeof();
195
+ const boxes = this.alloc(stride * limit);
196
+ const count = this.alloc(4);
197
+ try {
198
+ this.check(this.exports.tiny_image_load(image, buffer, bytes.byteLength), 'decode the image');
199
+ try {
200
+ this.check(this.exports.tiny_image_detect_faces(image, boxes, limit, count), 'detect faces');
201
+ }
202
+ finally {
203
+ this.exports.tiny_image_destroy(image);
204
+ }
205
+ const view = this.view();
206
+ const found = view.getUint32(count, true);
207
+ const out = [];
208
+ for (let i = 0; i < found; i++) {
209
+ const at = boxes + i * stride;
210
+ out.push({
211
+ x: view.getUint32(at, true),
212
+ y: view.getUint32(at + 4, true),
213
+ width: view.getUint32(at + 8, true),
214
+ height: view.getUint32(at + 12, true),
215
+ neighbors: view.getUint32(at + 16, true)
216
+ });
217
+ }
218
+ return out;
219
+ }
220
+ finally {
221
+ this.free(count);
222
+ this.free(boxes);
223
+ this.free(image);
224
+ this.free(buffer);
225
+ }
226
+ }
227
+ view() {
228
+ return new DataView(this.exports.memory.buffer);
229
+ }
230
+ bytes() {
231
+ return new Uint8Array(this.exports.memory.buffer);
232
+ }
233
+ alloc(size) {
234
+ const pointer = this.exports.tiny_alloc(size);
235
+ if (pointer === 0) {
236
+ throw errorFor(Err.memory, this.errorName(Err.memory), `allocate ${size} bytes`);
237
+ }
238
+ return pointer;
239
+ }
240
+ free(pointer) {
241
+ this.exports.tiny_free(pointer);
242
+ }
243
+ copyIn(source) {
244
+ const pointer = this.alloc(source.byteLength);
245
+ this.bytes().set(source, pointer);
246
+ return pointer;
247
+ }
248
+ copyOut(pointer, size) {
249
+ const out = new Uint8Array(size);
250
+ out.set(this.bytes().subarray(pointer, pointer + size));
251
+ return out;
252
+ }
253
+ readString(pointer) {
254
+ if (pointer === 0)
255
+ return '';
256
+ const memory = this.bytes().subarray(pointer);
257
+ const end = memory.indexOf(0);
258
+ return new TextDecoder().decode(memory.subarray(0, end < 0 ? undefined : end));
259
+ }
260
+ writeString(value) {
261
+ const encoded = new TextEncoder().encode(value);
262
+ const pointer = this.alloc(encoded.byteLength + 1);
263
+ const memory = this.bytes();
264
+ memory.set(encoded, pointer);
265
+ memory[pointer + encoded.byteLength] = 0;
266
+ return pointer;
267
+ }
268
+ check(result, context) {
269
+ if (result >= Err.ok)
270
+ return;
271
+ throw errorFor(result, this.errorName(result), context);
272
+ }
273
+ formatName(id) {
274
+ return FORMATS[id] ?? 'unknown';
275
+ }
276
+ formatId(name) {
277
+ const id = FORMATS.indexOf(name);
278
+ if (id <= 0)
279
+ throw new TypeError(`'${name}' is not a container format`);
280
+ return id;
281
+ }
282
+ }
283
+ //# sourceMappingURL=wasm.js.map