@areb0s/ocr-browser 1.0.0 → 1.0.1

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.
@@ -19,46 +19,68 @@ export declare class ImageRaw extends ImageRawBase {
19
19
  * Check if the input is an HTMLVideoElement
20
20
  */
21
21
  static isHTMLVideoElement(input: unknown): input is HTMLVideoElement;
22
+ /**
23
+ * Check if the input is an OffscreenCanvas
24
+ */
25
+ static isOffscreenCanvas(input: unknown): input is OffscreenCanvas;
22
26
  /**
23
27
  * Check if the input is ImageRawData
24
28
  */
25
29
  static isImageRawData(input: unknown): input is ImageRawData;
26
30
  /**
27
31
  * Universal factory method that accepts all browser image input types
28
- * @param input - URL string, ImageRawData, ImageBitmap, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement
32
+ * Works in both main thread and Web Worker
33
+ * @param input - URL string, ImageRawData, ImageBitmap, HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, or HTMLVideoElement
29
34
  * @returns Promise<ImageRaw>
30
35
  */
31
- static from(input: BrowserImageInput): Promise<ImageRaw>;
36
+ static from(input: BrowserImageInput | OffscreenCanvas): Promise<ImageRaw>;
32
37
  /**
33
- * Create ImageRaw from a URL (existing method)
38
+ * Create ImageRaw from a URL
39
+ * Works in both main thread and Web Worker
40
+ * Uses fetch + createImageBitmap for best performance
34
41
  */
35
42
  static open(url: string): Promise<ImageRaw>;
36
43
  /**
37
44
  * Create ImageRaw from an ImageBitmap
45
+ * Works in both main thread and Web Worker
38
46
  * Note: This method will close the ImageBitmap after conversion to free memory
39
47
  * @param bitmap - ImageBitmap to convert
40
48
  * @returns Promise<ImageRaw>
41
49
  */
42
50
  static fromImageBitmap(bitmap: ImageBitmap): Promise<ImageRaw>;
51
+ /**
52
+ * Create ImageRaw from an OffscreenCanvas
53
+ * Works in both main thread and Web Worker
54
+ * @param canvas - OffscreenCanvas to convert
55
+ * @returns Promise<ImageRaw>
56
+ */
57
+ static fromOffscreenCanvas(canvas: OffscreenCanvas): Promise<ImageRaw>;
43
58
  /**
44
59
  * Create ImageRaw from an HTMLImageElement
60
+ * Main thread only
45
61
  * @param img - HTMLImageElement to convert (must be loaded/decoded)
46
62
  * @returns Promise<ImageRaw>
47
63
  */
48
64
  static fromHTMLImageElement(img: HTMLImageElement): Promise<ImageRaw>;
49
65
  /**
50
66
  * Create ImageRaw from an HTMLCanvasElement
67
+ * Main thread only
51
68
  * @param canvas - HTMLCanvasElement to convert
52
69
  * @returns Promise<ImageRaw>
53
70
  */
54
71
  static fromHTMLCanvasElement(canvas: HTMLCanvasElement): Promise<ImageRaw>;
55
72
  /**
56
73
  * Create ImageRaw from an HTMLVideoElement (captures current frame)
74
+ * Main thread only
57
75
  * @param video - HTMLVideoElement to capture from
58
76
  * @returns Promise<ImageRaw>
59
77
  */
60
78
  static fromHTMLVideoElement(video: HTMLVideoElement): Promise<ImageRaw>;
61
79
  constructor({ data, width, height }: ImageRawData);
80
+ /**
81
+ * Debug method - appends canvas to document body
82
+ * Main thread only, no-op in Worker
83
+ */
62
84
  write(path: string): Promise<void>;
63
85
  resize({ width, height }: SizeOption): Promise<this>;
64
86
  drawBox(lineImages: LineImage[]): Promise<this>;
package/build/ImageRaw.js CHANGED
@@ -1,5 +1,78 @@
1
1
  import { ImageRawBase } from '@areb0s/ocr-common';
2
2
  import invariant from 'tiny-invariant';
3
+ // Cache environment checks (evaluated once at module load)
4
+ const IS_WORKER = typeof window === 'undefined' && typeof self !== 'undefined' && typeof document === 'undefined';
5
+ const HAS_OFFSCREEN_CANVAS = typeof OffscreenCanvas !== 'undefined';
6
+ const HAS_DOCUMENT = typeof document !== 'undefined';
7
+ const HAS_IMAGE = typeof Image !== 'undefined';
8
+ const HAS_CREATE_IMAGE_BITMAP = typeof createImageBitmap !== 'undefined';
9
+ // Cache canvas contexts for reuse (WeakMap allows GC when canvas is gone)
10
+ const contextCache = new WeakMap();
11
+ /**
12
+ * Create a canvas that works in both main thread and Web Worker
13
+ * Prefers OffscreenCanvas for better performance
14
+ */
15
+ function createCanvas(width, height) {
16
+ if (HAS_OFFSCREEN_CANVAS) {
17
+ return new OffscreenCanvas(width, height);
18
+ }
19
+ if (HAS_DOCUMENT) {
20
+ const canvas = document.createElement('canvas');
21
+ canvas.width = width;
22
+ canvas.height = height;
23
+ return canvas;
24
+ }
25
+ throw new Error('No canvas support available. Neither OffscreenCanvas nor document is available.');
26
+ }
27
+ /**
28
+ * Get 2D context from any canvas type (cached for performance)
29
+ */
30
+ function getContext2D(canvas, options) {
31
+ // Check cache first
32
+ const cached = contextCache.get(canvas);
33
+ if (cached)
34
+ return cached;
35
+ // Create new context with performance hints
36
+ const ctx = canvas.getContext('2d', {
37
+ willReadFrequently: true, // Optimize for getImageData() calls
38
+ ...options
39
+ });
40
+ if (ctx) {
41
+ contextCache.set(canvas, ctx);
42
+ }
43
+ return ctx;
44
+ }
45
+ /**
46
+ * Get ImageData from any canvas type
47
+ */
48
+ function getImageData(canvas) {
49
+ const ctx = getContext2D(canvas);
50
+ if (!ctx) {
51
+ throw new Error('Failed to get 2D context');
52
+ }
53
+ return ctx.getImageData(0, 0, canvas.width, canvas.height);
54
+ }
55
+ /**
56
+ * Create ImageBitmap with optimized options for OCR
57
+ * - premultiplyAlpha: 'none' - avoid alpha premultiplication overhead
58
+ * - colorSpaceConversion: 'none' - avoid color space conversion overhead
59
+ */
60
+ async function createOptimizedImageBitmap(source) {
61
+ if (!HAS_CREATE_IMAGE_BITMAP) {
62
+ throw new Error('createImageBitmap is not supported');
63
+ }
64
+ try {
65
+ // Try with optimization options (may not be supported in all browsers)
66
+ return await createImageBitmap(source, {
67
+ premultiplyAlpha: 'none',
68
+ colorSpaceConversion: 'none',
69
+ });
70
+ }
71
+ catch {
72
+ // Fallback without options
73
+ return await createImageBitmap(source);
74
+ }
75
+ }
3
76
  export class ImageRaw extends ImageRawBase {
4
77
  data;
5
78
  #imageData;
@@ -31,6 +104,12 @@ export class ImageRaw extends ImageRawBase {
31
104
  static isHTMLVideoElement(input) {
32
105
  return typeof HTMLVideoElement !== 'undefined' && input instanceof HTMLVideoElement;
33
106
  }
107
+ /**
108
+ * Check if the input is an OffscreenCanvas
109
+ */
110
+ static isOffscreenCanvas(input) {
111
+ return HAS_OFFSCREEN_CANVAS && input instanceof OffscreenCanvas;
112
+ }
34
113
  /**
35
114
  * Check if the input is ImageRawData
36
115
  */
@@ -47,7 +126,8 @@ export class ImageRaw extends ImageRawBase {
47
126
  // ===========================================
48
127
  /**
49
128
  * Universal factory method that accepts all browser image input types
50
- * @param input - URL string, ImageRawData, ImageBitmap, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement
129
+ * Works in both main thread and Web Worker
130
+ * @param input - URL string, ImageRawData, ImageBitmap, HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, or HTMLVideoElement
51
131
  * @returns Promise<ImageRaw>
52
132
  */
53
133
  static async from(input) {
@@ -55,44 +135,71 @@ export class ImageRaw extends ImageRawBase {
55
135
  if (typeof input === 'string') {
56
136
  return ImageRaw.open(input);
57
137
  }
58
- // ImageBitmap
138
+ // ImageBitmap - Works in both main thread and Worker (most efficient)
59
139
  if (ImageRaw.isImageBitmap(input)) {
60
140
  return ImageRaw.fromImageBitmap(input);
61
141
  }
62
- // HTMLImageElement
142
+ // OffscreenCanvas - Works in both main thread and Worker
143
+ if (ImageRaw.isOffscreenCanvas(input)) {
144
+ return ImageRaw.fromOffscreenCanvas(input);
145
+ }
146
+ // HTMLImageElement - Main thread only
63
147
  if (ImageRaw.isHTMLImageElement(input)) {
148
+ if (IS_WORKER) {
149
+ throw new Error('HTMLImageElement is not available in Web Worker. Use ImageBitmap instead.');
150
+ }
64
151
  return ImageRaw.fromHTMLImageElement(input);
65
152
  }
66
- // HTMLCanvasElement
153
+ // HTMLCanvasElement - Main thread only
67
154
  if (ImageRaw.isHTMLCanvasElement(input)) {
155
+ if (IS_WORKER) {
156
+ throw new Error('HTMLCanvasElement is not available in Web Worker. Use OffscreenCanvas instead.');
157
+ }
68
158
  return ImageRaw.fromHTMLCanvasElement(input);
69
159
  }
70
- // HTMLVideoElement
160
+ // HTMLVideoElement - Main thread only
71
161
  if (ImageRaw.isHTMLVideoElement(input)) {
162
+ if (IS_WORKER) {
163
+ throw new Error('HTMLVideoElement is not available in Web Worker. Use ImageBitmap instead.');
164
+ }
72
165
  return ImageRaw.fromHTMLVideoElement(input);
73
166
  }
74
- // ImageRawData (fallback)
167
+ // ImageRawData (fallback) - Works everywhere
75
168
  if (ImageRaw.isImageRawData(input)) {
76
169
  return new ImageRaw(input);
77
170
  }
78
171
  throw new Error('Unsupported image input type');
79
172
  }
80
173
  /**
81
- * Create ImageRaw from a URL (existing method)
174
+ * Create ImageRaw from a URL
175
+ * Works in both main thread and Web Worker
176
+ * Uses fetch + createImageBitmap for best performance
82
177
  */
83
178
  static async open(url) {
84
- const image = await imageFromUrl(url);
85
- const canvas = document.createElement('canvas');
86
- canvasDrawImage(canvas, image, image.naturalWidth, image.naturalHeight);
87
- const imageData = canvasGetImageData(canvas);
88
- return new ImageRaw({
89
- data: imageData.data,
90
- width: imageData.width,
91
- height: imageData.height,
92
- });
179
+ // Prefer fetch + createImageBitmap (works everywhere, better performance)
180
+ if (HAS_CREATE_IMAGE_BITMAP) {
181
+ const response = await fetch(url);
182
+ const blob = await response.blob();
183
+ const bitmap = await createOptimizedImageBitmap(blob);
184
+ return ImageRaw.fromImageBitmap(bitmap);
185
+ }
186
+ // Fallback: use Image element (main thread only)
187
+ if (!IS_WORKER && HAS_IMAGE) {
188
+ const image = await imageFromUrl(url);
189
+ const canvas = createCanvas(image.naturalWidth, image.naturalHeight);
190
+ canvasDrawImage(canvas, image, image.naturalWidth, image.naturalHeight);
191
+ const imageData = getImageData(canvas);
192
+ return new ImageRaw({
193
+ data: imageData.data,
194
+ width: imageData.width,
195
+ height: imageData.height,
196
+ });
197
+ }
198
+ throw new Error('Cannot load image from URL: no supported method available');
93
199
  }
94
200
  /**
95
201
  * Create ImageRaw from an ImageBitmap
202
+ * Works in both main thread and Web Worker
96
203
  * Note: This method will close the ImageBitmap after conversion to free memory
97
204
  * @param bitmap - ImageBitmap to convert
98
205
  * @returns Promise<ImageRaw>
@@ -102,18 +209,14 @@ export class ImageRaw extends ImageRawBase {
102
209
  if (bitmap.width === 0 || bitmap.height === 0) {
103
210
  throw new Error('Invalid ImageBitmap: dimensions are zero (bitmap may be closed or neutered)');
104
211
  }
105
- const canvas = document.createElement('canvas');
106
- canvas.width = bitmap.width;
107
- canvas.height = bitmap.height;
108
- const ctx = canvas.getContext('2d', { willReadFrequently: true });
212
+ const canvas = createCanvas(bitmap.width, bitmap.height);
213
+ const ctx = getContext2D(canvas);
109
214
  if (!ctx) {
110
215
  // Cleanup before throwing
111
216
  try {
112
217
  bitmap.close();
113
218
  }
114
- catch {
115
- // Ignore if already closed
116
- }
219
+ catch { /* ignore */ }
117
220
  throw new Error('Failed to create canvas 2D context');
118
221
  }
119
222
  try {
@@ -126,28 +229,50 @@ export class ImageRaw extends ImageRawBase {
126
229
  });
127
230
  }
128
231
  finally {
129
- // Always close the bitmap to free memory
232
+ // Always close the bitmap to free GPU/CPU memory
130
233
  try {
131
234
  bitmap.close();
132
235
  }
133
- catch {
134
- // Ignore if already closed or neutered
135
- }
236
+ catch { /* ignore */ }
136
237
  }
137
238
  }
239
+ /**
240
+ * Create ImageRaw from an OffscreenCanvas
241
+ * Works in both main thread and Web Worker
242
+ * @param canvas - OffscreenCanvas to convert
243
+ * @returns Promise<ImageRaw>
244
+ */
245
+ static async fromOffscreenCanvas(canvas) {
246
+ const imageData = getImageData(canvas);
247
+ return new ImageRaw({
248
+ data: imageData.data,
249
+ width: imageData.width,
250
+ height: imageData.height,
251
+ });
252
+ }
138
253
  /**
139
254
  * Create ImageRaw from an HTMLImageElement
255
+ * Main thread only
140
256
  * @param img - HTMLImageElement to convert (must be loaded/decoded)
141
257
  * @returns Promise<ImageRaw>
142
258
  */
143
259
  static async fromHTMLImageElement(img) {
260
+ if (IS_WORKER) {
261
+ throw new Error('HTMLImageElement is not available in Web Worker. Use ImageBitmap instead.');
262
+ }
144
263
  // Ensure image is loaded
145
264
  if (!img.complete || img.naturalWidth === 0) {
146
265
  await img.decode();
147
266
  }
148
- const canvas = document.createElement('canvas');
267
+ // Use createImageBitmap if available (more efficient)
268
+ if (HAS_CREATE_IMAGE_BITMAP) {
269
+ const bitmap = await createOptimizedImageBitmap(img);
270
+ return ImageRaw.fromImageBitmap(bitmap);
271
+ }
272
+ // Fallback to canvas
273
+ const canvas = createCanvas(img.naturalWidth, img.naturalHeight);
149
274
  canvasDrawImage(canvas, img, img.naturalWidth, img.naturalHeight);
150
- const imageData = canvasGetImageData(canvas);
275
+ const imageData = getImageData(canvas);
151
276
  return new ImageRaw({
152
277
  data: imageData.data,
153
278
  width: imageData.width,
@@ -156,11 +281,15 @@ export class ImageRaw extends ImageRawBase {
156
281
  }
157
282
  /**
158
283
  * Create ImageRaw from an HTMLCanvasElement
284
+ * Main thread only
159
285
  * @param canvas - HTMLCanvasElement to convert
160
286
  * @returns Promise<ImageRaw>
161
287
  */
162
288
  static async fromHTMLCanvasElement(canvas) {
163
- const imageData = canvasGetImageData(canvas);
289
+ if (IS_WORKER) {
290
+ throw new Error('HTMLCanvasElement is not available in Web Worker. Use OffscreenCanvas instead.');
291
+ }
292
+ const imageData = getImageData(canvas);
164
293
  return new ImageRaw({
165
294
  data: imageData.data,
166
295
  width: imageData.width,
@@ -169,17 +298,25 @@ export class ImageRaw extends ImageRawBase {
169
298
  }
170
299
  /**
171
300
  * Create ImageRaw from an HTMLVideoElement (captures current frame)
301
+ * Main thread only
172
302
  * @param video - HTMLVideoElement to capture from
173
303
  * @returns Promise<ImageRaw>
174
304
  */
175
305
  static async fromHTMLVideoElement(video) {
306
+ if (IS_WORKER) {
307
+ throw new Error('HTMLVideoElement is not available in Web Worker. Use ImageBitmap instead.');
308
+ }
176
309
  if (video.readyState < 2) {
177
310
  throw new Error('Video is not ready. Ensure video has loaded metadata and data.');
178
311
  }
179
- const canvas = document.createElement('canvas');
180
- canvas.width = video.videoWidth;
181
- canvas.height = video.videoHeight;
182
- const ctx = canvas.getContext('2d', { willReadFrequently: true });
312
+ // Use createImageBitmap if available (more efficient, direct GPU access)
313
+ if (HAS_CREATE_IMAGE_BITMAP) {
314
+ const bitmap = await createOptimizedImageBitmap(video);
315
+ return ImageRaw.fromImageBitmap(bitmap);
316
+ }
317
+ // Fallback to canvas
318
+ const canvas = createCanvas(video.videoWidth, video.videoHeight);
319
+ const ctx = getContext2D(canvas);
183
320
  if (!ctx) {
184
321
  throw new Error('Failed to create canvas 2D context');
185
322
  }
@@ -195,48 +332,59 @@ export class ImageRaw extends ImageRawBase {
195
332
  // Constructor & Instance Methods
196
333
  // ===========================================
197
334
  constructor({ data, width, height }) {
198
- const newData = Uint8ClampedArray.from(data);
335
+ // Avoid unnecessary copy if already Uint8ClampedArray
336
+ const newData = data instanceof Uint8ClampedArray
337
+ ? new Uint8ClampedArray(data.buffer, data.byteOffset, data.length)
338
+ : new Uint8ClampedArray(data);
199
339
  super({
200
340
  data: newData,
201
341
  width,
202
342
  height,
203
343
  });
204
- const canvas = document.createElement('canvas');
205
- const imageData = new ImageData(newData, width, height);
344
+ const canvas = createCanvas(width, height);
345
+ const imageData = new ImageData(new Uint8ClampedArray(newData), width, height);
206
346
  canvasPutImageData(canvas, imageData);
207
347
  this.#canvas = canvas;
208
348
  this.#imageData = imageData;
209
- this.data = newData; // this.data is undefined without this line
349
+ this.data = newData;
210
350
  }
351
+ /**
352
+ * Debug method - appends canvas to document body
353
+ * Main thread only, no-op in Worker
354
+ */
211
355
  async write(path) {
212
- document.body.append(this.#canvas);
356
+ if (!IS_WORKER && HAS_DOCUMENT && this.#canvas instanceof HTMLCanvasElement) {
357
+ document.body.append(this.#canvas);
358
+ }
359
+ // In Worker environment, this is a no-op
213
360
  }
214
361
  async resize({ width, height }) {
215
362
  invariant(width !== undefined || height !== undefined, 'both width and height are undefined');
216
363
  const newWidth = width || Math.round((this.width / this.height) * height);
217
364
  const newHeight = height || Math.round((this.height / this.width) * width);
218
- const newCanvas = document.createElement('canvas');
365
+ const newCanvas = createCanvas(newWidth, newHeight);
219
366
  canvasDrawImage(newCanvas, this.#canvas, newWidth, newHeight);
220
- const newImageData = canvasGetImageData(newCanvas);
367
+ const newImageData = getImageData(newCanvas);
221
368
  return this.#apply(newImageData);
222
369
  }
223
370
  async drawBox(lineImages) {
224
- this.#ctx.strokeStyle = 'red';
371
+ const ctx = getContext2D(this.#canvas);
372
+ if (!ctx) {
373
+ throw new Error('Failed to get 2D context');
374
+ }
375
+ ctx.strokeStyle = 'red';
225
376
  for (const lineImage of lineImages) {
226
377
  const [first, ...rests] = lineImage.box;
227
- this.#ctx.beginPath();
228
- this.#ctx.moveTo(first[0], first[1]);
378
+ ctx.beginPath();
379
+ ctx.moveTo(first[0], first[1]);
229
380
  for (const rest of rests) {
230
- this.#ctx.lineTo(rest[0], rest[1]);
381
+ ctx.lineTo(rest[0], rest[1]);
231
382
  }
232
- this.#ctx.closePath();
233
- this.#ctx.stroke();
383
+ ctx.closePath();
384
+ ctx.stroke();
234
385
  }
235
386
  return this;
236
387
  }
237
- get #ctx() {
238
- return this.#canvas.getContext('2d');
239
- }
240
388
  #apply(imageData) {
241
389
  canvasPutImageData(this.#canvas, imageData);
242
390
  this.#imageData = imageData;
@@ -245,16 +393,6 @@ export class ImageRaw extends ImageRawBase {
245
393
  this.height = imageData.height;
246
394
  return this;
247
395
  }
248
- #putImageData() {
249
- this.#canvas.width = this.width;
250
- this.#canvas.height = this.height;
251
- this.#ctx.putImageData(this.#imageData, 0, 0);
252
- return this;
253
- }
254
- #drawImage(image, width, height) {
255
- canvasDrawImage(this.#canvas, image, width, height);
256
- return this;
257
- }
258
396
  }
259
397
  // ===========================================
260
398
  // Helper Functions
@@ -262,18 +400,21 @@ export class ImageRaw extends ImageRawBase {
262
400
  function canvasDrawImage(canvas, image, width, height) {
263
401
  canvas.width = width || image.width;
264
402
  canvas.height = height || image.height;
265
- const ctx = canvas.getContext('2d');
403
+ const ctx = getContext2D(canvas);
404
+ if (!ctx) {
405
+ throw new Error('Failed to get 2D context');
406
+ }
266
407
  ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
267
408
  }
268
409
  function canvasPutImageData(canvas, imageData, width, height) {
269
- const ctx = canvas.getContext('2d');
270
410
  canvas.width = width || imageData.width;
271
411
  canvas.height = height || imageData.height;
412
+ const ctx = getContext2D(canvas);
413
+ if (!ctx) {
414
+ throw new Error('Failed to get 2D context');
415
+ }
272
416
  ctx.putImageData(imageData, 0, 0);
273
417
  }
274
- function canvasGetImageData(canvas) {
275
- return canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
276
- }
277
418
  async function imageFromUrl(url) {
278
419
  const image = new Image();
279
420
  image.src = url;
@@ -1 +1 @@
1
- {"version":3,"file":"ImageRaw.js","sourceRoot":"","sources":["../src/ImageRaw.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ImageRaw.js","sourceRoot":"","sources":["../src/ImageRaw.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,OAAO,SAAS,MAAM,gBAAgB,CAAA;AAUtC,2DAA2D;AAC3D,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,CAAA;AACjH,MAAM,oBAAoB,GAAG,OAAO,eAAe,KAAK,WAAW,CAAA;AACnE,MAAM,YAAY,GAAG,OAAO,QAAQ,KAAK,WAAW,CAAA;AACpD,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,WAAW,CAAA;AAC9C,MAAM,uBAAuB,GAAG,OAAO,iBAAiB,KAAK,WAAW,CAAA;AAExE,0EAA0E;AAC1E,MAAM,YAAY,GAAG,IAAI,OAAO,EAA+B,CAAA;AAE/D;;;GAGG;AACH,SAAS,YAAY,CAAC,KAAa,EAAE,MAAc;IACjD,IAAI,oBAAoB,EAAE,CAAC;QACzB,OAAO,IAAI,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;QAC/C,MAAM,CAAC,KAAK,GAAG,KAAK,CAAA;QACpB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAA;QACtB,OAAO,MAAM,CAAA;IACf,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAA;AACpG,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,MAAiB,EAAE,OAA0C;IACjF,oBAAoB;IACpB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,4CAA4C;IAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE;QAClC,kBAAkB,EAAE,IAAI,EAAE,oCAAoC;QAC9D,GAAG,OAAO;KACX,CAA4B,CAAA;IAE7B,IAAI,GAAG,EAAE,CAAC;QACR,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/B,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,MAAiB;IACrC,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IAC7C,CAAC;IACD,OAAO,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;AAC5D,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,0BAA0B,CAAC,MAAyB;IACjE,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IAED,IAAI,CAAC;QACH,uEAAuE;QACvE,OAAO,MAAM,iBAAiB,CAAC,MAAM,EAAE;YACrC,gBAAgB,EAAE,MAAM;YACxB,oBAAoB,EAAE,MAAM;SAC7B,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;QAC3B,OAAO,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAA;IACxC,CAAC;AACH,CAAC;AAED,MAAM,OAAO,QAAS,SAAQ,YAAY;IACxC,IAAI,CAAmB;IACvB,UAAU,CAAW;IACrB,OAAO,CAAW;IAElB,8CAA8C;IAC9C,cAAc;IACd,8CAA8C;IAE9C;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,KAAc;QACjC,OAAO,OAAO,WAAW,KAAK,WAAW,IAAI,KAAK,YAAY,WAAW,CAAA;IAC3E,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,KAAc;QACtC,OAAO,OAAO,gBAAgB,KAAK,WAAW,IAAI,KAAK,YAAY,gBAAgB,CAAA;IACrF,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,KAAc;QACvC,OAAO,OAAO,iBAAiB,KAAK,WAAW,IAAI,KAAK,YAAY,iBAAiB,CAAA;IACvF,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,KAAc;QACtC,OAAO,OAAO,gBAAgB,KAAK,WAAW,IAAI,KAAK,YAAY,gBAAgB,CAAA;IACrF,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,KAAc;QACrC,OAAO,oBAAoB,IAAI,KAAK,YAAY,eAAe,CAAA;IACjE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,KAAc;QAClC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,MAAM,IAAI,KAAK;YACf,OAAO,IAAI,KAAK;YAChB,QAAQ,IAAI,KAAK;YACjB,CAAC,KAAK,CAAC,IAAI,YAAY,UAAU,IAAI,KAAK,CAAC,IAAI,YAAY,iBAAiB,CAAC,CAC9E,CAAA;IACH,CAAC;IAED,8CAA8C;IAC9C,kBAAkB;IAClB,8CAA8C;IAE9C;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAA0C;QAC1D,2BAA2B;QAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,CAAC;QAED,sEAAsE;QACtE,IAAI,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;QACxC,CAAC;QAED,yDAAyD;QACzD,IAAI,QAAQ,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,OAAO,QAAQ,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAA;QAC5C,CAAC;QAED,sCAAsC;QACtC,IAAI,QAAQ,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAA;YAC9F,CAAC;YACD,OAAO,QAAQ,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAA;QAC7C,CAAC;QAED,uCAAuC;QACvC,IAAI,QAAQ,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YACxC,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAA;YACnG,CAAC;YACD,OAAO,QAAQ,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAA;QAC9C,CAAC;QAED,sCAAsC;QACtC,IAAI,QAAQ,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAA;YAC9F,CAAC;YACD,OAAO,QAAQ,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAA;QAC7C,CAAC;QAED,6CAA6C;QAC7C,IAAI,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC5B,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACjD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAW;QAC3B,0EAA0E;QAC1E,IAAI,uBAAuB,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;YACjC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;YAClC,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,IAAI,CAAC,CAAA;YACrD,OAAO,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;QACzC,CAAC;QAED,iDAAiD;QACjD,IAAI,CAAC,SAAS,IAAI,SAAS,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,CAAA;YACpE,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,CAAA;YACvE,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;YACtC,OAAO,IAAI,QAAQ,CAAC;gBAClB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,KAAK,EAAE,SAAS,CAAC,KAAK;gBACtB,MAAM,EAAE,SAAS,CAAC,MAAM;aACzB,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAA;IAC9E,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,MAAmB;QAC9C,kBAAkB;QAClB,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAA;QAChG,CAAC;QAED,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QACxD,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAEhC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,0BAA0B;YAC1B,IAAI,CAAC;gBAAC,MAAM,CAAC,KAAK,EAAE,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACvD,CAAC;QAED,IAAI,CAAC;YACH,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YAC3B,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;YAErE,OAAO,IAAI,QAAQ,CAAC;gBAClB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,KAAK,EAAE,SAAS,CAAC,KAAK;gBACtB,MAAM,EAAE,SAAS,CAAC,MAAM;aACzB,CAAC,CAAA;QACJ,CAAC;gBAAS,CAAC;YACT,iDAAiD;YACjD,IAAI,CAAC;gBAAC,MAAM,CAAC,KAAK,EAAE,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAuB;QACtD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAEtC,OAAO,IAAI,QAAQ,CAAC;YAClB,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,MAAM,EAAE,SAAS,CAAC,MAAM;SACzB,CAAC,CAAA;IACJ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,GAAqB;QACrD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAA;QAC9F,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,KAAK,CAAC,EAAE,CAAC;YAC5C,MAAM,GAAG,CAAC,MAAM,EAAE,CAAA;QACpB,CAAC;QAED,sDAAsD;QACtD,IAAI,uBAAuB,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,GAAG,CAAC,CAAA;YACpD,OAAO,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;QACzC,CAAC;QAED,qBAAqB;QACrB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,aAAa,CAAC,CAAA;QAChE,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,aAAa,CAAC,CAAA;QACjE,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAEtC,OAAO,IAAI,QAAQ,CAAC;YAClB,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,MAAM,EAAE,SAAS,CAAC,MAAM;SACzB,CAAC,CAAA;IACJ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,MAAyB;QAC1D,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAA;QACnG,CAAC;QAED,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAEtC,OAAO,IAAI,QAAQ,CAAC;YAClB,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,MAAM,EAAE,SAAS,CAAC,MAAM;SACzB,CAAC,CAAA;IACJ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAuB;QACvD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAA;QAC9F,CAAC;QAED,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;QACnF,CAAC;QAED,yEAAyE;QACzE,IAAI,uBAAuB,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,KAAK,CAAC,CAAA;YACtD,OAAO,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;QACzC,CAAC;QAED,qBAAqB;QACrB,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;QAChE,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAEhC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACvD,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QAC1B,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QAErE,OAAO,IAAI,QAAQ,CAAC;YAClB,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,MAAM,EAAE,SAAS,CAAC,MAAM;SACzB,CAAC,CAAA;IACJ,CAAC;IAED,8CAA8C;IAC9C,iCAAiC;IACjC,8CAA8C;IAE9C,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAgB;QAC/C,sDAAsD;QACtD,MAAM,OAAO,GAAG,IAAI,YAAY,iBAAiB;YAC/C,CAAC,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;YAClE,CAAC,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAA;QAE/B,KAAK,CAAC;YACJ,IAAI,EAAE,OAAO;YACb,KAAK;YACL,MAAM;SACP,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC1C,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QAC9E,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QACrC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAA;QAC3B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAA;IACrB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,IAAY;QACtB,IAAI,CAAC,SAAS,IAAI,YAAY,IAAI,IAAI,CAAC,OAAO,YAAY,iBAAiB,EAAE,CAAC;YAC5E,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACpC,CAAC;QACD,yCAAyC;IAC3C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAc;QACxC,SAAS,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,qCAAqC,CAAC,CAAA;QAC7F,MAAM,QAAQ,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,MAAO,CAAC,CAAA;QAC1E,MAAM,SAAS,GAAG,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,KAAM,CAAC,CAAA;QAC3E,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;QACnD,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;QAC7D,MAAM,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAuB;QACnC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACtC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;QAC7C,CAAC;QACD,GAAG,CAAC,WAAW,GAAG,KAAK,CAAA;QACvB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,GAAG,SAAS,CAAC,GAAG,CAAA;YACvC,GAAG,CAAC,SAAS,EAAE,CAAA;YACf,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;YAC9B,CAAC;YACD,GAAG,CAAC,SAAS,EAAE,CAAA;YACf,GAAG,CAAC,MAAM,EAAE,CAAA;QACd,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,CAAC,SAAoB;QACzB,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;QAC3C,IAAI,CAAC,UAAU,GAAG,SAAS,CAAA;QAC3B,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;QAC1B,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAA;QAC5B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;QAC9B,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAED,8CAA8C;AAC9C,mBAAmB;AACnB,8CAA8C;AAE9C,SAAS,eAAe,CAAC,MAAiB,EAAE,KAAwB,EAAE,KAAc,EAAE,MAAe;IACnG,MAAM,CAAC,KAAK,GAAG,KAAK,IAAK,KAAa,CAAC,KAAK,CAAA;IAC5C,MAAM,CAAC,MAAM,GAAG,MAAM,IAAK,KAAa,CAAC,MAAM,CAAA;IAC/C,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IAC7C,CAAC;IACD,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;AACzD,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAiB,EAAE,SAAoB,EAAE,KAAc,EAAE,MAAe;IAClG,MAAM,CAAC,KAAK,GAAG,KAAK,IAAI,SAAS,CAAC,KAAK,CAAA;IACvC,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,SAAS,CAAC,MAAM,CAAA;IAC1C,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IAC7C,CAAC;IACD,GAAG,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;AACnC,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAW;IACrC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAA;IACzB,KAAK,CAAC,GAAG,GAAG,GAAG,CAAA;IACf,MAAM,KAAK,CAAC,MAAM,EAAE,CAAA;IACpB,OAAO,KAAK,CAAA;AACd,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@areb0s/ocr-browser",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Fork of @gutenye/ocr-browser with ImageBitmap support. High accurate OCR library for Browser based on PaddleOCR and ONNX runtime. Accepts ImageBitmap, HTMLImageElement, HTMLCanvasElement, HTMLVideoElement as input.",
5
5
  "keywords": [
6
6
  "ocr",
package/src/ImageRaw.ts CHANGED
@@ -2,10 +2,98 @@ import { ImageRawBase } from '@areb0s/ocr-common'
2
2
  import type { ImageRawData, LineImage, SizeOption, BrowserImageInput } from '@areb0s/ocr-common'
3
3
  import invariant from 'tiny-invariant'
4
4
 
5
+ // ===========================================
6
+ // Environment Detection & Canvas Factory
7
+ // (Cached for performance)
8
+ // ===========================================
9
+
10
+ type AnyCanvas = HTMLCanvasElement | OffscreenCanvas
11
+ type AnyCanvasContext = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D
12
+
13
+ // Cache environment checks (evaluated once at module load)
14
+ const IS_WORKER = typeof window === 'undefined' && typeof self !== 'undefined' && typeof document === 'undefined'
15
+ const HAS_OFFSCREEN_CANVAS = typeof OffscreenCanvas !== 'undefined'
16
+ const HAS_DOCUMENT = typeof document !== 'undefined'
17
+ const HAS_IMAGE = typeof Image !== 'undefined'
18
+ const HAS_CREATE_IMAGE_BITMAP = typeof createImageBitmap !== 'undefined'
19
+
20
+ // Cache canvas contexts for reuse (WeakMap allows GC when canvas is gone)
21
+ const contextCache = new WeakMap<AnyCanvas, AnyCanvasContext>()
22
+
23
+ /**
24
+ * Create a canvas that works in both main thread and Web Worker
25
+ * Prefers OffscreenCanvas for better performance
26
+ */
27
+ function createCanvas(width: number, height: number): AnyCanvas {
28
+ if (HAS_OFFSCREEN_CANVAS) {
29
+ return new OffscreenCanvas(width, height)
30
+ }
31
+ if (HAS_DOCUMENT) {
32
+ const canvas = document.createElement('canvas')
33
+ canvas.width = width
34
+ canvas.height = height
35
+ return canvas
36
+ }
37
+ throw new Error('No canvas support available. Neither OffscreenCanvas nor document is available.')
38
+ }
39
+
40
+ /**
41
+ * Get 2D context from any canvas type (cached for performance)
42
+ */
43
+ function getContext2D(canvas: AnyCanvas, options?: CanvasRenderingContext2DSettings): AnyCanvasContext | null {
44
+ // Check cache first
45
+ const cached = contextCache.get(canvas)
46
+ if (cached) return cached
47
+
48
+ // Create new context with performance hints
49
+ const ctx = canvas.getContext('2d', {
50
+ willReadFrequently: true, // Optimize for getImageData() calls
51
+ ...options
52
+ }) as AnyCanvasContext | null
53
+
54
+ if (ctx) {
55
+ contextCache.set(canvas, ctx)
56
+ }
57
+ return ctx
58
+ }
59
+
60
+ /**
61
+ * Get ImageData from any canvas type
62
+ */
63
+ function getImageData(canvas: AnyCanvas): ImageData {
64
+ const ctx = getContext2D(canvas)
65
+ if (!ctx) {
66
+ throw new Error('Failed to get 2D context')
67
+ }
68
+ return ctx.getImageData(0, 0, canvas.width, canvas.height)
69
+ }
70
+
71
+ /**
72
+ * Create ImageBitmap with optimized options for OCR
73
+ * - premultiplyAlpha: 'none' - avoid alpha premultiplication overhead
74
+ * - colorSpaceConversion: 'none' - avoid color space conversion overhead
75
+ */
76
+ async function createOptimizedImageBitmap(source: ImageBitmapSource): Promise<ImageBitmap> {
77
+ if (!HAS_CREATE_IMAGE_BITMAP) {
78
+ throw new Error('createImageBitmap is not supported')
79
+ }
80
+
81
+ try {
82
+ // Try with optimization options (may not be supported in all browsers)
83
+ return await createImageBitmap(source, {
84
+ premultiplyAlpha: 'none',
85
+ colorSpaceConversion: 'none',
86
+ })
87
+ } catch {
88
+ // Fallback without options
89
+ return await createImageBitmap(source)
90
+ }
91
+ }
92
+
5
93
  export class ImageRaw extends ImageRawBase {
6
94
  data: Uint8ClampedArray
7
95
  #imageData: ImageData
8
- #canvas: HTMLCanvasElement
96
+ #canvas: AnyCanvas
9
97
 
10
98
  // ===========================================
11
99
  // Type Guards
@@ -39,6 +127,13 @@ export class ImageRaw extends ImageRawBase {
39
127
  return typeof HTMLVideoElement !== 'undefined' && input instanceof HTMLVideoElement
40
128
  }
41
129
 
130
+ /**
131
+ * Check if the input is an OffscreenCanvas
132
+ */
133
+ static isOffscreenCanvas(input: unknown): input is OffscreenCanvas {
134
+ return HAS_OFFSCREEN_CANVAS && input instanceof OffscreenCanvas
135
+ }
136
+
42
137
  /**
43
138
  * Check if the input is ImageRawData
44
139
  */
@@ -59,36 +154,51 @@ export class ImageRaw extends ImageRawBase {
59
154
 
60
155
  /**
61
156
  * Universal factory method that accepts all browser image input types
62
- * @param input - URL string, ImageRawData, ImageBitmap, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement
157
+ * Works in both main thread and Web Worker
158
+ * @param input - URL string, ImageRawData, ImageBitmap, HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, or HTMLVideoElement
63
159
  * @returns Promise<ImageRaw>
64
160
  */
65
- static async from(input: BrowserImageInput): Promise<ImageRaw> {
161
+ static async from(input: BrowserImageInput | OffscreenCanvas): Promise<ImageRaw> {
66
162
  // String (URL or data URL)
67
163
  if (typeof input === 'string') {
68
164
  return ImageRaw.open(input)
69
165
  }
70
166
 
71
- // ImageBitmap
167
+ // ImageBitmap - Works in both main thread and Worker (most efficient)
72
168
  if (ImageRaw.isImageBitmap(input)) {
73
169
  return ImageRaw.fromImageBitmap(input)
74
170
  }
75
171
 
76
- // HTMLImageElement
172
+ // OffscreenCanvas - Works in both main thread and Worker
173
+ if (ImageRaw.isOffscreenCanvas(input)) {
174
+ return ImageRaw.fromOffscreenCanvas(input)
175
+ }
176
+
177
+ // HTMLImageElement - Main thread only
77
178
  if (ImageRaw.isHTMLImageElement(input)) {
179
+ if (IS_WORKER) {
180
+ throw new Error('HTMLImageElement is not available in Web Worker. Use ImageBitmap instead.')
181
+ }
78
182
  return ImageRaw.fromHTMLImageElement(input)
79
183
  }
80
184
 
81
- // HTMLCanvasElement
185
+ // HTMLCanvasElement - Main thread only
82
186
  if (ImageRaw.isHTMLCanvasElement(input)) {
187
+ if (IS_WORKER) {
188
+ throw new Error('HTMLCanvasElement is not available in Web Worker. Use OffscreenCanvas instead.')
189
+ }
83
190
  return ImageRaw.fromHTMLCanvasElement(input)
84
191
  }
85
192
 
86
- // HTMLVideoElement
193
+ // HTMLVideoElement - Main thread only
87
194
  if (ImageRaw.isHTMLVideoElement(input)) {
195
+ if (IS_WORKER) {
196
+ throw new Error('HTMLVideoElement is not available in Web Worker. Use ImageBitmap instead.')
197
+ }
88
198
  return ImageRaw.fromHTMLVideoElement(input)
89
199
  }
90
200
 
91
- // ImageRawData (fallback)
201
+ // ImageRawData (fallback) - Works everywhere
92
202
  if (ImageRaw.isImageRawData(input)) {
93
203
  return new ImageRaw(input)
94
204
  }
@@ -97,22 +207,38 @@ export class ImageRaw extends ImageRawBase {
97
207
  }
98
208
 
99
209
  /**
100
- * Create ImageRaw from a URL (existing method)
210
+ * Create ImageRaw from a URL
211
+ * Works in both main thread and Web Worker
212
+ * Uses fetch + createImageBitmap for best performance
101
213
  */
102
214
  static async open(url: string): Promise<ImageRaw> {
103
- const image = await imageFromUrl(url)
104
- const canvas = document.createElement('canvas')
105
- canvasDrawImage(canvas, image, image.naturalWidth, image.naturalHeight)
106
- const imageData = canvasGetImageData(canvas)
107
- return new ImageRaw({
108
- data: imageData.data,
109
- width: imageData.width,
110
- height: imageData.height,
111
- })
215
+ // Prefer fetch + createImageBitmap (works everywhere, better performance)
216
+ if (HAS_CREATE_IMAGE_BITMAP) {
217
+ const response = await fetch(url)
218
+ const blob = await response.blob()
219
+ const bitmap = await createOptimizedImageBitmap(blob)
220
+ return ImageRaw.fromImageBitmap(bitmap)
221
+ }
222
+
223
+ // Fallback: use Image element (main thread only)
224
+ if (!IS_WORKER && HAS_IMAGE) {
225
+ const image = await imageFromUrl(url)
226
+ const canvas = createCanvas(image.naturalWidth, image.naturalHeight)
227
+ canvasDrawImage(canvas, image, image.naturalWidth, image.naturalHeight)
228
+ const imageData = getImageData(canvas)
229
+ return new ImageRaw({
230
+ data: imageData.data,
231
+ width: imageData.width,
232
+ height: imageData.height,
233
+ })
234
+ }
235
+
236
+ throw new Error('Cannot load image from URL: no supported method available')
112
237
  }
113
238
 
114
239
  /**
115
240
  * Create ImageRaw from an ImageBitmap
241
+ * Works in both main thread and Web Worker
116
242
  * Note: This method will close the ImageBitmap after conversion to free memory
117
243
  * @param bitmap - ImageBitmap to convert
118
244
  * @returns Promise<ImageRaw>
@@ -123,18 +249,12 @@ export class ImageRaw extends ImageRawBase {
123
249
  throw new Error('Invalid ImageBitmap: dimensions are zero (bitmap may be closed or neutered)')
124
250
  }
125
251
 
126
- const canvas = document.createElement('canvas')
127
- canvas.width = bitmap.width
128
- canvas.height = bitmap.height
129
-
130
- const ctx = canvas.getContext('2d', { willReadFrequently: true })
252
+ const canvas = createCanvas(bitmap.width, bitmap.height)
253
+ const ctx = getContext2D(canvas)
254
+
131
255
  if (!ctx) {
132
256
  // Cleanup before throwing
133
- try {
134
- bitmap.close()
135
- } catch {
136
- // Ignore if already closed
137
- }
257
+ try { bitmap.close() } catch { /* ignore */ }
138
258
  throw new Error('Failed to create canvas 2D context')
139
259
  }
140
260
 
@@ -148,29 +268,53 @@ export class ImageRaw extends ImageRawBase {
148
268
  height: imageData.height,
149
269
  })
150
270
  } finally {
151
- // Always close the bitmap to free memory
152
- try {
153
- bitmap.close()
154
- } catch {
155
- // Ignore if already closed or neutered
156
- }
271
+ // Always close the bitmap to free GPU/CPU memory
272
+ try { bitmap.close() } catch { /* ignore */ }
157
273
  }
158
274
  }
159
275
 
276
+ /**
277
+ * Create ImageRaw from an OffscreenCanvas
278
+ * Works in both main thread and Web Worker
279
+ * @param canvas - OffscreenCanvas to convert
280
+ * @returns Promise<ImageRaw>
281
+ */
282
+ static async fromOffscreenCanvas(canvas: OffscreenCanvas): Promise<ImageRaw> {
283
+ const imageData = getImageData(canvas)
284
+
285
+ return new ImageRaw({
286
+ data: imageData.data,
287
+ width: imageData.width,
288
+ height: imageData.height,
289
+ })
290
+ }
291
+
160
292
  /**
161
293
  * Create ImageRaw from an HTMLImageElement
294
+ * Main thread only
162
295
  * @param img - HTMLImageElement to convert (must be loaded/decoded)
163
296
  * @returns Promise<ImageRaw>
164
297
  */
165
298
  static async fromHTMLImageElement(img: HTMLImageElement): Promise<ImageRaw> {
299
+ if (IS_WORKER) {
300
+ throw new Error('HTMLImageElement is not available in Web Worker. Use ImageBitmap instead.')
301
+ }
302
+
166
303
  // Ensure image is loaded
167
304
  if (!img.complete || img.naturalWidth === 0) {
168
305
  await img.decode()
169
306
  }
170
307
 
171
- const canvas = document.createElement('canvas')
308
+ // Use createImageBitmap if available (more efficient)
309
+ if (HAS_CREATE_IMAGE_BITMAP) {
310
+ const bitmap = await createOptimizedImageBitmap(img)
311
+ return ImageRaw.fromImageBitmap(bitmap)
312
+ }
313
+
314
+ // Fallback to canvas
315
+ const canvas = createCanvas(img.naturalWidth, img.naturalHeight)
172
316
  canvasDrawImage(canvas, img, img.naturalWidth, img.naturalHeight)
173
- const imageData = canvasGetImageData(canvas)
317
+ const imageData = getImageData(canvas)
174
318
 
175
319
  return new ImageRaw({
176
320
  data: imageData.data,
@@ -181,11 +325,16 @@ export class ImageRaw extends ImageRawBase {
181
325
 
182
326
  /**
183
327
  * Create ImageRaw from an HTMLCanvasElement
328
+ * Main thread only
184
329
  * @param canvas - HTMLCanvasElement to convert
185
330
  * @returns Promise<ImageRaw>
186
331
  */
187
332
  static async fromHTMLCanvasElement(canvas: HTMLCanvasElement): Promise<ImageRaw> {
188
- const imageData = canvasGetImageData(canvas)
333
+ if (IS_WORKER) {
334
+ throw new Error('HTMLCanvasElement is not available in Web Worker. Use OffscreenCanvas instead.')
335
+ }
336
+
337
+ const imageData = getImageData(canvas)
189
338
 
190
339
  return new ImageRaw({
191
340
  data: imageData.data,
@@ -196,19 +345,29 @@ export class ImageRaw extends ImageRawBase {
196
345
 
197
346
  /**
198
347
  * Create ImageRaw from an HTMLVideoElement (captures current frame)
348
+ * Main thread only
199
349
  * @param video - HTMLVideoElement to capture from
200
350
  * @returns Promise<ImageRaw>
201
351
  */
202
352
  static async fromHTMLVideoElement(video: HTMLVideoElement): Promise<ImageRaw> {
353
+ if (IS_WORKER) {
354
+ throw new Error('HTMLVideoElement is not available in Web Worker. Use ImageBitmap instead.')
355
+ }
356
+
203
357
  if (video.readyState < 2) {
204
358
  throw new Error('Video is not ready. Ensure video has loaded metadata and data.')
205
359
  }
206
360
 
207
- const canvas = document.createElement('canvas')
208
- canvas.width = video.videoWidth
209
- canvas.height = video.videoHeight
361
+ // Use createImageBitmap if available (more efficient, direct GPU access)
362
+ if (HAS_CREATE_IMAGE_BITMAP) {
363
+ const bitmap = await createOptimizedImageBitmap(video)
364
+ return ImageRaw.fromImageBitmap(bitmap)
365
+ }
210
366
 
211
- const ctx = canvas.getContext('2d', { willReadFrequently: true })
367
+ // Fallback to canvas
368
+ const canvas = createCanvas(video.videoWidth, video.videoHeight)
369
+ const ctx = getContext2D(canvas)
370
+
212
371
  if (!ctx) {
213
372
  throw new Error('Failed to create canvas 2D context')
214
373
  }
@@ -228,53 +387,65 @@ export class ImageRaw extends ImageRawBase {
228
387
  // ===========================================
229
388
 
230
389
  constructor({ data, width, height }: ImageRawData) {
231
- const newData = Uint8ClampedArray.from(data)
390
+ // Avoid unnecessary copy if already Uint8ClampedArray
391
+ const newData = data instanceof Uint8ClampedArray
392
+ ? new Uint8ClampedArray(data.buffer, data.byteOffset, data.length)
393
+ : new Uint8ClampedArray(data)
394
+
232
395
  super({
233
396
  data: newData,
234
397
  width,
235
398
  height,
236
399
  })
237
- const canvas = document.createElement('canvas')
238
- const imageData = new ImageData(newData, width, height)
400
+
401
+ const canvas = createCanvas(width, height)
402
+ const imageData = new ImageData(new Uint8ClampedArray(newData), width, height)
239
403
  canvasPutImageData(canvas, imageData)
240
404
  this.#canvas = canvas
241
405
  this.#imageData = imageData
242
- this.data = newData // this.data is undefined without this line
406
+ this.data = newData
243
407
  }
244
408
 
409
+ /**
410
+ * Debug method - appends canvas to document body
411
+ * Main thread only, no-op in Worker
412
+ */
245
413
  async write(path: string) {
246
- document.body.append(this.#canvas)
414
+ if (!IS_WORKER && HAS_DOCUMENT && this.#canvas instanceof HTMLCanvasElement) {
415
+ document.body.append(this.#canvas)
416
+ }
417
+ // In Worker environment, this is a no-op
247
418
  }
248
419
 
249
420
  async resize({ width, height }: SizeOption) {
250
421
  invariant(width !== undefined || height !== undefined, 'both width and height are undefined')
251
422
  const newWidth = width || Math.round((this.width / this.height) * height!)
252
423
  const newHeight = height || Math.round((this.height / this.width) * width!)
253
- const newCanvas = document.createElement('canvas')
424
+ const newCanvas = createCanvas(newWidth, newHeight)
254
425
  canvasDrawImage(newCanvas, this.#canvas, newWidth, newHeight)
255
- const newImageData = canvasGetImageData(newCanvas)
426
+ const newImageData = getImageData(newCanvas)
256
427
  return this.#apply(newImageData)
257
428
  }
258
429
 
259
430
  async drawBox(lineImages: LineImage[]) {
260
- this.#ctx.strokeStyle = 'red'
431
+ const ctx = getContext2D(this.#canvas)
432
+ if (!ctx) {
433
+ throw new Error('Failed to get 2D context')
434
+ }
435
+ ctx.strokeStyle = 'red'
261
436
  for (const lineImage of lineImages) {
262
437
  const [first, ...rests] = lineImage.box
263
- this.#ctx.beginPath()
264
- this.#ctx.moveTo(first[0], first[1])
438
+ ctx.beginPath()
439
+ ctx.moveTo(first[0], first[1])
265
440
  for (const rest of rests) {
266
- this.#ctx.lineTo(rest[0], rest[1])
441
+ ctx.lineTo(rest[0], rest[1])
267
442
  }
268
- this.#ctx.closePath()
269
- this.#ctx.stroke()
443
+ ctx.closePath()
444
+ ctx.stroke()
270
445
  }
271
446
  return this
272
447
  }
273
448
 
274
- get #ctx() {
275
- return this.#canvas.getContext('2d')!
276
- }
277
-
278
449
  #apply(imageData: ImageData) {
279
450
  canvasPutImageData(this.#canvas, imageData)
280
451
  this.#imageData = imageData
@@ -283,43 +454,33 @@ export class ImageRaw extends ImageRawBase {
283
454
  this.height = imageData.height
284
455
  return this
285
456
  }
286
-
287
- #putImageData() {
288
- this.#canvas.width = this.width
289
- this.#canvas.height = this.height
290
- this.#ctx.putImageData(this.#imageData, 0, 0)
291
- return this
292
- }
293
-
294
- #drawImage(image: CanvasImageSource, width?: number, height?: number) {
295
- canvasDrawImage(this.#canvas, image, width, height)
296
- return this
297
- }
298
457
  }
299
458
 
300
459
  // ===========================================
301
460
  // Helper Functions
302
461
  // ===========================================
303
462
 
304
- function canvasDrawImage(canvas: HTMLCanvasElement, image: CanvasImageSource, width?: number, height?: number) {
463
+ function canvasDrawImage(canvas: AnyCanvas, image: CanvasImageSource, width?: number, height?: number) {
305
464
  canvas.width = width || (image as any).width
306
465
  canvas.height = height || (image as any).height
307
- const ctx = canvas.getContext('2d')!
466
+ const ctx = getContext2D(canvas)
467
+ if (!ctx) {
468
+ throw new Error('Failed to get 2D context')
469
+ }
308
470
  ctx.drawImage(image, 0, 0, canvas.width, canvas.height)
309
471
  }
310
472
 
311
- function canvasPutImageData(canvas: HTMLCanvasElement, imageData: ImageData, width?: number, height?: number) {
312
- const ctx = canvas.getContext('2d')!
473
+ function canvasPutImageData(canvas: AnyCanvas, imageData: ImageData, width?: number, height?: number) {
313
474
  canvas.width = width || imageData.width
314
475
  canvas.height = height || imageData.height
476
+ const ctx = getContext2D(canvas)
477
+ if (!ctx) {
478
+ throw new Error('Failed to get 2D context')
479
+ }
315
480
  ctx.putImageData(imageData, 0, 0)
316
481
  }
317
482
 
318
- function canvasGetImageData(canvas: HTMLCanvasElement) {
319
- return canvas.getContext('2d')!.getImageData(0, 0, canvas.width, canvas.height)
320
- }
321
-
322
- async function imageFromUrl(url: string) {
483
+ async function imageFromUrl(url: string): Promise<HTMLImageElement> {
323
484
  const image = new Image()
324
485
  image.src = url
325
486
  await image.decode()