imgcraft 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.
- package/README.md +98 -0
- package/dist/adapters/runtime.d.ts +7 -0
- package/dist/adapters/runtime.d.ts.map +1 -0
- package/dist/adapters/runtime.js +16 -0
- package/dist/adapters/runtime.js.map +1 -0
- package/dist/batch.d.ts +60 -0
- package/dist/batch.d.ts.map +1 -0
- package/dist/batch.js +207 -0
- package/dist/batch.js.map +1 -0
- package/dist/engines/node.d.ts +8 -0
- package/dist/engines/node.d.ts.map +1 -0
- package/dist/engines/node.js +176 -0
- package/dist/engines/node.js.map +1 -0
- package/dist/engines/wasm.d.ts +8 -0
- package/dist/engines/wasm.d.ts.map +1 -0
- package/dist/engines/wasm.js +199 -0
- package/dist/engines/wasm.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/pipeline.d.ts +45 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +135 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/transforms/ai.d.ts +6 -0
- package/dist/transforms/ai.d.ts.map +1 -0
- package/dist/transforms/ai.js +143 -0
- package/dist/transforms/ai.js.map +1 -0
- package/dist/types.d.ts +158 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { ImgCraftError } from '../types.js';
|
|
2
|
+
let photonCache = null;
|
|
3
|
+
async function importPhoton() {
|
|
4
|
+
if (photonCache !== null)
|
|
5
|
+
return photonCache;
|
|
6
|
+
try {
|
|
7
|
+
// Dynamic import respects the exports map — node condition in Node.js,
|
|
8
|
+
// workerd/default in Cloudflare Workers, browser bundler picks its own entry.
|
|
9
|
+
const mod = (await import('@cf-wasm/photon/node'));
|
|
10
|
+
photonCache = mod;
|
|
11
|
+
return mod;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
throw new ImgCraftError({
|
|
15
|
+
code: 'WASM_NOT_AVAILABLE',
|
|
16
|
+
message: '@cf-wasm/photon is required for browser/WASM image processing. Install it: npm install @cf-wasm/photon',
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function toUint8Array(input) {
|
|
21
|
+
if (typeof input === 'string') {
|
|
22
|
+
if (typeof fetch !== 'undefined') {
|
|
23
|
+
const res = await fetch(input);
|
|
24
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
25
|
+
}
|
|
26
|
+
throw new ImgCraftError({
|
|
27
|
+
code: 'UNSUPPORTED_INPUT',
|
|
28
|
+
message: 'File path inputs are not supported in the browser WASM engine. Use a URL or Blob.',
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (input instanceof Uint8Array)
|
|
32
|
+
return input;
|
|
33
|
+
if (input instanceof Buffer)
|
|
34
|
+
return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
35
|
+
if (input instanceof ArrayBuffer)
|
|
36
|
+
return new Uint8Array(input);
|
|
37
|
+
if (input instanceof URL) {
|
|
38
|
+
const res = await fetch(input);
|
|
39
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
40
|
+
}
|
|
41
|
+
throw new ImgCraftError({
|
|
42
|
+
code: 'INVALID_INPUT',
|
|
43
|
+
message: 'Unsupported input type for WASM engine.',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function warnUnsupported(opName) {
|
|
47
|
+
console.warn(`[imgcraft/wasm] "${opName}" is not supported in the WASM engine. Skipping.`);
|
|
48
|
+
}
|
|
49
|
+
function outputFormat(ops) {
|
|
50
|
+
let format = 'jpeg';
|
|
51
|
+
let quality;
|
|
52
|
+
for (const op of ops) {
|
|
53
|
+
if (op.op === 'format') {
|
|
54
|
+
format = op.options.format;
|
|
55
|
+
if (op.options.quality !== undefined)
|
|
56
|
+
quality = op.options.quality;
|
|
57
|
+
}
|
|
58
|
+
else if (op.op === 'quality') {
|
|
59
|
+
quality = op.value;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { format, quality };
|
|
63
|
+
}
|
|
64
|
+
function encodePhoton(photon, img, format, quality) {
|
|
65
|
+
switch (format) {
|
|
66
|
+
case 'jpeg':
|
|
67
|
+
return { data: img.get_bytes_jpeg(quality ?? 85), format: 'jpeg' };
|
|
68
|
+
case 'webp':
|
|
69
|
+
return { data: img.get_bytes_webp(), format: 'webp' };
|
|
70
|
+
case 'png':
|
|
71
|
+
return { data: img.get_bytes(), format: 'png' };
|
|
72
|
+
case 'avif':
|
|
73
|
+
console.warn('[imgcraft/wasm] avif is not supported in the WASM engine. Using WebP instead.');
|
|
74
|
+
return { data: img.get_bytes_webp(), format: 'webp' };
|
|
75
|
+
case 'tiff':
|
|
76
|
+
console.warn('[imgcraft/wasm] tiff is not supported in the WASM engine. Using PNG instead.');
|
|
77
|
+
return { data: img.get_bytes(), format: 'png' };
|
|
78
|
+
default:
|
|
79
|
+
console.warn(`[imgcraft/wasm] Unknown format "${format}". Using PNG.`);
|
|
80
|
+
return { data: img.get_bytes(), format: 'png' };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export async function processWasm(state) {
|
|
84
|
+
const photon = await importPhoton();
|
|
85
|
+
const bytes = await toUint8Array(state.input);
|
|
86
|
+
let img = photon.PhotonImage.new_from_byteslice(bytes);
|
|
87
|
+
const { format, quality } = outputFormat(state.ops);
|
|
88
|
+
try {
|
|
89
|
+
for (const op of state.ops) {
|
|
90
|
+
switch (op.op) {
|
|
91
|
+
case 'resize': {
|
|
92
|
+
const srcW = img.get_width();
|
|
93
|
+
const srcH = img.get_height();
|
|
94
|
+
let { width, height } = op.options;
|
|
95
|
+
// Preserve aspect ratio if only one dimension given
|
|
96
|
+
if (width !== undefined && height === undefined) {
|
|
97
|
+
height = Math.round((srcH / srcW) * width);
|
|
98
|
+
}
|
|
99
|
+
else if (height !== undefined && width === undefined) {
|
|
100
|
+
width = Math.round((srcW / srcH) * height);
|
|
101
|
+
}
|
|
102
|
+
if (width === undefined || height === undefined)
|
|
103
|
+
break;
|
|
104
|
+
const resized = photon.resize(img, width, height, photon.SamplingFilter.Lanczos3);
|
|
105
|
+
img.free();
|
|
106
|
+
img = resized;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case 'crop': {
|
|
110
|
+
const { left, top, width, height } = op.options;
|
|
111
|
+
const cropped = photon.crop(img, left, top, left + width, top + height);
|
|
112
|
+
img.free();
|
|
113
|
+
img = cropped;
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case 'rotate': {
|
|
117
|
+
const { angle } = op.options;
|
|
118
|
+
const norm = ((angle % 360) + 360) % 360;
|
|
119
|
+
if (norm === 0)
|
|
120
|
+
break;
|
|
121
|
+
if (norm === 90 || norm === 180 || norm === 270) {
|
|
122
|
+
photon.rotate(img, norm);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
warnUnsupported(`rotate(${angle}) — only 90°/180°/270° supported in WASM engine`);
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
case 'flip':
|
|
130
|
+
photon.flipv(img);
|
|
131
|
+
break;
|
|
132
|
+
case 'flop':
|
|
133
|
+
photon.fliph(img);
|
|
134
|
+
break;
|
|
135
|
+
case 'grayscale':
|
|
136
|
+
photon.grayscale_human_corrected(img);
|
|
137
|
+
break;
|
|
138
|
+
case 'negate':
|
|
139
|
+
photon.invert(img);
|
|
140
|
+
break;
|
|
141
|
+
case 'brightness':
|
|
142
|
+
if (op.options.brightness !== undefined) {
|
|
143
|
+
photon.adjust_brightness(img, Math.round((op.options.brightness - 1) * 128));
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
case 'contrast':
|
|
147
|
+
photon.adjust_contrast(img, (op.options.value - 1) * 128);
|
|
148
|
+
break;
|
|
149
|
+
case 'tint':
|
|
150
|
+
photon.tint(img, op.options.r, op.options.g, op.options.b);
|
|
151
|
+
break;
|
|
152
|
+
case 'blur':
|
|
153
|
+
case 'sharpen':
|
|
154
|
+
case 'median':
|
|
155
|
+
case 'saturation':
|
|
156
|
+
case 'composite':
|
|
157
|
+
case 'stripMeta':
|
|
158
|
+
case 'removeBackground':
|
|
159
|
+
case 'smartCrop':
|
|
160
|
+
case 'upscale':
|
|
161
|
+
warnUnsupported(op.op);
|
|
162
|
+
break;
|
|
163
|
+
case 'format':
|
|
164
|
+
case 'quality':
|
|
165
|
+
// Collected above in outputFormat()
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const { data, format: outFmt } = encodePhoton(photon, img, format, quality);
|
|
170
|
+
return {
|
|
171
|
+
data,
|
|
172
|
+
format: outFmt,
|
|
173
|
+
width: img.get_width(),
|
|
174
|
+
height: img.get_height(),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
img.free();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
export async function metadataWasm(input) {
|
|
182
|
+
const photon = await importPhoton();
|
|
183
|
+
const bytes = await toUint8Array(input);
|
|
184
|
+
const img = photon.PhotonImage.new_from_byteslice(bytes);
|
|
185
|
+
try {
|
|
186
|
+
return {
|
|
187
|
+
width: img.get_width(),
|
|
188
|
+
height: img.get_height(),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
img.free();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
export const wasmEngine = {
|
|
196
|
+
process: processWasm,
|
|
197
|
+
metadata: metadataWasm,
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=wasm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm.js","sourceRoot":"","sources":["../../src/engines/wasm.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Pipeline } from './pipeline.js';
|
|
2
|
+
import type { ImageInput } from './types.js';
|
|
3
|
+
export declare function img(input: ImageInput): Pipeline;
|
|
4
|
+
export { batch, Batch } from './batch.js';
|
|
5
|
+
export { Pipeline } from './pipeline.js';
|
|
6
|
+
export { ImgCraftError } from './types.js';
|
|
7
|
+
export type { ImageInput, FitMode, OutputFormat, BlendMode, Gravity, RgbaColor, ResizeOptions, CropOptions, RotateOptions, FormatOptions, BlurOptions, SharpenOptions, MedianOptions, TintOptions, ModulateOptions, ContrastOptions, CompositeOptions, MetadataResult, EngineResult, PipelineState, PipelineOp, SmartCropOptions, UpscaleOptions, } from './types.js';
|
|
8
|
+
export type { BatchResult, BatchOptions } from './batch.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,wBAAgB,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAE/C;AAED,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC1C,YAAY,EACV,UAAU,EACV,OAAO,EACP,YAAY,EACZ,SAAS,EACT,OAAO,EACP,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,cAAc,GACf,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Pipeline } from './pipeline.js';
|
|
2
|
+
export function img(input) {
|
|
3
|
+
return new Pipeline(input);
|
|
4
|
+
}
|
|
5
|
+
export { batch, Batch } from './batch.js';
|
|
6
|
+
export { Pipeline } from './pipeline.js';
|
|
7
|
+
export { ImgCraftError } from './types.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAGxC,MAAM,UAAU,GAAG,CAAC,KAAiB;IACnC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC5B,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ImageInput, PipelineOp, MetadataResult, ResizeOptions, CropOptions, RotateOptions, FormatOptions, OutputFormat, SharpenOptions, TintOptions, CompositeOptions, ContrastOptions, SmartCropOptions, UpscaleOptions } from './types.js';
|
|
2
|
+
export declare class Pipeline {
|
|
3
|
+
private readonly _state;
|
|
4
|
+
constructor(input: ImageInput, ops?: PipelineOp[]);
|
|
5
|
+
private push;
|
|
6
|
+
resize(width?: number, height?: number, options?: Omit<ResizeOptions, 'width' | 'height'>): this;
|
|
7
|
+
crop(options: CropOptions): this;
|
|
8
|
+
rotate(angle: number, options?: Omit<RotateOptions, 'angle'>): this;
|
|
9
|
+
flip(): this;
|
|
10
|
+
flop(): this;
|
|
11
|
+
format(type: OutputFormat, options?: Omit<FormatOptions, 'format'>): this;
|
|
12
|
+
jpeg(options?: {
|
|
13
|
+
quality?: number;
|
|
14
|
+
}): this;
|
|
15
|
+
png(options?: {
|
|
16
|
+
quality?: number;
|
|
17
|
+
}): this;
|
|
18
|
+
webp(options?: {
|
|
19
|
+
quality?: number;
|
|
20
|
+
}): this;
|
|
21
|
+
avif(options?: {
|
|
22
|
+
quality?: number;
|
|
23
|
+
}): this;
|
|
24
|
+
quality(value: number): this;
|
|
25
|
+
blur(sigma?: number): this;
|
|
26
|
+
sharpen(options?: SharpenOptions): this;
|
|
27
|
+
median(size?: number): this;
|
|
28
|
+
grayscale(): this;
|
|
29
|
+
tint(options: TintOptions): this;
|
|
30
|
+
negate(): this;
|
|
31
|
+
brightness(value: number): this;
|
|
32
|
+
saturation(value: number): this;
|
|
33
|
+
contrast(options: ContrastOptions): this;
|
|
34
|
+
composite(options: CompositeOptions): this;
|
|
35
|
+
stripMeta(): this;
|
|
36
|
+
removeBackground(): this;
|
|
37
|
+
smartCrop(options?: SmartCropOptions): this;
|
|
38
|
+
upscale(options: UpscaleOptions): this;
|
|
39
|
+
meta(): Promise<MetadataResult>;
|
|
40
|
+
toBuffer(): Promise<Buffer | Uint8Array>;
|
|
41
|
+
toFile(path: string): Promise<void>;
|
|
42
|
+
toStream(): Promise<ReadableStream<Uint8Array>>;
|
|
43
|
+
toDataURL(): Promise<string>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,UAAU,EAEV,UAAU,EACV,cAAc,EACd,aAAa,EACb,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EAEZ,cAAc,EAEd,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACf,MAAM,YAAY,CAAA;AAEnB,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,KAAK,EAAE,UAAU,EAAE,GAAG,GAAE,UAAU,EAAO;IAIrD,OAAO,CAAC,IAAI;IAKZ,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG,IAAI;IAIhG,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIhC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,IAAI;IAInE,IAAI,IAAI,IAAI;IAIZ,IAAI,IAAI,IAAI;IAIZ,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,GAAG,IAAI;IAIzE,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAI1C,GAAG,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIzC,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAI1C,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAI1C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAU5B,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAK1B,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI;IAIvC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAK3B,SAAS,IAAI,IAAI;IAIjB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIhC,MAAM,IAAI,IAAI;IAId,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI/B,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI/B,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAIxC,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAI1C,SAAS,IAAI,IAAI;IAIjB,gBAAgB,IAAI,IAAI;IAIxB,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAI3C,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIhC,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC;IAK/B,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,CAAC;IAMxC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnC,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAW/C,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;CAQnC"}
|
package/dist/pipeline.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { getEngine } from './adapters/runtime.js';
|
|
2
|
+
// btoa is available in Node 16+ and all modern browsers
|
|
3
|
+
function uint8ToBase64(bytes) {
|
|
4
|
+
let binary = '';
|
|
5
|
+
const chunkSize = 8192;
|
|
6
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
7
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
|
|
8
|
+
}
|
|
9
|
+
return btoa(binary);
|
|
10
|
+
}
|
|
11
|
+
import { ImgCraftError } from './types.js';
|
|
12
|
+
export class Pipeline {
|
|
13
|
+
_state;
|
|
14
|
+
constructor(input, ops = []) {
|
|
15
|
+
this._state = { input, ops: [...ops] };
|
|
16
|
+
}
|
|
17
|
+
push(op) {
|
|
18
|
+
this._state.ops.push(op);
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
resize(width, height, options) {
|
|
22
|
+
return this.push({ op: 'resize', options: { width, height, ...options } });
|
|
23
|
+
}
|
|
24
|
+
crop(options) {
|
|
25
|
+
return this.push({ op: 'crop', options });
|
|
26
|
+
}
|
|
27
|
+
rotate(angle, options) {
|
|
28
|
+
return this.push({ op: 'rotate', options: { angle, ...options } });
|
|
29
|
+
}
|
|
30
|
+
flip() {
|
|
31
|
+
return this.push({ op: 'flip' });
|
|
32
|
+
}
|
|
33
|
+
flop() {
|
|
34
|
+
return this.push({ op: 'flop' });
|
|
35
|
+
}
|
|
36
|
+
format(type, options) {
|
|
37
|
+
return this.push({ op: 'format', options: { format: type, ...options } });
|
|
38
|
+
}
|
|
39
|
+
jpeg(options) {
|
|
40
|
+
return this.format('jpeg', options);
|
|
41
|
+
}
|
|
42
|
+
png(options) {
|
|
43
|
+
return this.format('png', options);
|
|
44
|
+
}
|
|
45
|
+
webp(options) {
|
|
46
|
+
return this.format('webp', options);
|
|
47
|
+
}
|
|
48
|
+
avif(options) {
|
|
49
|
+
return this.format('avif', options);
|
|
50
|
+
}
|
|
51
|
+
quality(value) {
|
|
52
|
+
if (value < 1 || value > 100) {
|
|
53
|
+
throw new ImgCraftError({
|
|
54
|
+
code: 'INVALID_QUALITY',
|
|
55
|
+
message: `Quality must be between 1 and 100. Got: ${value}`,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return this.push({ op: 'quality', value });
|
|
59
|
+
}
|
|
60
|
+
blur(sigma) {
|
|
61
|
+
const options = sigma !== undefined ? { sigma } : {};
|
|
62
|
+
return this.push({ op: 'blur', options });
|
|
63
|
+
}
|
|
64
|
+
sharpen(options) {
|
|
65
|
+
return this.push({ op: 'sharpen', options: options ?? {} });
|
|
66
|
+
}
|
|
67
|
+
median(size) {
|
|
68
|
+
const options = size !== undefined ? { size } : {};
|
|
69
|
+
return this.push({ op: 'median', options });
|
|
70
|
+
}
|
|
71
|
+
grayscale() {
|
|
72
|
+
return this.push({ op: 'grayscale' });
|
|
73
|
+
}
|
|
74
|
+
tint(options) {
|
|
75
|
+
return this.push({ op: 'tint', options });
|
|
76
|
+
}
|
|
77
|
+
negate() {
|
|
78
|
+
return this.push({ op: 'negate' });
|
|
79
|
+
}
|
|
80
|
+
brightness(value) {
|
|
81
|
+
return this.push({ op: 'brightness', options: { brightness: value } });
|
|
82
|
+
}
|
|
83
|
+
saturation(value) {
|
|
84
|
+
return this.push({ op: 'saturation', options: { saturation: value } });
|
|
85
|
+
}
|
|
86
|
+
contrast(options) {
|
|
87
|
+
return this.push({ op: 'contrast', options });
|
|
88
|
+
}
|
|
89
|
+
composite(options) {
|
|
90
|
+
return this.push({ op: 'composite', options });
|
|
91
|
+
}
|
|
92
|
+
stripMeta() {
|
|
93
|
+
return this.push({ op: 'stripMeta' });
|
|
94
|
+
}
|
|
95
|
+
removeBackground() {
|
|
96
|
+
return this.push({ op: 'removeBackground' });
|
|
97
|
+
}
|
|
98
|
+
smartCrop(options) {
|
|
99
|
+
return this.push({ op: 'smartCrop', options: options ?? {} });
|
|
100
|
+
}
|
|
101
|
+
upscale(options) {
|
|
102
|
+
return this.push({ op: 'upscale', options });
|
|
103
|
+
}
|
|
104
|
+
async meta() {
|
|
105
|
+
const engine = await getEngine();
|
|
106
|
+
return engine.metadata(this._state.input);
|
|
107
|
+
}
|
|
108
|
+
async toBuffer() {
|
|
109
|
+
const engine = await getEngine();
|
|
110
|
+
const result = await engine.process(this._state);
|
|
111
|
+
return result.data;
|
|
112
|
+
}
|
|
113
|
+
async toFile(path) {
|
|
114
|
+
const { writeFile } = await import('node:fs/promises');
|
|
115
|
+
const data = await this.toBuffer();
|
|
116
|
+
await writeFile(path, data);
|
|
117
|
+
}
|
|
118
|
+
async toStream() {
|
|
119
|
+
const data = await this.toBuffer();
|
|
120
|
+
const chunk = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
121
|
+
return new ReadableStream({
|
|
122
|
+
start(controller) {
|
|
123
|
+
controller.enqueue(chunk);
|
|
124
|
+
controller.close();
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async toDataURL() {
|
|
129
|
+
const engine = await getEngine();
|
|
130
|
+
const result = await engine.process(this._state);
|
|
131
|
+
const base64 = uint8ToBase64(result.data instanceof Uint8Array ? result.data : new Uint8Array(result.data));
|
|
132
|
+
return `data:image/${result.format};base64,${base64}`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SmartCropOptions, UpscaleOptions } from '../types.js';
|
|
2
|
+
export declare function _resetAICaches(): void;
|
|
3
|
+
export declare function applyRemoveBackground(input: Buffer | Uint8Array): Promise<Buffer>;
|
|
4
|
+
export declare function applySmartCrop(input: Buffer | Uint8Array, options: SmartCropOptions): Promise<Buffer>;
|
|
5
|
+
export declare function applyUpscale(input: Buffer | Uint8Array, options: UpscaleOptions): Promise<Buffer>;
|
|
6
|
+
//# sourceMappingURL=ai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/transforms/ai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AA8BnE,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AA8DD,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBvF;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,GAAG,UAAU,EAC1B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CAqDjB;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,GAAG,UAAU,EAC1B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { ImgCraftError } from '../types.js';
|
|
2
|
+
// --- Module-level caches — populated on first call, never at module init ---
|
|
3
|
+
let bgRemovalFn = null;
|
|
4
|
+
let cocoSsdModel = null;
|
|
5
|
+
const upscalerCache = new Map();
|
|
6
|
+
// Clears all lazy-load caches — used in tests to restore fresh state
|
|
7
|
+
export function _resetAICaches() {
|
|
8
|
+
bgRemovalFn = null;
|
|
9
|
+
cocoSsdModel = null;
|
|
10
|
+
upscalerCache.clear();
|
|
11
|
+
}
|
|
12
|
+
// --- Loader helpers ---
|
|
13
|
+
async function loadBgRemoval() {
|
|
14
|
+
if (bgRemovalFn !== null)
|
|
15
|
+
return bgRemovalFn;
|
|
16
|
+
try {
|
|
17
|
+
const mod = await import('@imgly/background-removal');
|
|
18
|
+
bgRemovalFn = mod.removeBackground;
|
|
19
|
+
return bgRemovalFn;
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
throw new ImgCraftError({
|
|
23
|
+
code: 'BG_REMOVAL_UNAVAILABLE',
|
|
24
|
+
message: `@imgly/background-removal failed to load: ${err instanceof Error ? err.message : String(err)}`,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function loadCocoSsd() {
|
|
29
|
+
if (cocoSsdModel !== null)
|
|
30
|
+
return cocoSsdModel;
|
|
31
|
+
try {
|
|
32
|
+
// tfjs-node must be loaded first to register the Node backend
|
|
33
|
+
await import('@tensorflow/tfjs-node');
|
|
34
|
+
const cocoSsd = await import('@tensorflow-models/coco-ssd');
|
|
35
|
+
cocoSsdModel = (await cocoSsd.load());
|
|
36
|
+
return cocoSsdModel;
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
throw new ImgCraftError({
|
|
40
|
+
code: 'SMART_CROP_UNAVAILABLE',
|
|
41
|
+
message: `@tensorflow-models/coco-ssd failed to load: ${err instanceof Error ? err.message : String(err)}`,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function loadUpscaler(factor) {
|
|
46
|
+
const cached = upscalerCache.get(factor);
|
|
47
|
+
if (cached !== undefined)
|
|
48
|
+
return cached;
|
|
49
|
+
try {
|
|
50
|
+
await import('@tensorflow/tfjs-node');
|
|
51
|
+
const { default: Upscaler } = await import('upscalerjs');
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
53
|
+
const model = factor === 2
|
|
54
|
+
? (await import('@upscalerjs/esrgan-slim/2x')).default
|
|
55
|
+
: (await import('@upscalerjs/esrgan-slim/4x')).default;
|
|
56
|
+
const instance = new Upscaler({ model });
|
|
57
|
+
upscalerCache.set(factor, instance);
|
|
58
|
+
return instance;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
throw new ImgCraftError({
|
|
62
|
+
code: 'UPSCALE_UNAVAILABLE',
|
|
63
|
+
message: `upscalerjs failed to load: ${err instanceof Error ? err.message : String(err)}`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// --- Public transform functions ---
|
|
68
|
+
export async function applyRemoveBackground(input) {
|
|
69
|
+
const removeBg = await loadBgRemoval();
|
|
70
|
+
// Copy into a fresh ArrayBuffer so Blob constructor gets Uint8Array<ArrayBuffer> (not ArrayBufferLike)
|
|
71
|
+
const bytes = Uint8Array.from(input);
|
|
72
|
+
const blob = new Blob([bytes], { type: 'image/png' });
|
|
73
|
+
try {
|
|
74
|
+
const result = await removeBg(blob);
|
|
75
|
+
const arrayBuffer = await result.arrayBuffer();
|
|
76
|
+
return Buffer.from(arrayBuffer);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
throw new ImgCraftError({
|
|
80
|
+
code: 'BG_REMOVAL_FAILED',
|
|
81
|
+
message: `Background removal failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function applySmartCrop(input, options) {
|
|
86
|
+
const model = await loadCocoSsd();
|
|
87
|
+
const tf = (await import('@tensorflow/tfjs-node'));
|
|
88
|
+
const buffer = input instanceof Buffer ? input : Buffer.from(input);
|
|
89
|
+
// Get image dimensions via sharp (already a dep in node engine context)
|
|
90
|
+
const sharpMod = await import('sharp');
|
|
91
|
+
const sharp = sharpMod.default;
|
|
92
|
+
const meta = await sharp(buffer).metadata();
|
|
93
|
+
const imgWidth = meta.width ?? 0;
|
|
94
|
+
const imgHeight = meta.height ?? 0;
|
|
95
|
+
const tensor = tf.node.decodeImage(buffer, 3);
|
|
96
|
+
let predictions;
|
|
97
|
+
try {
|
|
98
|
+
predictions = await model.detect(tensor);
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
if ('dispose' in tensor && typeof tensor.dispose === 'function') {
|
|
102
|
+
;
|
|
103
|
+
tensor.dispose();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (predictions.length === 0) {
|
|
107
|
+
return buffer;
|
|
108
|
+
}
|
|
109
|
+
const filtered = options.subject !== undefined
|
|
110
|
+
? predictions.filter((p) => p.class === options.subject)
|
|
111
|
+
: predictions;
|
|
112
|
+
const target = (filtered.length > 0 ? filtered : predictions).sort((a, b) => b.score - a.score)[0];
|
|
113
|
+
if (target === undefined)
|
|
114
|
+
return buffer;
|
|
115
|
+
const padding = options.padding ?? 20;
|
|
116
|
+
const [x, y, w, h] = target.bbox;
|
|
117
|
+
const left = Math.max(0, Math.round(x - padding));
|
|
118
|
+
const top = Math.max(0, Math.round(y - padding));
|
|
119
|
+
const right = Math.min(imgWidth, Math.round(x + w + padding));
|
|
120
|
+
const bottom = Math.min(imgHeight, Math.round(y + h + padding));
|
|
121
|
+
return sharp(buffer)
|
|
122
|
+
.extract({ left, top, width: right - left, height: bottom - top })
|
|
123
|
+
.png()
|
|
124
|
+
.toBuffer();
|
|
125
|
+
}
|
|
126
|
+
export async function applyUpscale(input, options) {
|
|
127
|
+
const upscaler = await loadUpscaler(options.factor);
|
|
128
|
+
const buffer = input instanceof Buffer ? input : Buffer.from(input);
|
|
129
|
+
const base64Input = `data:image/png;base64,${buffer.toString('base64')}`;
|
|
130
|
+
let base64Output;
|
|
131
|
+
try {
|
|
132
|
+
base64Output = await upscaler.upscale(base64Input);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
throw new ImgCraftError({
|
|
136
|
+
code: 'UPSCALE_FAILED',
|
|
137
|
+
message: `Upscaling failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
const base64Data = base64Output.slice(base64Output.indexOf(',') + 1);
|
|
141
|
+
return Buffer.from(base64Data, 'base64');
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=ai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/transforms/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAwB3C,8EAA8E;AAE9E,IAAI,WAAW,GAAuB,IAAI,CAAA;AAC1C,IAAI,YAAY,GAAwB,IAAI,CAAA;AAC5C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAuB,CAAA;AAEpD,qEAAqE;AACrE,MAAM,UAAU,cAAc;IAC5B,WAAW,GAAG,IAAI,CAAA;IAClB,YAAY,GAAG,IAAI,CAAA;IACnB,aAAa,CAAC,KAAK,EAAE,CAAA;AACvB,CAAC;AAED,yBAAyB;AAEzB,KAAK,UAAU,aAAa;IAC1B,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,WAAW,CAAA;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAA;QACrD,WAAW,GAAG,GAAG,CAAC,gBAA+B,CAAA;QACjD,OAAO,WAAW,CAAA;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CAAC;YACtB,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,6CAA6C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SACzG,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW;IACxB,IAAI,YAAY,KAAK,IAAI;QAAE,OAAO,YAAY,CAAA;IAC9C,IAAI,CAAC;QACH,8DAA8D;QAC9D,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAA;QACrC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAA;QAC3D,YAAY,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAiB,CAAA;QACrD,OAAO,YAAY,CAAA;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CAAC;YACtB,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,+CAA+C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAC3G,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,MAAa;IACvC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACxC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IAEvC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAA;QACrC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAI,MAAM,MAAM,CAAC,YAAY,CAEvD,CAAA;QACD,mEAAmE;QACnE,MAAM,KAAK,GACT,MAAM,KAAK,CAAC;YACV,CAAC,CAAE,CAAC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAA0B,CAAC,OAAO;YAChF,CAAC,CAAE,CAAC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAA0B,CAAC,OAAO,CAAA;QAEpF,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QACxC,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QACnC,OAAO,QAAQ,CAAA;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CAAC;YACtB,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAC1F,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,qCAAqC;AAErC,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAA0B;IACpE,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAA;IAEtC,uGAAuG;IACvG,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IAErD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAA;QACnC,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAA;QAC9C,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CAAC;YACtB,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAC1F,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAA0B,EAC1B,OAAyB;IAEzB,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAA;IACjC,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAEhD,CAAA;IAED,MAAM,MAAM,GAAG,KAAK,YAAY,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAEnE,wEAAwE;IACxE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAA;IAC9B,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAA;IAChC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAA;IAElC,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAE7C,IAAI,WAA+B,CAAA;IACnC,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC1C,CAAC;YAAS,CAAC;QACT,IAAI,SAAS,IAAI,MAAM,IAAI,OAAQ,MAAkC,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YAC7F,CAAC;YAAC,MAAkC,CAAC,OAAO,EAAE,CAAA;QAChD,CAAC;IACH,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAA;IACf,CAAC;IAED,MAAM,QAAQ,GACZ,OAAO,CAAC,OAAO,KAAK,SAAS;QAC3B,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC;QACxD,CAAC,CAAC,WAAW,CAAA;IAEjB,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAChE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAC5B,CAAC,CAAC,CAAC,CAAA;IAEJ,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IAEvC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAA;IACrC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAA;IAEhC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;IAE/D,OAAO,KAAK,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,CAAC;SACjE,GAAG,EAAE;SACL,QAAQ,EAAE,CAAA;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAA0B,EAC1B,OAAuB;IAEvB,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAEnD,MAAM,MAAM,GAAG,KAAK,YAAY,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACnE,MAAM,WAAW,GAAG,yBAAyB,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAA;IAExE,IAAI,YAAoB,CAAA;IACxB,IAAI,CAAC;QACH,YAAY,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CAAC;YACtB,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,qBAAqB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SACjF,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IACpE,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;AAC1C,CAAC"}
|