@fideus-labs/fidnii 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/LICENSE.txt +9 -0
- package/README.md +180 -0
- package/dist/BufferManager.d.ts +86 -0
- package/dist/BufferManager.d.ts.map +1 -0
- package/dist/BufferManager.js +146 -0
- package/dist/BufferManager.js.map +1 -0
- package/dist/ClipPlanes.d.ts +180 -0
- package/dist/ClipPlanes.d.ts.map +1 -0
- package/dist/ClipPlanes.js +513 -0
- package/dist/ClipPlanes.js.map +1 -0
- package/dist/OMEZarrNVImage.d.ts +545 -0
- package/dist/OMEZarrNVImage.d.ts.map +1 -0
- package/dist/OMEZarrNVImage.js +1799 -0
- package/dist/OMEZarrNVImage.js.map +1 -0
- package/dist/RegionCoalescer.d.ts +75 -0
- package/dist/RegionCoalescer.d.ts.map +1 -0
- package/dist/RegionCoalescer.js +151 -0
- package/dist/RegionCoalescer.js.map +1 -0
- package/dist/ResolutionSelector.d.ts +88 -0
- package/dist/ResolutionSelector.d.ts.map +1 -0
- package/dist/ResolutionSelector.js +224 -0
- package/dist/ResolutionSelector.js.map +1 -0
- package/dist/ViewportBounds.d.ts +50 -0
- package/dist/ViewportBounds.d.ts.map +1 -0
- package/dist/ViewportBounds.js +325 -0
- package/dist/ViewportBounds.js.map +1 -0
- package/dist/events.d.ts +122 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +12 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +273 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +126 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/affine.d.ts +72 -0
- package/dist/utils/affine.d.ts.map +1 -0
- package/dist/utils/affine.js +173 -0
- package/dist/utils/affine.js.map +1 -0
- package/dist/utils/coordinates.d.ts +80 -0
- package/dist/utils/coordinates.d.ts.map +1 -0
- package/dist/utils/coordinates.js +207 -0
- package/dist/utils/coordinates.js.map +1 -0
- package/package.json +61 -0
- package/src/BufferManager.ts +176 -0
- package/src/ClipPlanes.ts +640 -0
- package/src/OMEZarrNVImage.ts +2286 -0
- package/src/RegionCoalescer.ts +217 -0
- package/src/ResolutionSelector.ts +325 -0
- package/src/ViewportBounds.ts +369 -0
- package/src/events.ts +146 -0
- package/src/index.ts +153 -0
- package/src/types.ts +429 -0
- package/src/utils/affine.ts +218 -0
- package/src/utils/coordinates.ts +271 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright (c) Fideus Labs LLC
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { TypedArray, TypedArrayConstructor, ZarrDtype } from "./types.js";
|
|
5
|
+
import { getBytesPerPixel, getTypedArrayConstructor } from "./types.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Manages a dynamically-sized pixel buffer for volume data.
|
|
9
|
+
*
|
|
10
|
+
* The buffer is resized to match the fetched data dimensions exactly.
|
|
11
|
+
* Memory is reused when possible to avoid unnecessary allocations.
|
|
12
|
+
*
|
|
13
|
+
* Memory reuse strategy:
|
|
14
|
+
* - Reuse buffer if newSize <= currentCapacity
|
|
15
|
+
* - Reallocate if newSize > currentCapacity OR newSize < 25% of currentCapacity
|
|
16
|
+
*/
|
|
17
|
+
export class BufferManager {
|
|
18
|
+
private buffer: ArrayBuffer;
|
|
19
|
+
private currentDimensions: [number, number, number];
|
|
20
|
+
private readonly maxPixels: number;
|
|
21
|
+
private readonly TypedArrayCtor: TypedArrayConstructor;
|
|
22
|
+
private readonly bytesPerPixel: number;
|
|
23
|
+
private readonly dtype: ZarrDtype;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create a new BufferManager.
|
|
27
|
+
*
|
|
28
|
+
* @param maxPixels - Maximum number of pixels allowed (budget)
|
|
29
|
+
* @param dtype - Data type for the buffer
|
|
30
|
+
*/
|
|
31
|
+
constructor(maxPixels: number, dtype: ZarrDtype) {
|
|
32
|
+
this.maxPixels = maxPixels;
|
|
33
|
+
this.dtype = dtype;
|
|
34
|
+
this.TypedArrayCtor = getTypedArrayConstructor(dtype);
|
|
35
|
+
this.bytesPerPixel = getBytesPerPixel(dtype);
|
|
36
|
+
|
|
37
|
+
// Initialize with empty buffer - will be allocated on first resize
|
|
38
|
+
this.currentDimensions = [0, 0, 0];
|
|
39
|
+
this.buffer = new ArrayBuffer(0);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Resize the buffer to fit the given dimensions.
|
|
44
|
+
*
|
|
45
|
+
* Reuses existing buffer if large enough, otherwise allocates new buffer.
|
|
46
|
+
* Will also reallocate if the buffer is significantly oversized (< 25% utilization).
|
|
47
|
+
*
|
|
48
|
+
* If dimensions exceed maxPixels, a warning is logged but the buffer is still
|
|
49
|
+
* allocated. This handles the case where even the lowest resolution exceeds the
|
|
50
|
+
* pixel budget - we still want to load something rather than failing.
|
|
51
|
+
*
|
|
52
|
+
* @param dimensions - New dimensions [z, y, x]
|
|
53
|
+
* @returns TypedArray view over the (possibly new) buffer
|
|
54
|
+
*/
|
|
55
|
+
resize(dimensions: [number, number, number]): TypedArray {
|
|
56
|
+
const requiredPixels = dimensions[0] * dimensions[1] * dimensions[2];
|
|
57
|
+
|
|
58
|
+
if (requiredPixels > this.maxPixels) {
|
|
59
|
+
console.warn(
|
|
60
|
+
`[fidnii] BufferManager: Requested dimensions [${
|
|
61
|
+
dimensions.join(", ")
|
|
62
|
+
}] = ${requiredPixels} pixels exceeds maxPixels (${this.maxPixels}). ` +
|
|
63
|
+
`Proceeding anyway (likely at lowest resolution).`,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const currentCapacityPixels = this.buffer.byteLength / this.bytesPerPixel;
|
|
68
|
+
const utilizationRatio = currentCapacityPixels > 0
|
|
69
|
+
? requiredPixels / currentCapacityPixels
|
|
70
|
+
: 0;
|
|
71
|
+
|
|
72
|
+
const needsReallocation = requiredPixels > currentCapacityPixels ||
|
|
73
|
+
utilizationRatio < 0.25;
|
|
74
|
+
|
|
75
|
+
if (needsReallocation) {
|
|
76
|
+
// Allocate new buffer
|
|
77
|
+
const newByteLength = requiredPixels * this.bytesPerPixel;
|
|
78
|
+
this.buffer = new ArrayBuffer(newByteLength);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.currentDimensions = [...dimensions];
|
|
82
|
+
return this.getTypedArray();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get the underlying ArrayBuffer.
|
|
87
|
+
*/
|
|
88
|
+
getBuffer(): ArrayBuffer {
|
|
89
|
+
return this.buffer;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get a typed array view over the current buffer region.
|
|
94
|
+
*
|
|
95
|
+
* The view is sized to match currentDimensions, not the full buffer capacity.
|
|
96
|
+
*/
|
|
97
|
+
getTypedArray(): TypedArray {
|
|
98
|
+
const pixelCount = this.currentDimensions[0] *
|
|
99
|
+
this.currentDimensions[1] *
|
|
100
|
+
this.currentDimensions[2];
|
|
101
|
+
return new this.TypedArrayCtor(this.buffer, 0, pixelCount);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the current buffer dimensions [z, y, x].
|
|
106
|
+
*/
|
|
107
|
+
getDimensions(): [number, number, number] {
|
|
108
|
+
return [...this.currentDimensions];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get the total number of pixels in the current buffer region.
|
|
113
|
+
*/
|
|
114
|
+
getPixelCount(): number {
|
|
115
|
+
return (
|
|
116
|
+
this.currentDimensions[0] *
|
|
117
|
+
this.currentDimensions[1] *
|
|
118
|
+
this.currentDimensions[2]
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get the buffer capacity in pixels.
|
|
124
|
+
*/
|
|
125
|
+
getCapacity(): number {
|
|
126
|
+
return this.buffer.byteLength / this.bytesPerPixel;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get the bytes per pixel.
|
|
131
|
+
*/
|
|
132
|
+
getBytesPerPixel(): number {
|
|
133
|
+
return this.bytesPerPixel;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get the data type.
|
|
138
|
+
*/
|
|
139
|
+
getDtype(): ZarrDtype {
|
|
140
|
+
return this.dtype;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get the maximum pixels budget.
|
|
145
|
+
*/
|
|
146
|
+
getMaxPixels(): number {
|
|
147
|
+
return this.maxPixels;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Clear the current buffer region to zeros.
|
|
152
|
+
*/
|
|
153
|
+
clear(): void {
|
|
154
|
+
const pixelCount = this.getPixelCount();
|
|
155
|
+
if (pixelCount > 0) {
|
|
156
|
+
const view = new Uint8Array(
|
|
157
|
+
this.buffer,
|
|
158
|
+
0,
|
|
159
|
+
pixelCount * this.bytesPerPixel,
|
|
160
|
+
);
|
|
161
|
+
view.fill(0);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Check if the buffer can accommodate the given dimensions without reallocation.
|
|
167
|
+
*
|
|
168
|
+
* @param dimensions - Dimensions to check [z, y, x]
|
|
169
|
+
* @returns True if current buffer can fit the dimensions
|
|
170
|
+
*/
|
|
171
|
+
canAccommodate(dimensions: [number, number, number]): boolean {
|
|
172
|
+
const requiredPixels = dimensions[0] * dimensions[1] * dimensions[2];
|
|
173
|
+
const currentCapacityPixels = this.buffer.byteLength / this.bytesPerPixel;
|
|
174
|
+
return requiredPixels <= currentCapacityPixels;
|
|
175
|
+
}
|
|
176
|
+
}
|