@computationalpathologygroup/openslide-js 1.0.0-beta.2

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.
Files changed (69) hide show
  1. package/LICENSE +501 -0
  2. package/NOTICE +216 -0
  3. package/README.md +160 -0
  4. package/dist/cjs/deep-zoom.d.ts +66 -0
  5. package/dist/cjs/deep-zoom.d.ts.map +1 -0
  6. package/dist/cjs/deep-zoom.js +186 -0
  7. package/dist/cjs/deep-zoom.js.map +1 -0
  8. package/dist/cjs/errors.d.ts +9 -0
  9. package/dist/cjs/errors.d.ts.map +1 -0
  10. package/dist/cjs/errors.js +26 -0
  11. package/dist/cjs/errors.js.map +1 -0
  12. package/dist/cjs/index.d.ts +18 -0
  13. package/dist/cjs/index.d.ts.map +1 -0
  14. package/dist/cjs/index.js +27 -0
  15. package/dist/cjs/index.js.map +1 -0
  16. package/dist/cjs/openslide.d.ts +47 -0
  17. package/dist/cjs/openslide.d.ts.map +1 -0
  18. package/dist/cjs/openslide.js +191 -0
  19. package/dist/cjs/openslide.js.map +1 -0
  20. package/dist/cjs/package.json +1 -0
  21. package/dist/cjs/slide.d.ts +70 -0
  22. package/dist/cjs/slide.d.ts.map +1 -0
  23. package/dist/cjs/slide.js +139 -0
  24. package/dist/cjs/slide.js.map +1 -0
  25. package/dist/cjs/types.d.ts +150 -0
  26. package/dist/cjs/types.d.ts.map +1 -0
  27. package/dist/cjs/types.js +3 -0
  28. package/dist/cjs/types.js.map +1 -0
  29. package/dist/cjs/wasm/openslide.js +2 -0
  30. package/dist/cjs/wasm/openslide.wasm +0 -0
  31. package/dist/cjs/worker-api.d.ts +55 -0
  32. package/dist/cjs/worker-api.d.ts.map +1 -0
  33. package/dist/cjs/worker-api.js +287 -0
  34. package/dist/cjs/worker-api.js.map +1 -0
  35. package/dist/esm/deep-zoom.d.ts +66 -0
  36. package/dist/esm/deep-zoom.d.ts.map +1 -0
  37. package/dist/esm/deep-zoom.js +182 -0
  38. package/dist/esm/deep-zoom.js.map +1 -0
  39. package/dist/esm/errors.d.ts +9 -0
  40. package/dist/esm/errors.d.ts.map +1 -0
  41. package/dist/esm/errors.js +21 -0
  42. package/dist/esm/errors.js.map +1 -0
  43. package/dist/esm/index.d.ts +18 -0
  44. package/dist/esm/index.d.ts.map +1 -0
  45. package/dist/esm/index.js +19 -0
  46. package/dist/esm/index.js.map +1 -0
  47. package/dist/esm/openslide.d.ts +47 -0
  48. package/dist/esm/openslide.d.ts.map +1 -0
  49. package/dist/esm/openslide.js +187 -0
  50. package/dist/esm/openslide.js.map +1 -0
  51. package/dist/esm/slide.d.ts +70 -0
  52. package/dist/esm/slide.d.ts.map +1 -0
  53. package/dist/esm/slide.js +135 -0
  54. package/dist/esm/slide.js.map +1 -0
  55. package/dist/esm/types.d.ts +150 -0
  56. package/dist/esm/types.d.ts.map +1 -0
  57. package/dist/esm/types.js +2 -0
  58. package/dist/esm/types.js.map +1 -0
  59. package/dist/esm/wasm/openslide.js +2 -0
  60. package/dist/esm/wasm/openslide.wasm +0 -0
  61. package/dist/esm/worker-api.d.ts +55 -0
  62. package/dist/esm/worker-api.d.ts.map +1 -0
  63. package/dist/esm/worker-api.js +283 -0
  64. package/dist/esm/worker-api.js.map +1 -0
  65. package/dist/esm/worker.d.ts +8 -0
  66. package/dist/esm/worker.d.ts.map +1 -0
  67. package/dist/esm/worker.js +175 -0
  68. package/dist/esm/worker.js.map +1 -0
  69. package/package.json +74 -0
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpenSlideUnsupportedFormatError = exports.OpenSlideError = void 0;
4
+ /** Base error class for all OpenSlide errors. */
5
+ class OpenSlideError extends Error {
6
+ constructor(message) {
7
+ const msg = typeof message === 'string' ? message
8
+ : message instanceof Error ? message.message
9
+ : typeof message === 'object' && message !== null ? JSON.stringify(message)
10
+ : String(message);
11
+ super(msg);
12
+ this.name = 'OpenSlideError';
13
+ Object.setPrototypeOf(this, new.target.prototype);
14
+ }
15
+ }
16
+ exports.OpenSlideError = OpenSlideError;
17
+ /** Thrown when the file format is not supported by OpenSlide. */
18
+ class OpenSlideUnsupportedFormatError extends OpenSlideError {
19
+ constructor(message) {
20
+ super(message ?? 'Unsupported slide format');
21
+ this.name = 'OpenSlideUnsupportedFormatError';
22
+ Object.setPrototypeOf(this, new.target.prototype);
23
+ }
24
+ }
25
+ exports.OpenSlideUnsupportedFormatError = OpenSlideUnsupportedFormatError;
26
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":";;;AAAA,iDAAiD;AACjD,MAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAgB;QAC1B,MAAM,GAAG,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO;YAC/C,CAAC,CAAC,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;gBAC5C,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;oBAC3E,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpB,KAAK,CAAC,GAAG,CAAC,CAAC;QACX,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAVD,wCAUC;AAED,iEAAiE;AACjE,MAAa,+BAAgC,SAAQ,cAAc;IACjE,YAAY,OAAgB;QAC1B,KAAK,CAAC,OAAO,IAAI,0BAA0B,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,GAAG,iCAAiC,CAAC;QAC9C,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAND,0EAMC"}
@@ -0,0 +1,18 @@
1
+ export { OpenSlide } from './openslide.js';
2
+ export { Slide } from './slide.js';
3
+ export { DeepZoomGenerator } from './deep-zoom.js';
4
+ export type { DeepZoomOptions } from './deep-zoom.js';
5
+ export { OpenSlideError, OpenSlideUnsupportedFormatError } from './errors.js';
6
+ export type { Dimensions, SlideInfo, DziInfo, OpenSlideOptions, SlideSource, VirtualFile, } from './types.js';
7
+ export declare const PROPERTY_NAME_COMMENT = "openslide.comment";
8
+ export declare const PROPERTY_NAME_VENDOR = "openslide.vendor";
9
+ export declare const PROPERTY_NAME_QUICKHASH1 = "openslide.quickhash-1";
10
+ export declare const PROPERTY_NAME_BACKGROUND_COLOR = "openslide.background-color";
11
+ export declare const PROPERTY_NAME_OBJECTIVE_POWER = "openslide.objective-power";
12
+ export declare const PROPERTY_NAME_MPP_X = "openslide.mpp-x";
13
+ export declare const PROPERTY_NAME_MPP_Y = "openslide.mpp-y";
14
+ export declare const PROPERTY_NAME_BOUNDS_X = "openslide.bounds-x";
15
+ export declare const PROPERTY_NAME_BOUNDS_Y = "openslide.bounds-y";
16
+ export declare const PROPERTY_NAME_BOUNDS_WIDTH = "openslide.bounds-width";
17
+ export declare const PROPERTY_NAME_BOUNDS_HEIGHT = "openslide.bounds-height";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,cAAc,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AAG9E,YAAY,EACV,UAAU,EACV,SAAS,EACT,OAAO,EACP,gBAAgB,EAChB,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AACvD,eAAO,MAAM,wBAAwB,0BAA0B,CAAC;AAChE,eAAO,MAAM,8BAA8B,+BAA+B,CAAC;AAC3E,eAAO,MAAM,6BAA6B,8BAA8B,CAAC;AACzE,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAC3D,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAC3D,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AACnE,eAAO,MAAM,2BAA2B,4BAA4B,CAAC"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROPERTY_NAME_BOUNDS_HEIGHT = exports.PROPERTY_NAME_BOUNDS_WIDTH = exports.PROPERTY_NAME_BOUNDS_Y = exports.PROPERTY_NAME_BOUNDS_X = exports.PROPERTY_NAME_MPP_Y = exports.PROPERTY_NAME_MPP_X = exports.PROPERTY_NAME_OBJECTIVE_POWER = exports.PROPERTY_NAME_BACKGROUND_COLOR = exports.PROPERTY_NAME_QUICKHASH1 = exports.PROPERTY_NAME_VENDOR = exports.PROPERTY_NAME_COMMENT = exports.OpenSlideUnsupportedFormatError = exports.OpenSlideError = exports.DeepZoomGenerator = exports.Slide = exports.OpenSlide = void 0;
4
+ // Core classes
5
+ var openslide_js_1 = require("./openslide.js");
6
+ Object.defineProperty(exports, "OpenSlide", { enumerable: true, get: function () { return openslide_js_1.OpenSlide; } });
7
+ var slide_js_1 = require("./slide.js");
8
+ Object.defineProperty(exports, "Slide", { enumerable: true, get: function () { return slide_js_1.Slide; } });
9
+ var deep_zoom_js_1 = require("./deep-zoom.js");
10
+ Object.defineProperty(exports, "DeepZoomGenerator", { enumerable: true, get: function () { return deep_zoom_js_1.DeepZoomGenerator; } });
11
+ // Errors
12
+ var errors_js_1 = require("./errors.js");
13
+ Object.defineProperty(exports, "OpenSlideError", { enumerable: true, get: function () { return errors_js_1.OpenSlideError; } });
14
+ Object.defineProperty(exports, "OpenSlideUnsupportedFormatError", { enumerable: true, get: function () { return errors_js_1.OpenSlideUnsupportedFormatError; } });
15
+ // Property name constants (matching OpenSlide C library)
16
+ exports.PROPERTY_NAME_COMMENT = 'openslide.comment';
17
+ exports.PROPERTY_NAME_VENDOR = 'openslide.vendor';
18
+ exports.PROPERTY_NAME_QUICKHASH1 = 'openslide.quickhash-1';
19
+ exports.PROPERTY_NAME_BACKGROUND_COLOR = 'openslide.background-color';
20
+ exports.PROPERTY_NAME_OBJECTIVE_POWER = 'openslide.objective-power';
21
+ exports.PROPERTY_NAME_MPP_X = 'openslide.mpp-x';
22
+ exports.PROPERTY_NAME_MPP_Y = 'openslide.mpp-y';
23
+ exports.PROPERTY_NAME_BOUNDS_X = 'openslide.bounds-x';
24
+ exports.PROPERTY_NAME_BOUNDS_Y = 'openslide.bounds-y';
25
+ exports.PROPERTY_NAME_BOUNDS_WIDTH = 'openslide.bounds-width';
26
+ exports.PROPERTY_NAME_BOUNDS_HEIGHT = 'openslide.bounds-height';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,eAAe;AACf,+CAA2C;AAAlC,yGAAA,SAAS,OAAA;AAClB,uCAAmC;AAA1B,iGAAA,KAAK,OAAA;AACd,+CAAmD;AAA1C,iHAAA,iBAAiB,OAAA;AAG1B,SAAS;AACT,yCAA8E;AAArE,2GAAA,cAAc,OAAA;AAAE,4HAAA,+BAA+B,OAAA;AAYxD,yDAAyD;AAC5C,QAAA,qBAAqB,GAAG,mBAAmB,CAAC;AAC5C,QAAA,oBAAoB,GAAG,kBAAkB,CAAC;AAC1C,QAAA,wBAAwB,GAAG,uBAAuB,CAAC;AACnD,QAAA,8BAA8B,GAAG,4BAA4B,CAAC;AAC9D,QAAA,6BAA6B,GAAG,2BAA2B,CAAC;AAC5D,QAAA,mBAAmB,GAAG,iBAAiB,CAAC;AACxC,QAAA,mBAAmB,GAAG,iBAAiB,CAAC;AACxC,QAAA,sBAAsB,GAAG,oBAAoB,CAAC;AAC9C,QAAA,sBAAsB,GAAG,oBAAoB,CAAC;AAC9C,QAAA,0BAA0B,GAAG,wBAAwB,CAAC;AACtD,QAAA,2BAA2B,GAAG,yBAAyB,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * openslide.ts
3
+ *
4
+ * Main entry point for the library. Manages a pool of Web Workers,
5
+ * each running an independent WASM instance. Distributes work
6
+ * across workers for parallel tile reads.
7
+ */
8
+ import type { OpenSlideOptions, SlideSource } from './types.js';
9
+ import { Slide } from './slide.js';
10
+ export declare class OpenSlide {
11
+ private workers;
12
+ private nextId;
13
+ private terminated;
14
+ private constructor();
15
+ /**
16
+ * Create and initialize an OpenSlide instance with a worker pool.
17
+ *
18
+ * @param options.workerCount - Number of workers (default: hardwareConcurrency or 4).
19
+ * @param options.wasmUrl - Custom URL to the WASM module JS loader.
20
+ */
21
+ static initialize(options?: OpenSlideOptions): Promise<OpenSlide>;
22
+ /**
23
+ * Open a whole-slide image.
24
+ *
25
+ * Accepts:
26
+ * - A single File (dropped or from file input)
27
+ * - An array of Files (for multi-file formats like MIRAX)
28
+ * - An array of VirtualFile objects (files with relative paths)
29
+ * - A URL object or string URL (fetched via HTTP range requests)
30
+ */
31
+ open(source: SlideSource): Promise<Slide>;
32
+ /**
33
+ * Detect the vendor of a slide file without fully opening it.
34
+ * Returns the vendor string (e.g., "aperio", "hamamatsu") or null.
35
+ */
36
+ detectVendor(source: SlideSource): Promise<string | null>;
37
+ /** Get the OpenSlide library version string. */
38
+ getVersion(): Promise<string>;
39
+ /** Terminate all workers. The instance cannot be used after this. */
40
+ terminate(): void;
41
+ private leastBusy;
42
+ private sendTo;
43
+ private createSendFn;
44
+ private generateMountId;
45
+ private ensureAlive;
46
+ }
47
+ //# sourceMappingURL=openslide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openslide.d.ts","sourceRoot":"","sources":["../../src/openslide.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EAIZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAcnC,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO;IAEP;;;;;OAKG;WACU,UAAU,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC;IAmDvE;;;;;;;;OAQG;IACG,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC;IAyC/C;;;OAGG;IACG,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAsB/D,gDAAgD;IAC1C,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAKnC,qEAAqE;IACrE,SAAS,IAAI,IAAI;IAcjB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,WAAW;CAKpB"}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ /**
3
+ * openslide.ts
4
+ *
5
+ * Main entry point for the library. Manages a pool of Web Workers,
6
+ * each running an independent WASM instance. Distributes work
7
+ * across workers for parallel tile reads.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.OpenSlide = void 0;
11
+ const errors_js_1 = require("./errors.js");
12
+ const slide_js_1 = require("./slide.js");
13
+ class OpenSlide {
14
+ workers = [];
15
+ nextId = 1;
16
+ terminated = false;
17
+ constructor() { }
18
+ /**
19
+ * Create and initialize an OpenSlide instance with a worker pool.
20
+ *
21
+ * @param options.workerCount - Number of workers (default: hardwareConcurrency or 4).
22
+ * @param options.wasmUrl - Custom URL to the WASM module JS loader.
23
+ */
24
+ static async initialize(options) {
25
+ const instance = new OpenSlide();
26
+ const count = options?.workerCount ?? (typeof navigator !== 'undefined' ? navigator.hardwareConcurrency : 4) ?? 4;
27
+ let workerUrl;
28
+ if (options?.workerUrl) {
29
+ workerUrl = new URL(options.workerUrl);
30
+ }
31
+ else {
32
+ // @ts-ignore - import.meta.url is valid in ESM; CJS users must pass workerUrl
33
+ workerUrl = new URL('./worker.js', import.meta.url);
34
+ }
35
+ const initPromises = [];
36
+ for (let i = 0; i < count; i++) {
37
+ const worker = new Worker(workerUrl, { type: 'module' });
38
+ const managed = { worker, pending: new Map(), activeTasks: 0 };
39
+ worker.onmessage = (e) => {
40
+ const resp = e.data;
41
+ const req = managed.pending.get(resp.id);
42
+ if (!req)
43
+ return;
44
+ managed.pending.delete(resp.id);
45
+ managed.activeTasks--;
46
+ if (resp.ok) {
47
+ req.resolve(resp.result);
48
+ }
49
+ else {
50
+ req.reject(new errors_js_1.OpenSlideError(resp.error));
51
+ }
52
+ };
53
+ worker.onerror = (e) => {
54
+ // Reject all pending requests on this worker
55
+ for (const [, req] of managed.pending) {
56
+ req.reject(new errors_js_1.OpenSlideError(`Worker error: ${e.message}`));
57
+ }
58
+ managed.pending.clear();
59
+ managed.activeTasks = 0;
60
+ };
61
+ instance.workers.push(managed);
62
+ initPromises.push(instance.sendTo(managed, { cmd: 'init', wasmUrl: options?.wasmUrl }));
63
+ }
64
+ await Promise.all(initPromises);
65
+ return instance;
66
+ }
67
+ /**
68
+ * Open a whole-slide image.
69
+ *
70
+ * Accepts:
71
+ * - A single File (dropped or from file input)
72
+ * - An array of Files (for multi-file formats like MIRAX)
73
+ * - An array of VirtualFile objects (files with relative paths)
74
+ * - A URL object or string URL (fetched via HTTP range requests)
75
+ */
76
+ async open(source) {
77
+ this.ensureAlive();
78
+ const worker = this.leastBusy();
79
+ const send = this.createSendFn(worker);
80
+ const mountId = this.generateMountId();
81
+ let slidePath;
82
+ if (typeof source === 'string') {
83
+ slidePath = await send({ cmd: 'mountUrl', url: source, mountId });
84
+ }
85
+ else if (source instanceof URL) {
86
+ slidePath = await send({ cmd: 'mountUrl', url: source.href, mountId });
87
+ }
88
+ else if (source instanceof File) {
89
+ slidePath = await send({ cmd: 'mountFile', files: [source], mountId });
90
+ }
91
+ else if (Array.isArray(source)) {
92
+ if (source.length > 0 && 'file' in source[0]) {
93
+ // VirtualFile[] — multi-file format with directory structure
94
+ const entries = source;
95
+ // Find the index file (the .mrxs, .vms, etc.)
96
+ const indexEntry = entries.find(e => !e.path.includes('/')) ?? entries[0];
97
+ slidePath = await send({ cmd: 'mountDir', entries, indexFile: indexEntry.path, mountId });
98
+ }
99
+ else {
100
+ // File[] — flat list of files
101
+ slidePath = await send({ cmd: 'mountFile', files: source, mountId });
102
+ }
103
+ }
104
+ else {
105
+ throw new errors_js_1.OpenSlideError('Invalid slide source');
106
+ }
107
+ const handle = await send({ cmd: 'open', mountId: slidePath });
108
+ const info = await send({ cmd: 'getSlideInfo', handle });
109
+ // Reconstruct the Map from the serialized data (postMessage turns Map into plain object)
110
+ const props = info.properties instanceof Map
111
+ ? info.properties
112
+ : new Map(Object.entries(info.properties));
113
+ const normalizedInfo = { ...info, properties: props };
114
+ return new slide_js_1.Slide(send, handle, mountId, normalizedInfo);
115
+ }
116
+ /**
117
+ * Detect the vendor of a slide file without fully opening it.
118
+ * Returns the vendor string (e.g., "aperio", "hamamatsu") or null.
119
+ */
120
+ async detectVendor(source) {
121
+ this.ensureAlive();
122
+ const worker = this.leastBusy();
123
+ const send = this.createSendFn(worker);
124
+ const mountId = this.generateMountId();
125
+ let slidePath;
126
+ if (typeof source === 'string') {
127
+ slidePath = await send({ cmd: 'mountUrl', url: source, mountId });
128
+ }
129
+ else if (source instanceof URL) {
130
+ slidePath = await send({ cmd: 'mountUrl', url: source.href, mountId });
131
+ }
132
+ else if (source instanceof File) {
133
+ slidePath = await send({ cmd: 'mountFile', files: [source], mountId });
134
+ }
135
+ else {
136
+ throw new errors_js_1.OpenSlideError('detectVendor requires a single file or URL');
137
+ }
138
+ const vendor = await send({ cmd: 'detectVendor', mountId: slidePath });
139
+ await send({ cmd: 'unmount', mountId });
140
+ return vendor;
141
+ }
142
+ /** Get the OpenSlide library version string. */
143
+ async getVersion() {
144
+ this.ensureAlive();
145
+ return await this.sendTo(this.workers[0], { cmd: 'getVersion' });
146
+ }
147
+ /** Terminate all workers. The instance cannot be used after this. */
148
+ terminate() {
149
+ this.terminated = true;
150
+ for (const { worker, pending } of this.workers) {
151
+ for (const [, req] of pending) {
152
+ req.reject(new errors_js_1.OpenSlideError('OpenSlide terminated'));
153
+ }
154
+ pending.clear();
155
+ worker.terminate();
156
+ }
157
+ this.workers = [];
158
+ }
159
+ // --- Internal ---
160
+ leastBusy() {
161
+ let best = this.workers[0];
162
+ for (let i = 1; i < this.workers.length; i++) {
163
+ if (this.workers[i].activeTasks < best.activeTasks) {
164
+ best = this.workers[i];
165
+ }
166
+ }
167
+ return best;
168
+ }
169
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
170
+ sendTo(managed, cmd) {
171
+ const id = this.nextId++;
172
+ return new Promise((resolve, reject) => {
173
+ managed.pending.set(id, { resolve, reject });
174
+ managed.activeTasks++;
175
+ managed.worker.postMessage({ ...cmd, id });
176
+ });
177
+ }
178
+ createSendFn(managed) {
179
+ return (cmd) => this.sendTo(managed, cmd);
180
+ }
181
+ generateMountId() {
182
+ return `m${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
183
+ }
184
+ ensureAlive() {
185
+ if (this.terminated) {
186
+ throw new errors_js_1.OpenSlideError('OpenSlide has been terminated');
187
+ }
188
+ }
189
+ }
190
+ exports.OpenSlide = OpenSlide;
191
+ //# sourceMappingURL=openslide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openslide.js","sourceRoot":"","sources":["../../src/openslide.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * slide.ts
3
+ *
4
+ * Represents an opened whole-slide image. Created by OpenSlide.open().
5
+ * Metadata properties are synchronous (eagerly loaded), while pixel
6
+ * operations are async (delegated to a worker).
7
+ */
8
+ import type { Dimensions, SlideInfo } from './types.js';
9
+ /** Function type for sending a command to a worker and awaiting the response. */
10
+ export type SendCommand = (cmd: Record<string, any>) => Promise<unknown>;
11
+ export declare class Slide {
12
+ /** @internal */ private _send;
13
+ /** @internal */ private _handle;
14
+ /** @internal */ private _mountId;
15
+ /** @internal */ private _info;
16
+ /** @internal */ private _closed;
17
+ /** @internal */
18
+ constructor(send: SendCommand, handle: number, mountId: string, info: SlideInfo);
19
+ /** Number of pyramid levels in the slide. */
20
+ get levelCount(): number;
21
+ /** Dimensions of level 0 (full resolution). */
22
+ get dimensions(): Dimensions;
23
+ /** Dimensions of each pyramid level. */
24
+ get levelDimensions(): readonly Dimensions[];
25
+ /** Downsample factor for each pyramid level. */
26
+ get levelDownsamples(): readonly number[];
27
+ /** Slide metadata properties (vendor, MPP, objective power, etc.). */
28
+ get properties(): ReadonlyMap<string, string>;
29
+ /** Names of associated images (e.g., "label", "thumbnail", "macro"). */
30
+ get associatedImageNames(): readonly string[];
31
+ /**
32
+ * Find the best pyramid level for a given downsample factor.
33
+ * Returns the level index whose downsample is closest to (but not
34
+ * exceeding) the requested factor.
35
+ */
36
+ getBestLevelForDownsample(downsample: number): number;
37
+ /**
38
+ * Read a region of pixel data from the slide.
39
+ *
40
+ * @param x - Top-left x coordinate in level-0 reference frame.
41
+ * @param y - Top-left y coordinate in level-0 reference frame.
42
+ * @param level - Pyramid level to read from.
43
+ * @param width - Width in pixels at the target level.
44
+ * @param height - Height in pixels at the target level.
45
+ * @returns ImageData containing RGBA pixel data.
46
+ */
47
+ readRegion(x: number, y: number, level: number, width: number, height: number): Promise<ImageData>;
48
+ /**
49
+ * Read an associated image (e.g., slide label or macro image).
50
+ *
51
+ * @param name - Name of the associated image.
52
+ * @returns ImageData containing RGBA pixel data.
53
+ */
54
+ readAssociatedImage(name: string): Promise<ImageData>;
55
+ /**
56
+ * Get the dimensions of an associated image.
57
+ */
58
+ getAssociatedImageDimensions(name: string): Promise<Dimensions>;
59
+ /**
60
+ * Read the ICC color profile embedded in the slide, if any.
61
+ * @returns Raw ICC profile bytes, or null if none.
62
+ */
63
+ getIccProfile(): Promise<ArrayBuffer | null>;
64
+ /** Close the slide and release WASM resources. */
65
+ close(): Promise<void>;
66
+ /** Support for `await using slide = ...` (explicit resource management). */
67
+ [Symbol.asyncDispose](): Promise<void>;
68
+ private ensureOpen;
69
+ }
70
+ //# sourceMappingURL=slide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slide.d.ts","sourceRoot":"","sources":["../../src/slide.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGxD,iFAAiF;AAEjF,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEzE,qBAAa,KAAK;IAChB,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAc;IAC5C,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAS;IACzC,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAS;IAC1C,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAY;IAC1C,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAS;IAEzC,gBAAgB;gBACJ,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS;IAO/E,6CAA6C;IAC7C,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,+CAA+C;IAC/C,IAAI,UAAU,IAAI,UAAU,CAE3B;IAED,wCAAwC;IACxC,IAAI,eAAe,IAAI,SAAS,UAAU,EAAE,CAE3C;IAED,gDAAgD;IAChD,IAAI,gBAAgB,IAAI,SAAS,MAAM,EAAE,CAExC;IAED,sEAAsE;IACtE,IAAI,UAAU,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAE5C;IAED,wEAAwE;IACxE,IAAI,oBAAoB,IAAI,SAAS,MAAM,EAAE,CAE5C;IAED;;;;OAIG;IACH,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAOrD;;;;;;;;;OASG;IACG,UAAU,CACd,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,CAAC;IAarB;;;;;OAKG;IACG,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAY3D;;OAEG;IACG,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IASrE;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAQlD,kDAAkD;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,4EAA4E;IACtE,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5C,OAAO,CAAC,UAAU;CAKnB"}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ /**
3
+ * slide.ts
4
+ *
5
+ * Represents an opened whole-slide image. Created by OpenSlide.open().
6
+ * Metadata properties are synchronous (eagerly loaded), while pixel
7
+ * operations are async (delegated to a worker).
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.Slide = void 0;
11
+ const errors_js_1 = require("./errors.js");
12
+ class Slide {
13
+ /** @internal */ _send;
14
+ /** @internal */ _handle;
15
+ /** @internal */ _mountId;
16
+ /** @internal */ _info;
17
+ /** @internal */ _closed = false;
18
+ /** @internal */
19
+ constructor(send, handle, mountId, info) {
20
+ this._send = send;
21
+ this._handle = handle;
22
+ this._mountId = mountId;
23
+ this._info = info;
24
+ }
25
+ /** Number of pyramid levels in the slide. */
26
+ get levelCount() {
27
+ return this._info.levelCount;
28
+ }
29
+ /** Dimensions of level 0 (full resolution). */
30
+ get dimensions() {
31
+ return this._info.levelDimensions[0];
32
+ }
33
+ /** Dimensions of each pyramid level. */
34
+ get levelDimensions() {
35
+ return this._info.levelDimensions;
36
+ }
37
+ /** Downsample factor for each pyramid level. */
38
+ get levelDownsamples() {
39
+ return this._info.levelDownsamples;
40
+ }
41
+ /** Slide metadata properties (vendor, MPP, objective power, etc.). */
42
+ get properties() {
43
+ return this._info.properties;
44
+ }
45
+ /** Names of associated images (e.g., "label", "thumbnail", "macro"). */
46
+ get associatedImageNames() {
47
+ return this._info.associatedImageNames;
48
+ }
49
+ /**
50
+ * Find the best pyramid level for a given downsample factor.
51
+ * Returns the level index whose downsample is closest to (but not
52
+ * exceeding) the requested factor.
53
+ */
54
+ getBestLevelForDownsample(downsample) {
55
+ for (let i = this._info.levelDownsamples.length - 1; i >= 0; i--) {
56
+ if (this._info.levelDownsamples[i] <= downsample)
57
+ return i;
58
+ }
59
+ return 0;
60
+ }
61
+ /**
62
+ * Read a region of pixel data from the slide.
63
+ *
64
+ * @param x - Top-left x coordinate in level-0 reference frame.
65
+ * @param y - Top-left y coordinate in level-0 reference frame.
66
+ * @param level - Pyramid level to read from.
67
+ * @param width - Width in pixels at the target level.
68
+ * @param height - Height in pixels at the target level.
69
+ * @returns ImageData containing RGBA pixel data.
70
+ */
71
+ async readRegion(x, y, level, width, height) {
72
+ this.ensureOpen();
73
+ const buffer = await this._send({
74
+ cmd: 'readRegion',
75
+ handle: this._handle,
76
+ x, y, level,
77
+ w: width, h: height,
78
+ });
79
+ const data = new Uint8ClampedArray(buffer);
80
+ return new ImageData(data, width, height);
81
+ }
82
+ /**
83
+ * Read an associated image (e.g., slide label or macro image).
84
+ *
85
+ * @param name - Name of the associated image.
86
+ * @returns ImageData containing RGBA pixel data.
87
+ */
88
+ async readAssociatedImage(name) {
89
+ this.ensureOpen();
90
+ const result = await this._send({
91
+ cmd: 'readAssociatedImage',
92
+ handle: this._handle,
93
+ name,
94
+ });
95
+ const data = new Uint8ClampedArray(result.buffer);
96
+ return new ImageData(data, result.width, result.height);
97
+ }
98
+ /**
99
+ * Get the dimensions of an associated image.
100
+ */
101
+ async getAssociatedImageDimensions(name) {
102
+ this.ensureOpen();
103
+ return await this._send({
104
+ cmd: 'getAssociatedImageDimensions',
105
+ handle: this._handle,
106
+ name,
107
+ });
108
+ }
109
+ /**
110
+ * Read the ICC color profile embedded in the slide, if any.
111
+ * @returns Raw ICC profile bytes, or null if none.
112
+ */
113
+ async getIccProfile() {
114
+ this.ensureOpen();
115
+ return await this._send({
116
+ cmd: 'getIccProfile',
117
+ handle: this._handle,
118
+ });
119
+ }
120
+ /** Close the slide and release WASM resources. */
121
+ async close() {
122
+ if (this._closed)
123
+ return;
124
+ this._closed = true;
125
+ await this._send({ cmd: 'close', handle: this._handle });
126
+ await this._send({ cmd: 'unmount', mountId: this._mountId });
127
+ }
128
+ /** Support for `await using slide = ...` (explicit resource management). */
129
+ async [Symbol.asyncDispose]() {
130
+ await this.close();
131
+ }
132
+ ensureOpen() {
133
+ if (this._closed) {
134
+ throw new errors_js_1.OpenSlideError('Slide has been closed');
135
+ }
136
+ }
137
+ }
138
+ exports.Slide = Slide;
139
+ //# sourceMappingURL=slide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slide.js","sourceRoot":"","sources":["../../src/slide.ts"],"names":[],"mappings":"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"}