@fideus-labs/fiff 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/dist/chunk-reader.d.ts +25 -0
- package/dist/chunk-reader.d.ts.map +1 -0
- package/dist/chunk-reader.js +71 -0
- package/dist/chunk-reader.js.map +1 -0
- package/dist/dtypes.d.ts +42 -0
- package/dist/dtypes.d.ts.map +1 -0
- package/dist/dtypes.js +122 -0
- package/dist/dtypes.js.map +1 -0
- package/dist/ifd-indexer.d.ts +56 -0
- package/dist/ifd-indexer.d.ts.map +1 -0
- package/dist/ifd-indexer.js +197 -0
- package/dist/ifd-indexer.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata.d.ts +116 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +234 -0
- package/dist/metadata.js.map +1 -0
- package/dist/ome-xml.d.ts +74 -0
- package/dist/ome-xml.d.ts.map +1 -0
- package/dist/ome-xml.js +178 -0
- package/dist/ome-xml.js.map +1 -0
- package/dist/tiff-store.d.ts +95 -0
- package/dist/tiff-store.d.ts.map +1 -0
- package/dist/tiff-store.js +263 -0
- package/dist/tiff-store.js.map +1 -0
- package/dist/utils.d.ts +64 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +116 -0
- package/dist/utils.js.map +1 -0
- package/package.json +51 -0
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026-present Fideus Labs LLC <info@fideus.io>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chunk reader: reads pixel data from a GeoTIFFImage for a specific chunk,
|
|
3
|
+
* returning raw bytes suitable for a Zarr store response.
|
|
4
|
+
*/
|
|
5
|
+
import type { GeoTIFFImage } from "geotiff";
|
|
6
|
+
import type { ZarrDataType } from "./dtypes.js";
|
|
7
|
+
import type { PlaneSelection } from "./ifd-indexer.js";
|
|
8
|
+
/**
|
|
9
|
+
* Read a single chunk of data from a TIFF image.
|
|
10
|
+
*
|
|
11
|
+
* @param getImage - Function to resolve (selection, level) to a GeoTIFFImage.
|
|
12
|
+
* @param sel - The plane selection (c, z, t).
|
|
13
|
+
* @param level - The resolution level.
|
|
14
|
+
* @param chunkY - The y chunk index within the image.
|
|
15
|
+
* @param chunkX - The x chunk index within the image.
|
|
16
|
+
* @param chunkHeight - Chunk size in pixels (y dimension).
|
|
17
|
+
* @param chunkWidth - Chunk size in pixels (x dimension).
|
|
18
|
+
* @param imageWidth - Total image width at this level.
|
|
19
|
+
* @param imageHeight - Total image height at this level.
|
|
20
|
+
* @param dtype - The Zarr data type of the output.
|
|
21
|
+
* @param signal - Optional abort signal.
|
|
22
|
+
* @returns Raw bytes for this chunk, zero-padded for edge chunks.
|
|
23
|
+
*/
|
|
24
|
+
export declare function readChunk(getImage: (sel: PlaneSelection, level: number) => Promise<GeoTIFFImage>, sel: PlaneSelection, level: number, chunkY: number, chunkX: number, chunkHeight: number, chunkWidth: number, imageWidth: number, imageHeight: number, dtype: ZarrDataType, signal?: AbortSignal): Promise<Uint8Array>;
|
|
25
|
+
//# sourceMappingURL=chunk-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-reader.d.ts","sourceRoot":"","sources":["../src/chunk-reader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,CACR,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,KACV,OAAO,CAAC,YAAY,CAAC,EAC1B,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,EACnB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoDrB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chunk reader: reads pixel data from a GeoTIFFImage for a specific chunk,
|
|
3
|
+
* returning raw bytes suitable for a Zarr store response.
|
|
4
|
+
*/
|
|
5
|
+
import { bytesPerElement } from "./dtypes.js";
|
|
6
|
+
import { computePixelWindow, encodeChunkBytes } from "./utils.js";
|
|
7
|
+
/**
|
|
8
|
+
* Read a single chunk of data from a TIFF image.
|
|
9
|
+
*
|
|
10
|
+
* @param getImage - Function to resolve (selection, level) to a GeoTIFFImage.
|
|
11
|
+
* @param sel - The plane selection (c, z, t).
|
|
12
|
+
* @param level - The resolution level.
|
|
13
|
+
* @param chunkY - The y chunk index within the image.
|
|
14
|
+
* @param chunkX - The x chunk index within the image.
|
|
15
|
+
* @param chunkHeight - Chunk size in pixels (y dimension).
|
|
16
|
+
* @param chunkWidth - Chunk size in pixels (x dimension).
|
|
17
|
+
* @param imageWidth - Total image width at this level.
|
|
18
|
+
* @param imageHeight - Total image height at this level.
|
|
19
|
+
* @param dtype - The Zarr data type of the output.
|
|
20
|
+
* @param signal - Optional abort signal.
|
|
21
|
+
* @returns Raw bytes for this chunk, zero-padded for edge chunks.
|
|
22
|
+
*/
|
|
23
|
+
export async function readChunk(getImage, sel, level, chunkY, chunkX, chunkHeight, chunkWidth, imageWidth, imageHeight, dtype, signal) {
|
|
24
|
+
const [left, top, right, bottom] = computePixelWindow(chunkX, chunkY, chunkWidth, chunkHeight, imageWidth, imageHeight);
|
|
25
|
+
const windowWidth = right - left;
|
|
26
|
+
const windowHeight = bottom - top;
|
|
27
|
+
if (windowWidth <= 0 || windowHeight <= 0) {
|
|
28
|
+
// Chunk is entirely outside the image; return fill value (zeros)
|
|
29
|
+
const bpe = bytesPerElement(dtype);
|
|
30
|
+
return new Uint8Array(chunkWidth * chunkHeight * bpe);
|
|
31
|
+
}
|
|
32
|
+
const image = await getImage(sel, level);
|
|
33
|
+
// Read the pixel data for this window
|
|
34
|
+
// interleave=true gives a single flat TypedArray
|
|
35
|
+
const rasterData = await image.readRasters({
|
|
36
|
+
window: [left, top, right, bottom],
|
|
37
|
+
width: windowWidth,
|
|
38
|
+
height: windowHeight,
|
|
39
|
+
interleave: true,
|
|
40
|
+
samples: [0], // single sample; channel is handled at IFD level
|
|
41
|
+
signal,
|
|
42
|
+
});
|
|
43
|
+
// readRasters with interleave returns a single TypedArray
|
|
44
|
+
const pixelData = rasterData;
|
|
45
|
+
const bpe = bytesPerElement(dtype);
|
|
46
|
+
const expectedElements = chunkWidth * chunkHeight;
|
|
47
|
+
// For edge chunks, we need to properly pad the data.
|
|
48
|
+
// The data from readRasters has shape (windowHeight, windowWidth) but
|
|
49
|
+
// we need it in a buffer of shape (chunkHeight, chunkWidth).
|
|
50
|
+
if (windowWidth < chunkWidth || windowHeight < chunkHeight) {
|
|
51
|
+
return padEdgeChunk(pixelData, windowWidth, windowHeight, chunkWidth, chunkHeight, bpe);
|
|
52
|
+
}
|
|
53
|
+
return encodeChunkBytes(pixelData, expectedElements, bpe);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Pad an edge chunk by copying row-by-row into a full-size buffer.
|
|
57
|
+
* Edge chunks occur at the right and bottom boundaries of the image.
|
|
58
|
+
*/
|
|
59
|
+
function padEdgeChunk(data, srcWidth, srcHeight, dstWidth, dstHeight, bytesPerEl) {
|
|
60
|
+
const output = new Uint8Array(dstWidth * dstHeight * bytesPerEl);
|
|
61
|
+
const src = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
62
|
+
const srcRowBytes = srcWidth * bytesPerEl;
|
|
63
|
+
const dstRowBytes = dstWidth * bytesPerEl;
|
|
64
|
+
for (let row = 0; row < srcHeight; row++) {
|
|
65
|
+
const srcOffset = row * srcRowBytes;
|
|
66
|
+
const dstOffset = row * dstRowBytes;
|
|
67
|
+
output.set(src.subarray(srcOffset, srcOffset + srcRowBytes), dstOffset);
|
|
68
|
+
}
|
|
69
|
+
return output;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=chunk-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-reader.js","sourceRoot":"","sources":["../src/chunk-reader.ts"],"names":[],"mappings":"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"}
|
package/dist/dtypes.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TIFF sample format and bit depth to Zarr v3 data_type mapping.
|
|
3
|
+
*
|
|
4
|
+
* TIFF SampleFormat values:
|
|
5
|
+
* 1 = unsigned integer
|
|
6
|
+
* 2 = signed integer (two's complement)
|
|
7
|
+
* 3 = IEEE floating point
|
|
8
|
+
*
|
|
9
|
+
* Zarr v3 data_type strings: int8, int16, int32, uint8, uint16, uint32,
|
|
10
|
+
* float32, float64, etc.
|
|
11
|
+
*/
|
|
12
|
+
/** Zarr v3 numeric data type strings. */
|
|
13
|
+
export type ZarrDataType = "int8" | "int16" | "int32" | "uint8" | "uint16" | "uint32" | "float32" | "float64";
|
|
14
|
+
/** TIFF SampleFormat tag values. */
|
|
15
|
+
export declare const SAMPLE_FORMAT_UINT = 1;
|
|
16
|
+
export declare const SAMPLE_FORMAT_INT = 2;
|
|
17
|
+
export declare const SAMPLE_FORMAT_FLOAT = 3;
|
|
18
|
+
/**
|
|
19
|
+
* Map TIFF SampleFormat + BitsPerSample to a Zarr v3 data_type string.
|
|
20
|
+
*
|
|
21
|
+
* @param sampleFormat - TIFF SampleFormat tag value (1=uint, 2=int, 3=float).
|
|
22
|
+
* Defaults to 1 (unsigned integer) if not specified.
|
|
23
|
+
* @param bitsPerSample - Bits per sample (8, 16, 32, 64).
|
|
24
|
+
* @returns The corresponding Zarr v3 data_type string.
|
|
25
|
+
* @throws If the combination is unsupported.
|
|
26
|
+
*/
|
|
27
|
+
export declare function tiffDtypeToZarr(sampleFormat: number, bitsPerSample: number): ZarrDataType;
|
|
28
|
+
/**
|
|
29
|
+
* Map an OME-XML pixel Type string to a Zarr v3 data_type string.
|
|
30
|
+
*
|
|
31
|
+
* OME pixel types: int8, int16, int32, uint8, uint16, uint32, float, double
|
|
32
|
+
*/
|
|
33
|
+
export declare function omePixelTypeToZarr(omeType: string): ZarrDataType;
|
|
34
|
+
/** Number of bytes per element for a given Zarr data_type. */
|
|
35
|
+
export declare function bytesPerElement(dtype: ZarrDataType): number;
|
|
36
|
+
/**
|
|
37
|
+
* Get the appropriate TypedArray constructor for a Zarr data_type.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getTypedArrayConstructor(dtype: ZarrDataType): {
|
|
40
|
+
new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=dtypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dtypes.d.ts","sourceRoot":"","sources":["../src/dtypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,yCAAyC;AACzC,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,OAAO,GACP,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,SAAS,CAAC;AAEd,oCAAoC;AACpC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,YAAY,CAyCd;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAiBhE;AAED,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAY3D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,YAAY,GAClB;IACD,KAAK,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAC1D,UAAU,GACV,SAAS,GACT,WAAW,GACX,UAAU,GACV,WAAW,GACX,UAAU,GACV,YAAY,GACZ,YAAY,CAAC;CAClB,CAmBA"}
|
package/dist/dtypes.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TIFF sample format and bit depth to Zarr v3 data_type mapping.
|
|
3
|
+
*
|
|
4
|
+
* TIFF SampleFormat values:
|
|
5
|
+
* 1 = unsigned integer
|
|
6
|
+
* 2 = signed integer (two's complement)
|
|
7
|
+
* 3 = IEEE floating point
|
|
8
|
+
*
|
|
9
|
+
* Zarr v3 data_type strings: int8, int16, int32, uint8, uint16, uint32,
|
|
10
|
+
* float32, float64, etc.
|
|
11
|
+
*/
|
|
12
|
+
/** TIFF SampleFormat tag values. */
|
|
13
|
+
export const SAMPLE_FORMAT_UINT = 1;
|
|
14
|
+
export const SAMPLE_FORMAT_INT = 2;
|
|
15
|
+
export const SAMPLE_FORMAT_FLOAT = 3;
|
|
16
|
+
/**
|
|
17
|
+
* Map TIFF SampleFormat + BitsPerSample to a Zarr v3 data_type string.
|
|
18
|
+
*
|
|
19
|
+
* @param sampleFormat - TIFF SampleFormat tag value (1=uint, 2=int, 3=float).
|
|
20
|
+
* Defaults to 1 (unsigned integer) if not specified.
|
|
21
|
+
* @param bitsPerSample - Bits per sample (8, 16, 32, 64).
|
|
22
|
+
* @returns The corresponding Zarr v3 data_type string.
|
|
23
|
+
* @throws If the combination is unsupported.
|
|
24
|
+
*/
|
|
25
|
+
export function tiffDtypeToZarr(sampleFormat, bitsPerSample) {
|
|
26
|
+
if (sampleFormat === SAMPLE_FORMAT_UINT) {
|
|
27
|
+
switch (bitsPerSample) {
|
|
28
|
+
case 8:
|
|
29
|
+
return "uint8";
|
|
30
|
+
case 16:
|
|
31
|
+
return "uint16";
|
|
32
|
+
case 32:
|
|
33
|
+
return "uint32";
|
|
34
|
+
default:
|
|
35
|
+
throw new Error(`Unsupported unsigned integer bit depth: ${bitsPerSample}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if (sampleFormat === SAMPLE_FORMAT_INT) {
|
|
39
|
+
switch (bitsPerSample) {
|
|
40
|
+
case 8:
|
|
41
|
+
return "int8";
|
|
42
|
+
case 16:
|
|
43
|
+
return "int16";
|
|
44
|
+
case 32:
|
|
45
|
+
return "int32";
|
|
46
|
+
default:
|
|
47
|
+
throw new Error(`Unsupported signed integer bit depth: ${bitsPerSample}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (sampleFormat === SAMPLE_FORMAT_FLOAT) {
|
|
51
|
+
switch (bitsPerSample) {
|
|
52
|
+
case 32:
|
|
53
|
+
return "float32";
|
|
54
|
+
case 64:
|
|
55
|
+
return "float64";
|
|
56
|
+
default:
|
|
57
|
+
throw new Error(`Unsupported floating point bit depth: ${bitsPerSample}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
throw new Error(`Unsupported TIFF SampleFormat: ${sampleFormat}`);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Map an OME-XML pixel Type string to a Zarr v3 data_type string.
|
|
64
|
+
*
|
|
65
|
+
* OME pixel types: int8, int16, int32, uint8, uint16, uint32, float, double
|
|
66
|
+
*/
|
|
67
|
+
export function omePixelTypeToZarr(omeType) {
|
|
68
|
+
const map = {
|
|
69
|
+
int8: "int8",
|
|
70
|
+
int16: "int16",
|
|
71
|
+
int32: "int32",
|
|
72
|
+
uint8: "uint8",
|
|
73
|
+
uint16: "uint16",
|
|
74
|
+
uint32: "uint32",
|
|
75
|
+
float: "float32",
|
|
76
|
+
double: "float64",
|
|
77
|
+
};
|
|
78
|
+
const lower = omeType.toLowerCase();
|
|
79
|
+
const result = map[lower];
|
|
80
|
+
if (!result) {
|
|
81
|
+
throw new Error(`Unsupported OME pixel type: ${omeType}`);
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
/** Number of bytes per element for a given Zarr data_type. */
|
|
86
|
+
export function bytesPerElement(dtype) {
|
|
87
|
+
const map = {
|
|
88
|
+
int8: 1,
|
|
89
|
+
uint8: 1,
|
|
90
|
+
int16: 2,
|
|
91
|
+
uint16: 2,
|
|
92
|
+
int32: 4,
|
|
93
|
+
uint32: 4,
|
|
94
|
+
float32: 4,
|
|
95
|
+
float64: 8,
|
|
96
|
+
};
|
|
97
|
+
return map[dtype];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get the appropriate TypedArray constructor for a Zarr data_type.
|
|
101
|
+
*/
|
|
102
|
+
export function getTypedArrayConstructor(dtype) {
|
|
103
|
+
switch (dtype) {
|
|
104
|
+
case "uint8":
|
|
105
|
+
return Uint8Array;
|
|
106
|
+
case "int8":
|
|
107
|
+
return Int8Array;
|
|
108
|
+
case "uint16":
|
|
109
|
+
return Uint16Array;
|
|
110
|
+
case "int16":
|
|
111
|
+
return Int16Array;
|
|
112
|
+
case "uint32":
|
|
113
|
+
return Uint32Array;
|
|
114
|
+
case "int32":
|
|
115
|
+
return Int32Array;
|
|
116
|
+
case "float32":
|
|
117
|
+
return Float32Array;
|
|
118
|
+
case "float64":
|
|
119
|
+
return Float64Array;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=dtypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dtypes.js","sourceRoot":"","sources":["../src/dtypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAaH,oCAAoC;AACpC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,YAAoB,EACpB,aAAqB;IAErB,IAAI,YAAY,KAAK,kBAAkB,EAAE,CAAC;QACxC,QAAQ,aAAa,EAAE,CAAC;YACtB,KAAK,CAAC;gBACJ,OAAO,OAAO,CAAC;YACjB,KAAK,EAAE;gBACL,OAAO,QAAQ,CAAC;YAClB,KAAK,EAAE;gBACL,OAAO,QAAQ,CAAC;YAClB;gBACE,MAAM,IAAI,KAAK,CACb,2CAA2C,aAAa,EAAE,CAC3D,CAAC;QACN,CAAC;IACH,CAAC;SAAM,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;QAC9C,QAAQ,aAAa,EAAE,CAAC;YACtB,KAAK,CAAC;gBACJ,OAAO,MAAM,CAAC;YAChB,KAAK,EAAE;gBACL,OAAO,OAAO,CAAC;YACjB,KAAK,EAAE;gBACL,OAAO,OAAO,CAAC;YACjB;gBACE,MAAM,IAAI,KAAK,CACb,yCAAyC,aAAa,EAAE,CACzD,CAAC;QACN,CAAC;IACH,CAAC;SAAM,IAAI,YAAY,KAAK,mBAAmB,EAAE,CAAC;QAChD,QAAQ,aAAa,EAAE,CAAC;YACtB,KAAK,EAAE;gBACL,OAAO,SAAS,CAAC;YACnB,KAAK,EAAE;gBACL,OAAO,SAAS,CAAC;YACnB;gBACE,MAAM,IAAI,KAAK,CACb,yCAAyC,aAAa,EAAE,CACzD,CAAC;QACN,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kCAAkC,YAAY,EAAE,CAAC,CAAC;AACpE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,GAAG,GAAiC;QACxC,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,SAAS;KAClB,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,OAAO,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,eAAe,CAAC,KAAmB;IACjD,MAAM,GAAG,GAAiC;QACxC,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;KACX,CAAC;IACF,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACtC,KAAmB;IAYnB,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,UAAU,CAAC;QACpB,KAAK,MAAM;YACT,OAAO,SAAS,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,WAAW,CAAC;QACrB,KAAK,OAAO;YACV,OAAO,UAAU,CAAC;QACpB,KAAK,QAAQ;YACX,OAAO,WAAW,CAAC;QACrB,KAAK,OAAO;YACV,OAAO,UAAU,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,YAAY,CAAC;QACtB,KAAK,SAAS;YACZ,OAAO,YAAY,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IFD indexer: maps (c, z, t, resolution level) to a GeoTIFFImage.
|
|
3
|
+
*
|
|
4
|
+
* Handles both modern (SubIFD-based) and legacy (flat IFD chain) pyramid
|
|
5
|
+
* storage strategies, as well as optional pre-computed IFD byte offsets
|
|
6
|
+
* for fast random access.
|
|
7
|
+
*/
|
|
8
|
+
import type GeoTIFF from "geotiff";
|
|
9
|
+
import type { GeoTIFFImage } from "geotiff";
|
|
10
|
+
import { type OmePixels } from "./ome-xml.js";
|
|
11
|
+
/** A selection identifying a single 2D plane in a multi-dimensional image. */
|
|
12
|
+
export interface PlaneSelection {
|
|
13
|
+
c: number;
|
|
14
|
+
z: number;
|
|
15
|
+
t: number;
|
|
16
|
+
}
|
|
17
|
+
/** Information about the pyramid structure of a TIFF. */
|
|
18
|
+
export interface PyramidInfo {
|
|
19
|
+
/** Number of resolution levels (1 means no pyramid). */
|
|
20
|
+
levels: number;
|
|
21
|
+
/** Whether the pyramid uses SubIFDs (modern) or flat IFDs (legacy). */
|
|
22
|
+
usesSubIfds: boolean;
|
|
23
|
+
/** Width at each level. */
|
|
24
|
+
widths: number[];
|
|
25
|
+
/** Height at each level. */
|
|
26
|
+
heights: number[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Determine the pyramid structure of a TIFF by inspecting the first image.
|
|
30
|
+
*
|
|
31
|
+
* @param tiff - The opened GeoTIFF object.
|
|
32
|
+
* @param omeImages - Number of OME-XML Image entries (for legacy detection).
|
|
33
|
+
* @param planesPerImage - Number of planes (C*Z*T) per OME Image entry.
|
|
34
|
+
* @returns Pyramid info describing all resolution levels.
|
|
35
|
+
*/
|
|
36
|
+
export declare function detectPyramid(tiff: GeoTIFF, omeImages: number, planesPerImage: number): Promise<PyramidInfo>;
|
|
37
|
+
/**
|
|
38
|
+
* Create an indexer function for OME-TIFF images.
|
|
39
|
+
*
|
|
40
|
+
* The returned function maps a (selection, level) pair to a GeoTIFFImage.
|
|
41
|
+
*
|
|
42
|
+
* @param tiff - The opened GeoTIFF object.
|
|
43
|
+
* @param pixels - OME-XML Pixels metadata.
|
|
44
|
+
* @param pyramid - Pyramid info from detectPyramid.
|
|
45
|
+
* @param ifdOffset - Offset into the IFD chain for this OME Image entry.
|
|
46
|
+
* @param offsets - Optional pre-computed IFD byte offsets.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createOmeIndexer(tiff: GeoTIFF, pixels: OmePixels, pyramid: PyramidInfo, ifdOffset?: number, offsets?: number[]): (sel: PlaneSelection, level: number) => Promise<GeoTIFFImage>;
|
|
49
|
+
/**
|
|
50
|
+
* Create an indexer function for plain (non-OME) TIFF images.
|
|
51
|
+
*
|
|
52
|
+
* For plain TIFFs: single channel, each IFD is a different resolution level
|
|
53
|
+
* (COG pattern) or a single image.
|
|
54
|
+
*/
|
|
55
|
+
export declare function createPlainIndexer(tiff: GeoTIFF, offsets?: number[]): (sel: PlaneSelection, level: number) => Promise<GeoTIFFImage>;
|
|
56
|
+
//# sourceMappingURL=ifd-indexer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ifd-indexer.d.ts","sourceRoot":"","sources":["../src/ifd-indexer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,8EAA8E;AAC9E,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,WAAW,EAAE,OAAO,CAAC;IACrB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,WAAW,CAAC,CA0GtB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,WAAW,EACpB,SAAS,GAAE,MAAU,EACrB,OAAO,CAAC,EAAE,MAAM,EAAE,GACjB,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CA6C/D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,MAAM,EAAE,GACjB,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAO/D"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IFD indexer: maps (c, z, t, resolution level) to a GeoTIFFImage.
|
|
3
|
+
*
|
|
4
|
+
* Handles both modern (SubIFD-based) and legacy (flat IFD chain) pyramid
|
|
5
|
+
* storage strategies, as well as optional pre-computed IFD byte offsets
|
|
6
|
+
* for fast random access.
|
|
7
|
+
*/
|
|
8
|
+
import { getIfdIndex } from "./ome-xml.js";
|
|
9
|
+
/**
|
|
10
|
+
* Determine the pyramid structure of a TIFF by inspecting the first image.
|
|
11
|
+
*
|
|
12
|
+
* @param tiff - The opened GeoTIFF object.
|
|
13
|
+
* @param omeImages - Number of OME-XML Image entries (for legacy detection).
|
|
14
|
+
* @param planesPerImage - Number of planes (C*Z*T) per OME Image entry.
|
|
15
|
+
* @returns Pyramid info describing all resolution levels.
|
|
16
|
+
*/
|
|
17
|
+
export async function detectPyramid(tiff, omeImages, planesPerImage) {
|
|
18
|
+
const firstImage = await tiff.getImage(0);
|
|
19
|
+
const baseWidth = firstImage.getWidth();
|
|
20
|
+
const baseHeight = firstImage.getHeight();
|
|
21
|
+
// Check for SubIFDs (modern bioformats2raw + raw2ometiff format)
|
|
22
|
+
let subIfds;
|
|
23
|
+
try {
|
|
24
|
+
if (firstImage.fileDirectory.hasTag("SubIFDs")) {
|
|
25
|
+
const raw = await firstImage.fileDirectory.loadValue("SubIFDs");
|
|
26
|
+
subIfds = Array.isArray(raw) ? raw : Array.from(raw);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// SubIFDs not available
|
|
31
|
+
}
|
|
32
|
+
if (subIfds && subIfds.length > 0) {
|
|
33
|
+
// Modern format: base + N sub-resolutions
|
|
34
|
+
const levels = subIfds.length + 1;
|
|
35
|
+
const widths = [baseWidth];
|
|
36
|
+
const heights = [baseHeight];
|
|
37
|
+
// Parse each SubIFD to get its dimensions
|
|
38
|
+
for (const offset of subIfds) {
|
|
39
|
+
try {
|
|
40
|
+
const ifd = await tiff.parseFileDirectoryAt(offset);
|
|
41
|
+
const subWidth = ifd.fileDirectory?.getValue?.("ImageWidth") ??
|
|
42
|
+
ifd.getValue?.("ImageWidth") ??
|
|
43
|
+
Math.ceil(widths[widths.length - 1] / 2);
|
|
44
|
+
const subHeight = ifd.fileDirectory?.getValue?.("ImageLength") ??
|
|
45
|
+
ifd.getValue?.("ImageLength") ??
|
|
46
|
+
Math.ceil(heights[heights.length - 1] / 2);
|
|
47
|
+
widths.push(subWidth);
|
|
48
|
+
heights.push(subHeight);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Fallback: assume 2x downsampling
|
|
52
|
+
widths.push(Math.ceil(widths[widths.length - 1] / 2));
|
|
53
|
+
heights.push(Math.ceil(heights[heights.length - 1] / 2));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { levels, usesSubIfds: true, widths, heights };
|
|
57
|
+
}
|
|
58
|
+
// Legacy: multiple OME Image entries = multiple resolution levels
|
|
59
|
+
if (omeImages > 1) {
|
|
60
|
+
const levels = omeImages;
|
|
61
|
+
const widths = [baseWidth];
|
|
62
|
+
const heights = [baseHeight];
|
|
63
|
+
for (let lvl = 1; lvl < levels; lvl++) {
|
|
64
|
+
const ifdIdx = lvl * planesPerImage;
|
|
65
|
+
try {
|
|
66
|
+
const img = await tiff.getImage(ifdIdx);
|
|
67
|
+
widths.push(img.getWidth());
|
|
68
|
+
heights.push(img.getHeight());
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
widths.push(Math.ceil(widths[widths.length - 1] / 2));
|
|
72
|
+
heights.push(Math.ceil(heights[heights.length - 1] / 2));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { levels, usesSubIfds: false, widths, heights };
|
|
76
|
+
}
|
|
77
|
+
// Check for COG-style: multiple IFDs with decreasing resolution
|
|
78
|
+
// (non-OME TIFFs with overview images)
|
|
79
|
+
try {
|
|
80
|
+
const imageCount = await tiff.getImageCount();
|
|
81
|
+
if (imageCount > 1) {
|
|
82
|
+
const widths = [baseWidth];
|
|
83
|
+
const heights = [baseHeight];
|
|
84
|
+
for (let i = 1; i < imageCount; i++) {
|
|
85
|
+
const img = await tiff.getImage(i);
|
|
86
|
+
const w = img.getWidth();
|
|
87
|
+
const h = img.getHeight();
|
|
88
|
+
// Only count as pyramid level if it's smaller
|
|
89
|
+
if (w < widths[widths.length - 1] && h < heights[heights.length - 1]) {
|
|
90
|
+
widths.push(w);
|
|
91
|
+
heights.push(h);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (widths.length > 1) {
|
|
98
|
+
return {
|
|
99
|
+
levels: widths.length,
|
|
100
|
+
usesSubIfds: false,
|
|
101
|
+
widths,
|
|
102
|
+
heights,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Cannot determine image count
|
|
109
|
+
}
|
|
110
|
+
// Single level (no pyramid)
|
|
111
|
+
return {
|
|
112
|
+
levels: 1,
|
|
113
|
+
usesSubIfds: false,
|
|
114
|
+
widths: [baseWidth],
|
|
115
|
+
heights: [baseHeight],
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Create an indexer function for OME-TIFF images.
|
|
120
|
+
*
|
|
121
|
+
* The returned function maps a (selection, level) pair to a GeoTIFFImage.
|
|
122
|
+
*
|
|
123
|
+
* @param tiff - The opened GeoTIFF object.
|
|
124
|
+
* @param pixels - OME-XML Pixels metadata.
|
|
125
|
+
* @param pyramid - Pyramid info from detectPyramid.
|
|
126
|
+
* @param ifdOffset - Offset into the IFD chain for this OME Image entry.
|
|
127
|
+
* @param offsets - Optional pre-computed IFD byte offsets.
|
|
128
|
+
*/
|
|
129
|
+
export function createOmeIndexer(tiff, pixels, pyramid, ifdOffset = 0, offsets) {
|
|
130
|
+
const ifdCache = new Map();
|
|
131
|
+
const planesPerImage = pixels.sizeC * pixels.sizeZ * pixels.sizeT;
|
|
132
|
+
return async (sel, level) => {
|
|
133
|
+
const relativeIfd = getIfdIndex(sel.c, sel.z, sel.t, pixels);
|
|
134
|
+
const absoluteIfd = relativeIfd + ifdOffset;
|
|
135
|
+
if (level === 0) {
|
|
136
|
+
// Base resolution: fetch the IFD directly
|
|
137
|
+
return getImage(tiff, absoluteIfd, offsets);
|
|
138
|
+
}
|
|
139
|
+
if (pyramid.usesSubIfds) {
|
|
140
|
+
// Modern: get base image, then look up SubIFD for the pyramid level
|
|
141
|
+
const cacheKey = `sub_${absoluteIfd}_${level}`;
|
|
142
|
+
if (!ifdCache.has(cacheKey)) {
|
|
143
|
+
ifdCache.set(cacheKey, (async () => {
|
|
144
|
+
const baseImage = await getImage(tiff, absoluteIfd, offsets);
|
|
145
|
+
const rawSubIfds = await baseImage.fileDirectory.loadValue("SubIFDs");
|
|
146
|
+
const subIfds = Array.isArray(rawSubIfds)
|
|
147
|
+
? rawSubIfds
|
|
148
|
+
: Array.from(rawSubIfds);
|
|
149
|
+
const subIfdOffset = subIfds[level - 1];
|
|
150
|
+
if (subIfdOffset === undefined) {
|
|
151
|
+
throw new Error(`SubIFD index ${level - 1} out of range (${subIfds.length} available)`);
|
|
152
|
+
}
|
|
153
|
+
return getImageAtOffset(tiff, subIfdOffset);
|
|
154
|
+
})());
|
|
155
|
+
}
|
|
156
|
+
return ifdCache.get(cacheKey);
|
|
157
|
+
}
|
|
158
|
+
// Legacy: flat IFD chain, each level's IFDs are offset by
|
|
159
|
+
// level * planesPerImage from the base
|
|
160
|
+
const levelIfd = absoluteIfd + level * planesPerImage;
|
|
161
|
+
return getImage(tiff, levelIfd, offsets);
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Create an indexer function for plain (non-OME) TIFF images.
|
|
166
|
+
*
|
|
167
|
+
* For plain TIFFs: single channel, each IFD is a different resolution level
|
|
168
|
+
* (COG pattern) or a single image.
|
|
169
|
+
*/
|
|
170
|
+
export function createPlainIndexer(tiff, offsets) {
|
|
171
|
+
return async (_sel, level) => {
|
|
172
|
+
return getImage(tiff, level, offsets);
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// ---------- internal helpers ----------
|
|
176
|
+
/**
|
|
177
|
+
* Get a GeoTIFFImage by IFD index, using pre-computed offsets if available.
|
|
178
|
+
*/
|
|
179
|
+
async function getImage(tiff, index, offsets) {
|
|
180
|
+
if (offsets && index < offsets.length) {
|
|
181
|
+
// Use pre-computed offset for direct access
|
|
182
|
+
return getImageAtOffset(tiff, offsets[index]);
|
|
183
|
+
}
|
|
184
|
+
return tiff.getImage(index);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Parse an IFD at a specific byte offset and return a GeoTIFFImage.
|
|
188
|
+
*/
|
|
189
|
+
async function getImageAtOffset(tiff, byteOffset) {
|
|
190
|
+
// GeoTIFF.parseFileDirectoryAt is semi-internal but widely used by Viv etc.
|
|
191
|
+
const ifd = await tiff.parseFileDirectoryAt(byteOffset);
|
|
192
|
+
// Construct a GeoTIFFImage from the parsed IFD
|
|
193
|
+
// The exact constructor signature depends on geotiff.js version
|
|
194
|
+
const GeoTIFFImageClass = (await tiff.getImage(0)).constructor;
|
|
195
|
+
return new GeoTIFFImageClass(ifd.fileDirectory ?? ifd, tiff.littleEndian, tiff.cache, tiff.source);
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=ifd-indexer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ifd-indexer.js","sourceRoot":"","sources":["../src/ifd-indexer.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fideus-labs/fiff
|
|
3
|
+
*
|
|
4
|
+
* Present TIFF files as a zarrita.js Zarr store following the OME-Zarr
|
|
5
|
+
* (NGFF v0.5) data model.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { TiffStore } from "@fideus-labs/fiff";
|
|
10
|
+
* import * as zarr from "zarrita";
|
|
11
|
+
*
|
|
12
|
+
* const store = await TiffStore.fromUrl("https://example.com/image.ome.tif");
|
|
13
|
+
* const group = await zarr.open(store, { kind: "group" });
|
|
14
|
+
* const arr = await zarr.open(group.resolve("0"), { kind: "array" });
|
|
15
|
+
* const chunk = await arr.getChunk([0, 0, 0]);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export { TiffStore, type TiffStoreOptions } from "./tiff-store.js";
|
|
19
|
+
export type { ZarrDataType } from "./dtypes.js";
|
|
20
|
+
export type { OmeImage, OmePixels, OmeChannel, DimensionOrder } from "./ome-xml.js";
|
|
21
|
+
export type { PyramidInfo, PlaneSelection } from "./ifd-indexer.js";
|
|
22
|
+
export type { OmeAxis, OmeMultiscale, OmeDataset, OmeCoordinateTransformation, OmeroMetadata, OmeroChannel, ZarrGroupMetadata, ZarrArrayMetadata, } from "./metadata.js";
|
|
23
|
+
export { parseOmeXml, isOmeXml, getIfdIndex } from "./ome-xml.js";
|
|
24
|
+
export { tiffDtypeToZarr, omePixelTypeToZarr, bytesPerElement } from "./dtypes.js";
|
|
25
|
+
export { parseStoreKey, computePixelWindow } from "./utils.js";
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACpF,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACpE,YAAY,EACV,OAAO,EACP,aAAa,EACb,UAAU,EACV,2BAA2B,EAC3B,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fideus-labs/fiff
|
|
3
|
+
*
|
|
4
|
+
* Present TIFF files as a zarrita.js Zarr store following the OME-Zarr
|
|
5
|
+
* (NGFF v0.5) data model.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { TiffStore } from "@fideus-labs/fiff";
|
|
10
|
+
* import * as zarr from "zarrita";
|
|
11
|
+
*
|
|
12
|
+
* const store = await TiffStore.fromUrl("https://example.com/image.ome.tif");
|
|
13
|
+
* const group = await zarr.open(store, { kind: "group" });
|
|
14
|
+
* const arr = await zarr.open(group.resolve("0"), { kind: "array" });
|
|
15
|
+
* const chunk = await arr.getChunk([0, 0, 0]);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export { TiffStore } from "./tiff-store.js";
|
|
19
|
+
// Export utilities that may be useful
|
|
20
|
+
export { parseOmeXml, isOmeXml, getIfdIndex } from "./ome-xml.js";
|
|
21
|
+
export { tiffDtypeToZarr, omePixelTypeToZarr, bytesPerElement } from "./dtypes.js";
|
|
22
|
+
export { parseStoreKey, computePixelWindow } from "./utils.js";
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAC;AAiBnE,sCAAsC;AACtC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|