@fideus-labs/fiff 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +204 -25
- package/dist/dtypes.d.ts +15 -0
- package/dist/dtypes.d.ts.map +1 -1
- package/dist/dtypes.js +34 -0
- package/dist/dtypes.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/ome-xml-writer.d.ts +57 -0
- package/dist/ome-xml-writer.d.ts.map +1 -0
- package/dist/ome-xml-writer.js +210 -0
- package/dist/ome-xml-writer.js.map +1 -0
- package/dist/tiff-writer.d.ts +122 -0
- package/dist/tiff-writer.d.ts.map +1 -0
- package/dist/tiff-writer.js +640 -0
- package/dist/tiff-writer.js.map +1 -0
- package/dist/write.d.ts +84 -0
- package/dist/write.d.ts.map +1 -0
- package/dist/write.js +173 -0
- package/dist/write.js.map +1 -0
- package/package.json +13 -3
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright (c) Fideus Labs LLC
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* Low-level TIFF binary builder.
|
|
5
|
+
*
|
|
6
|
+
* Assembles IFD entries, tag values, tile/strip data, and SubIFD chains into
|
|
7
|
+
* a valid TIFF file (little-endian). Supports both classic TIFF (32-bit
|
|
8
|
+
* offsets, magic 42) and BigTIFF (64-bit offsets, magic 43).
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Tiled output (default 256x256, configurable)
|
|
12
|
+
* - Deflate compression via CompressionStream (async, non-blocking)
|
|
13
|
+
* with synchronous pako fallback
|
|
14
|
+
* - Automatic BigTIFF when offsets exceed 4 GB
|
|
15
|
+
* - Compress-and-release: tiles are compressed eagerly, uncompressed
|
|
16
|
+
* data is released immediately to minimise peak memory
|
|
17
|
+
*
|
|
18
|
+
* Layout strategy (two-pass):
|
|
19
|
+
* Pass 1: Compress tiles, resolve tags, compute sizes and offsets.
|
|
20
|
+
* Pass 2: Write into a pre-allocated ArrayBuffer.
|
|
21
|
+
*
|
|
22
|
+
* File layout:
|
|
23
|
+
* [Header 8 or 16 bytes]
|
|
24
|
+
* [Main IFD 0 entries + overflow data + tile data]
|
|
25
|
+
* [SubIFD 0,0 ...]
|
|
26
|
+
* [SubIFD 0,1 ...]
|
|
27
|
+
* [Main IFD 1 entries + overflow data + tile data]
|
|
28
|
+
* ...
|
|
29
|
+
*/
|
|
30
|
+
import { deflate } from "pako";
|
|
31
|
+
// ── TIFF constants ──────────────────────────────────────────────────
|
|
32
|
+
/** TIFF tag data types and their byte sizes. */
|
|
33
|
+
export const TIFF_TYPE_BYTE = 1; // 1 byte
|
|
34
|
+
export const TIFF_TYPE_ASCII = 2; // 1 byte (null-terminated)
|
|
35
|
+
export const TIFF_TYPE_SHORT = 3; // 2 bytes
|
|
36
|
+
export const TIFF_TYPE_LONG = 4; // 4 bytes
|
|
37
|
+
export const TIFF_TYPE_RATIONAL = 5; // 8 bytes (two LONGs)
|
|
38
|
+
export const TIFF_TYPE_LONG8 = 16; // 8 bytes (BigTIFF only)
|
|
39
|
+
const TYPE_SIZES = {
|
|
40
|
+
[TIFF_TYPE_BYTE]: 1,
|
|
41
|
+
[TIFF_TYPE_ASCII]: 1,
|
|
42
|
+
[TIFF_TYPE_SHORT]: 2,
|
|
43
|
+
[TIFF_TYPE_LONG]: 4,
|
|
44
|
+
[TIFF_TYPE_RATIONAL]: 8,
|
|
45
|
+
[TIFF_TYPE_LONG8]: 8,
|
|
46
|
+
};
|
|
47
|
+
/** Well-known TIFF tags. */
|
|
48
|
+
export const TAG_NEW_SUBFILE_TYPE = 254;
|
|
49
|
+
export const TAG_IMAGE_WIDTH = 256;
|
|
50
|
+
export const TAG_IMAGE_LENGTH = 257;
|
|
51
|
+
export const TAG_BITS_PER_SAMPLE = 258;
|
|
52
|
+
export const TAG_COMPRESSION = 259;
|
|
53
|
+
export const TAG_PHOTOMETRIC = 262;
|
|
54
|
+
export const TAG_IMAGE_DESCRIPTION = 270;
|
|
55
|
+
export const TAG_STRIP_OFFSETS = 273;
|
|
56
|
+
export const TAG_SAMPLES_PER_PIXEL = 277;
|
|
57
|
+
export const TAG_ROWS_PER_STRIP = 278;
|
|
58
|
+
export const TAG_STRIP_BYTE_COUNTS = 279;
|
|
59
|
+
export const TAG_PLANAR_CONFIGURATION = 284;
|
|
60
|
+
export const TAG_TILE_WIDTH = 322;
|
|
61
|
+
export const TAG_TILE_LENGTH = 323;
|
|
62
|
+
export const TAG_TILE_OFFSETS = 324;
|
|
63
|
+
export const TAG_TILE_BYTE_COUNTS = 325;
|
|
64
|
+
export const TAG_SUB_IFDS = 330;
|
|
65
|
+
export const TAG_SAMPLE_FORMAT = 339;
|
|
66
|
+
/** TIFF compression codes. */
|
|
67
|
+
export const COMPRESSION_NONE = 1;
|
|
68
|
+
export const COMPRESSION_DEFLATE = 8;
|
|
69
|
+
/** Default tile size (OME-TIFF convention). Must be a multiple of 16. */
|
|
70
|
+
export const DEFAULT_TILE_SIZE = 256;
|
|
71
|
+
const CLASSIC_FORMAT = {
|
|
72
|
+
headerSize: 8,
|
|
73
|
+
ifdEntrySize: 12,
|
|
74
|
+
offsetSize: 4,
|
|
75
|
+
inlineThreshold: 4,
|
|
76
|
+
offsetType: TIFF_TYPE_LONG,
|
|
77
|
+
magic: 42,
|
|
78
|
+
};
|
|
79
|
+
const BIGTIFF_FORMAT = {
|
|
80
|
+
headerSize: 16,
|
|
81
|
+
ifdEntrySize: 20,
|
|
82
|
+
offsetSize: 8,
|
|
83
|
+
inlineThreshold: 8,
|
|
84
|
+
offsetType: TIFF_TYPE_LONG8,
|
|
85
|
+
magic: 43,
|
|
86
|
+
};
|
|
87
|
+
// ── Public API ──────────────────────────────────────────────────────
|
|
88
|
+
/**
|
|
89
|
+
* Build a complete TIFF file from a list of IFDs.
|
|
90
|
+
*
|
|
91
|
+
* Tiles are compressed (if requested) eagerly and in parallel where
|
|
92
|
+
* possible. The uncompressed data is released after compression to
|
|
93
|
+
* minimise peak memory usage.
|
|
94
|
+
*
|
|
95
|
+
* @param ifds - Main IFD chain (linked via next-IFD pointers).
|
|
96
|
+
* @param options - Build options (compression, format, etc.).
|
|
97
|
+
* @returns A complete TIFF file as an ArrayBuffer.
|
|
98
|
+
*/
|
|
99
|
+
export async function buildTiff(ifds, options = {}) {
|
|
100
|
+
const compression = options.compression ?? "none";
|
|
101
|
+
const compressionLevel = options.compressionLevel ?? 6;
|
|
102
|
+
const formatOpt = options.format ?? "auto";
|
|
103
|
+
// Phase 1: Compress tiles eagerly (compress-and-release)
|
|
104
|
+
const processedIfds = await Promise.all(ifds.map((ifd) => processIfdAsync(ifd, compression, compressionLevel)));
|
|
105
|
+
// Phase 2: Determine format (auto-detect BigTIFF if needed)
|
|
106
|
+
const rawSize = estimateRawSize(processedIfds);
|
|
107
|
+
let fmt;
|
|
108
|
+
if (formatOpt === "bigtiff") {
|
|
109
|
+
fmt = BIGTIFF_FORMAT;
|
|
110
|
+
}
|
|
111
|
+
else if (formatOpt === "classic") {
|
|
112
|
+
fmt = CLASSIC_FORMAT;
|
|
113
|
+
if (rawSize > 0xffff_fffe) {
|
|
114
|
+
throw new Error(`File size (~${(rawSize / 1e9).toFixed(1)} GB) exceeds classic TIFF 4 GB limit. ` +
|
|
115
|
+
`Use format: "auto" or "bigtiff".`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// auto: use BigTIFF if estimated size > 3.9 GB (conservative)
|
|
120
|
+
fmt = rawSize > 3.9e9 ? BIGTIFF_FORMAT : CLASSIC_FORMAT;
|
|
121
|
+
}
|
|
122
|
+
// Phase 3: Compute sizes and place all IFDs
|
|
123
|
+
const placed = placeIfds(processedIfds, fmt);
|
|
124
|
+
// Phase 4: Compute total file size
|
|
125
|
+
const totalSize = computeTotalSize(placed, fmt);
|
|
126
|
+
// Phase 5: Write into buffer
|
|
127
|
+
const buffer = new ArrayBuffer(totalSize);
|
|
128
|
+
const view = new DataView(buffer);
|
|
129
|
+
writeHeader(view, fmt, placed.length > 0 ? placed[0].ifdOffset : 0);
|
|
130
|
+
for (const p of placed) {
|
|
131
|
+
writeIfd(view, buffer, p, fmt);
|
|
132
|
+
}
|
|
133
|
+
return buffer;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Compress a Uint8Array using deflate (zlib-wrapped, RFC 1950).
|
|
137
|
+
* Compatible with TIFF compression code 8 and geotiff.js's pako.inflate().
|
|
138
|
+
*
|
|
139
|
+
* Prefers the native CompressionStream API (async, non-blocking) when
|
|
140
|
+
* available, falling back to synchronous pako.deflate().
|
|
141
|
+
*/
|
|
142
|
+
export async function compressDeflateAsync(data, level = 6) {
|
|
143
|
+
// CompressionStream("deflate") produces zlib-wrapped output (RFC 1950),
|
|
144
|
+
// which is what TIFF code 8 expects and what geotiff.js decompresses.
|
|
145
|
+
// However, CompressionStream doesn't support compression level, so we
|
|
146
|
+
// only use it for the default level to avoid surprising behaviour.
|
|
147
|
+
// For non-default levels, we fall back to pako.
|
|
148
|
+
if (typeof globalThis.CompressionStream !== "undefined" &&
|
|
149
|
+
level === 6) {
|
|
150
|
+
const stream = new CompressionStream("deflate");
|
|
151
|
+
const writer = stream.writable.getWriter();
|
|
152
|
+
const reader = stream.readable.getReader();
|
|
153
|
+
// Write and close
|
|
154
|
+
writer.write(data);
|
|
155
|
+
writer.close();
|
|
156
|
+
// Collect chunks
|
|
157
|
+
const chunks = [];
|
|
158
|
+
let totalLen = 0;
|
|
159
|
+
while (true) {
|
|
160
|
+
const { done, value } = await reader.read();
|
|
161
|
+
if (done)
|
|
162
|
+
break;
|
|
163
|
+
chunks.push(value);
|
|
164
|
+
totalLen += value.length;
|
|
165
|
+
}
|
|
166
|
+
// Concatenate
|
|
167
|
+
const result = new Uint8Array(totalLen);
|
|
168
|
+
let offset = 0;
|
|
169
|
+
for (const chunk of chunks) {
|
|
170
|
+
result.set(chunk, offset);
|
|
171
|
+
offset += chunk.length;
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
return compressDeflate(data, level);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Compress a Uint8Array using deflate (zlib-wrapped, RFC 1950) synchronously.
|
|
179
|
+
* Compatible with TIFF compression code 8 and geotiff.js's pako.inflate().
|
|
180
|
+
*/
|
|
181
|
+
export function compressDeflate(data, level = 6) {
|
|
182
|
+
return deflate(data, { level: level });
|
|
183
|
+
}
|
|
184
|
+
// ── Internal helpers ────────────────────────────────────────────────
|
|
185
|
+
/**
|
|
186
|
+
* Process an IFD: compress tiles if needed, add compression tag,
|
|
187
|
+
* and recursively process SubIFDs. Async for CompressionStream support.
|
|
188
|
+
*
|
|
189
|
+
* This is the "compress-and-release" step: after compression, the
|
|
190
|
+
* original uncompressed tile data can be GC'd.
|
|
191
|
+
*/
|
|
192
|
+
async function processIfdAsync(ifd, compression, level) {
|
|
193
|
+
let tiles = ifd.tiles;
|
|
194
|
+
const tags = [...ifd.tags];
|
|
195
|
+
if (compression === "deflate") {
|
|
196
|
+
// Compress all tiles in parallel
|
|
197
|
+
tiles = await Promise.all(tiles.map((t) => compressDeflateAsync(t, level)));
|
|
198
|
+
// Replace or add Compression tag
|
|
199
|
+
const compIdx = tags.findIndex((t) => t.tag === TAG_COMPRESSION);
|
|
200
|
+
if (compIdx >= 0) {
|
|
201
|
+
tags[compIdx] = { tag: TAG_COMPRESSION, type: TIFF_TYPE_SHORT, values: [COMPRESSION_DEFLATE] };
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
tags.push({ tag: TAG_COMPRESSION, type: TIFF_TYPE_SHORT, values: [COMPRESSION_DEFLATE] });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const subIfds = ifd.subIfds
|
|
208
|
+
? await Promise.all(ifd.subIfds.map((sub) => processIfdAsync(sub, compression, level)))
|
|
209
|
+
: undefined;
|
|
210
|
+
return { tags, tiles, subIfds };
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Estimate raw file size (sum of all tile data + overhead per IFD).
|
|
214
|
+
* Used for BigTIFF auto-detection.
|
|
215
|
+
*/
|
|
216
|
+
function estimateRawSize(ifds) {
|
|
217
|
+
let size = 16; // BigTIFF header (conservative)
|
|
218
|
+
for (const ifd of ifds) {
|
|
219
|
+
size += 256; // tags overhead estimate
|
|
220
|
+
for (const tile of ifd.tiles) {
|
|
221
|
+
size += tile.length;
|
|
222
|
+
}
|
|
223
|
+
if (ifd.subIfds) {
|
|
224
|
+
size += estimateRawSize(ifd.subIfds);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return size;
|
|
228
|
+
}
|
|
229
|
+
/** Write the TIFF file header. */
|
|
230
|
+
function writeHeader(view, fmt, firstIfdOffset) {
|
|
231
|
+
// Byte order: "II" (little-endian)
|
|
232
|
+
view.setUint16(0, 0x4949, true);
|
|
233
|
+
if (fmt.magic === 42) {
|
|
234
|
+
// Classic TIFF
|
|
235
|
+
view.setUint16(2, 42, true);
|
|
236
|
+
view.setUint32(4, firstIfdOffset, true);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
// BigTIFF
|
|
240
|
+
view.setUint16(2, 43, true);
|
|
241
|
+
view.setUint16(4, 8, true); // offset size
|
|
242
|
+
view.setUint16(6, 0, true); // padding
|
|
243
|
+
setBigUint64(view, 8, firstIfdOffset);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** Resolve a TiffTag to its byte representation. */
|
|
247
|
+
function resolveTag(tag) {
|
|
248
|
+
if (typeof tag.values === "string") {
|
|
249
|
+
// ASCII: null-terminated
|
|
250
|
+
const encoder = new TextEncoder();
|
|
251
|
+
const strBytes = encoder.encode(tag.values);
|
|
252
|
+
const valueBytes = new Uint8Array(strBytes.length + 1); // +1 for null terminator
|
|
253
|
+
valueBytes.set(strBytes);
|
|
254
|
+
valueBytes[strBytes.length] = 0;
|
|
255
|
+
return { tag: tag.tag, type: TIFF_TYPE_ASCII, count: valueBytes.length, valueBytes };
|
|
256
|
+
}
|
|
257
|
+
const typeSize = TYPE_SIZES[tag.type];
|
|
258
|
+
if (!typeSize) {
|
|
259
|
+
throw new Error(`Unknown TIFF type: ${tag.type}`);
|
|
260
|
+
}
|
|
261
|
+
const count = tag.type === TIFF_TYPE_RATIONAL ? tag.values.length / 2 : tag.values.length;
|
|
262
|
+
const totalBytes = count * typeSize;
|
|
263
|
+
const valueBytes = new Uint8Array(totalBytes);
|
|
264
|
+
const dv = new DataView(valueBytes.buffer, valueBytes.byteOffset, valueBytes.byteLength);
|
|
265
|
+
for (let i = 0; i < tag.values.length; i++) {
|
|
266
|
+
switch (tag.type) {
|
|
267
|
+
case TIFF_TYPE_BYTE:
|
|
268
|
+
dv.setUint8(i, tag.values[i]);
|
|
269
|
+
break;
|
|
270
|
+
case TIFF_TYPE_SHORT:
|
|
271
|
+
dv.setUint16(i * 2, tag.values[i], true);
|
|
272
|
+
break;
|
|
273
|
+
case TIFF_TYPE_LONG:
|
|
274
|
+
dv.setUint32(i * 4, tag.values[i], true);
|
|
275
|
+
break;
|
|
276
|
+
case TIFF_TYPE_LONG8:
|
|
277
|
+
setBigUint64(dv, i * 8, tag.values[i]);
|
|
278
|
+
break;
|
|
279
|
+
case TIFF_TYPE_RATIONAL:
|
|
280
|
+
// Rationals are stored as two LONGs (numerator, denominator)
|
|
281
|
+
dv.setUint32(i * 4, tag.values[i], true);
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return { tag: tag.tag, type: tag.type, count, valueBytes };
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Compute the byte size of an IFD entry block.
|
|
289
|
+
* Classic: 2 + 12*N + 4
|
|
290
|
+
* BigTIFF: 8 + 20*N + 8
|
|
291
|
+
*/
|
|
292
|
+
function ifdEntryBlockSize(numTags, fmt) {
|
|
293
|
+
if (fmt.magic === 42) {
|
|
294
|
+
return 2 + numTags * 12 + 4;
|
|
295
|
+
}
|
|
296
|
+
// BigTIFF: 8 bytes entry count + 20 bytes per entry + 8 bytes next offset
|
|
297
|
+
return 8 + numTags * 20 + 8;
|
|
298
|
+
}
|
|
299
|
+
/** Compute overflow size for resolved tags (values that don't fit inline). */
|
|
300
|
+
function overflowSize(tags, fmt) {
|
|
301
|
+
let size = 0;
|
|
302
|
+
for (const t of tags) {
|
|
303
|
+
if (t.valueBytes.length > fmt.inlineThreshold) {
|
|
304
|
+
size += t.valueBytes.length;
|
|
305
|
+
// Pad to word boundary (2-byte alignment)
|
|
306
|
+
if (t.valueBytes.length % 2 !== 0)
|
|
307
|
+
size += 1;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return size;
|
|
311
|
+
}
|
|
312
|
+
/** Compute total tile data size. */
|
|
313
|
+
function totalTileSize(tiles) {
|
|
314
|
+
return tiles.reduce((sum, t) => sum + t.length, 0);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Place all IFDs sequentially, computing absolute offsets.
|
|
318
|
+
* Returns a flat list of PlacedIfds (main chain first, then SubIFDs interleaved).
|
|
319
|
+
*/
|
|
320
|
+
function placeIfds(ifds, fmt) {
|
|
321
|
+
const allPlaced = [];
|
|
322
|
+
function resolveIfdInfo(ifd) {
|
|
323
|
+
const userTags = ifd.tags.map(resolveTag);
|
|
324
|
+
// Determine if this is tiled or stripped based on tags
|
|
325
|
+
const hasTileWidth = ifd.tags.some((t) => t.tag === TAG_TILE_WIDTH);
|
|
326
|
+
// Add offset and byte-count tags as placeholders
|
|
327
|
+
const offsetTag = hasTileWidth ? TAG_TILE_OFFSETS : TAG_STRIP_OFFSETS;
|
|
328
|
+
const countTag = hasTileWidth ? TAG_TILE_BYTE_COUNTS : TAG_STRIP_BYTE_COUNTS;
|
|
329
|
+
const tileOffsetsTag = {
|
|
330
|
+
tag: offsetTag,
|
|
331
|
+
type: fmt.offsetType,
|
|
332
|
+
count: ifd.tiles.length,
|
|
333
|
+
valueBytes: new Uint8Array(ifd.tiles.length * fmt.offsetSize),
|
|
334
|
+
};
|
|
335
|
+
const tileByteCountsBytes = new Uint8Array(ifd.tiles.length * fmt.offsetSize);
|
|
336
|
+
const tbcView = new DataView(tileByteCountsBytes.buffer);
|
|
337
|
+
for (let i = 0; i < ifd.tiles.length; i++) {
|
|
338
|
+
if (fmt.offsetSize === 8) {
|
|
339
|
+
setBigUint64(tbcView, i * 8, ifd.tiles[i].length);
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
tbcView.setUint32(i * 4, ifd.tiles[i].length, true);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const tileByteCountsTag = {
|
|
346
|
+
tag: countTag,
|
|
347
|
+
type: fmt.offsetType,
|
|
348
|
+
count: ifd.tiles.length,
|
|
349
|
+
valueBytes: tileByteCountsBytes,
|
|
350
|
+
};
|
|
351
|
+
const allTags = [...userTags, tileOffsetsTag, tileByteCountsTag];
|
|
352
|
+
// Add SubIFDs tag if there are SubIFDs
|
|
353
|
+
const subIfdInfos = (ifd.subIfds ?? []).map(resolveIfdInfo);
|
|
354
|
+
if (subIfdInfos.length > 0) {
|
|
355
|
+
const subIfdsTag = {
|
|
356
|
+
tag: TAG_SUB_IFDS,
|
|
357
|
+
type: fmt.offsetType,
|
|
358
|
+
count: subIfdInfos.length,
|
|
359
|
+
valueBytes: new Uint8Array(subIfdInfos.length * fmt.offsetSize),
|
|
360
|
+
};
|
|
361
|
+
allTags.push(subIfdsTag);
|
|
362
|
+
}
|
|
363
|
+
// Sort by tag number (TIFF spec requires this)
|
|
364
|
+
allTags.sort((a, b) => a.tag - b.tag);
|
|
365
|
+
return {
|
|
366
|
+
tags: allTags,
|
|
367
|
+
tiles: ifd.tiles,
|
|
368
|
+
subIfdInfos,
|
|
369
|
+
entryBlockSize: ifdEntryBlockSize(allTags.length, fmt),
|
|
370
|
+
overflow: overflowSize(allTags, fmt),
|
|
371
|
+
tileSize: totalTileSize(ifd.tiles),
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
const mainInfos = ifds.map(resolveIfdInfo);
|
|
375
|
+
// Place IFDs sequentially
|
|
376
|
+
let cursor = fmt.headerSize;
|
|
377
|
+
function placeIfdInfo(info) {
|
|
378
|
+
const ifdOffset = cursor;
|
|
379
|
+
cursor += info.entryBlockSize;
|
|
380
|
+
const overflowOffset = cursor;
|
|
381
|
+
cursor += info.overflow;
|
|
382
|
+
const tileDataOffset = cursor;
|
|
383
|
+
cursor += info.tileSize;
|
|
384
|
+
const placed = {
|
|
385
|
+
ifdOffset,
|
|
386
|
+
tags: info.tags,
|
|
387
|
+
overflowOffset,
|
|
388
|
+
overflowSize: info.overflow,
|
|
389
|
+
tileDataOffset,
|
|
390
|
+
tiles: info.tiles,
|
|
391
|
+
subIfds: [],
|
|
392
|
+
nextIfdOffset: 0,
|
|
393
|
+
};
|
|
394
|
+
info.placed = placed;
|
|
395
|
+
allPlaced.push(placed);
|
|
396
|
+
// Place SubIFDs immediately after this IFD's tile data
|
|
397
|
+
for (const subInfo of info.subIfdInfos) {
|
|
398
|
+
placed.subIfds.push(placeIfdInfo(subInfo));
|
|
399
|
+
}
|
|
400
|
+
return placed;
|
|
401
|
+
}
|
|
402
|
+
const mainPlaced = [];
|
|
403
|
+
for (let i = 0; i < mainInfos.length; i++) {
|
|
404
|
+
mainPlaced.push(placeIfdInfo(mainInfos[i]));
|
|
405
|
+
}
|
|
406
|
+
// Link main chain next-IFD pointers
|
|
407
|
+
for (let i = 0; i < mainPlaced.length - 1; i++) {
|
|
408
|
+
mainPlaced[i].nextIfdOffset = mainPlaced[i + 1].ifdOffset;
|
|
409
|
+
}
|
|
410
|
+
return allPlaced;
|
|
411
|
+
}
|
|
412
|
+
/** Compute total file size from placed IFDs. */
|
|
413
|
+
function computeTotalSize(placed, fmt) {
|
|
414
|
+
if (placed.length === 0)
|
|
415
|
+
return fmt.headerSize;
|
|
416
|
+
let maxEnd = fmt.headerSize;
|
|
417
|
+
for (const p of placed) {
|
|
418
|
+
const end = p.tileDataOffset + totalTileSize(p.tiles);
|
|
419
|
+
if (end > maxEnd)
|
|
420
|
+
maxEnd = end;
|
|
421
|
+
}
|
|
422
|
+
return maxEnd;
|
|
423
|
+
}
|
|
424
|
+
/** Write a single placed IFD into the buffer. */
|
|
425
|
+
function writeIfd(view, buffer, placed, fmt) {
|
|
426
|
+
let pos = placed.ifdOffset;
|
|
427
|
+
const isBig = fmt.magic === 43;
|
|
428
|
+
// Write entry count
|
|
429
|
+
if (isBig) {
|
|
430
|
+
setBigUint64(view, pos, placed.tags.length);
|
|
431
|
+
pos += 8;
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
view.setUint16(pos, placed.tags.length, true);
|
|
435
|
+
pos += 2;
|
|
436
|
+
}
|
|
437
|
+
// Compute tile offsets for this IFD
|
|
438
|
+
const tileOffsets = [];
|
|
439
|
+
let tileCursor = placed.tileDataOffset;
|
|
440
|
+
for (const tile of placed.tiles) {
|
|
441
|
+
tileOffsets.push(tileCursor);
|
|
442
|
+
tileCursor += tile.length;
|
|
443
|
+
}
|
|
444
|
+
// Compute SubIFD offsets
|
|
445
|
+
const subIfdOffsets = placed.subIfds.map((s) => s.ifdOffset);
|
|
446
|
+
// Track overflow cursor
|
|
447
|
+
let overflowCursor = placed.overflowOffset;
|
|
448
|
+
// Determine which offset/bytecount tag numbers are in play
|
|
449
|
+
const isOffsetTag = (t) => t === TAG_TILE_OFFSETS || t === TAG_STRIP_OFFSETS;
|
|
450
|
+
const isByteCountTag = (t) => t === TAG_TILE_BYTE_COUNTS || t === TAG_STRIP_BYTE_COUNTS;
|
|
451
|
+
// Write each tag entry
|
|
452
|
+
for (const tag of placed.tags) {
|
|
453
|
+
if (isBig) {
|
|
454
|
+
view.setUint16(pos, tag.tag, true);
|
|
455
|
+
view.setUint16(pos + 2, tag.type, true);
|
|
456
|
+
setBigUint64(view, pos + 4, tag.count);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
view.setUint16(pos, tag.tag, true);
|
|
460
|
+
view.setUint16(pos + 2, tag.type, true);
|
|
461
|
+
view.setUint32(pos + 4, tag.count, true);
|
|
462
|
+
}
|
|
463
|
+
const valueFieldOffset = isBig ? pos + 12 : pos + 8;
|
|
464
|
+
// Determine the value bytes to write
|
|
465
|
+
let valueBytes = tag.valueBytes;
|
|
466
|
+
// Patch offset tags
|
|
467
|
+
if (isOffsetTag(tag.tag)) {
|
|
468
|
+
valueBytes = new Uint8Array(tileOffsets.length * fmt.offsetSize);
|
|
469
|
+
const dv = new DataView(valueBytes.buffer, valueBytes.byteOffset, valueBytes.byteLength);
|
|
470
|
+
for (let i = 0; i < tileOffsets.length; i++) {
|
|
471
|
+
if (fmt.offsetSize === 8) {
|
|
472
|
+
setBigUint64(dv, i * 8, tileOffsets[i]);
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
dv.setUint32(i * 4, tileOffsets[i], true);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
// Patch byte count tags — recompute from actual tile sizes
|
|
480
|
+
if (isByteCountTag(tag.tag)) {
|
|
481
|
+
valueBytes = new Uint8Array(placed.tiles.length * fmt.offsetSize);
|
|
482
|
+
const dv = new DataView(valueBytes.buffer, valueBytes.byteOffset, valueBytes.byteLength);
|
|
483
|
+
for (let i = 0; i < placed.tiles.length; i++) {
|
|
484
|
+
if (fmt.offsetSize === 8) {
|
|
485
|
+
setBigUint64(dv, i * 8, placed.tiles[i].length);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
dv.setUint32(i * 4, placed.tiles[i].length, true);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Patch SubIFDs offsets
|
|
493
|
+
if (tag.tag === TAG_SUB_IFDS && subIfdOffsets.length > 0) {
|
|
494
|
+
valueBytes = new Uint8Array(subIfdOffsets.length * fmt.offsetSize);
|
|
495
|
+
const dv = new DataView(valueBytes.buffer, valueBytes.byteOffset, valueBytes.byteLength);
|
|
496
|
+
for (let i = 0; i < subIfdOffsets.length; i++) {
|
|
497
|
+
if (fmt.offsetSize === 8) {
|
|
498
|
+
setBigUint64(dv, i * 8, subIfdOffsets[i]);
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
dv.setUint32(i * 4, subIfdOffsets[i], true);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (valueBytes.length <= fmt.inlineThreshold) {
|
|
506
|
+
// Inline: write value bytes directly in the value/offset field
|
|
507
|
+
const dest = new Uint8Array(buffer, valueFieldOffset, fmt.inlineThreshold);
|
|
508
|
+
dest.fill(0);
|
|
509
|
+
dest.set(valueBytes);
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
// Overflow: write offset to overflow area, then write bytes there
|
|
513
|
+
if (fmt.offsetSize === 8) {
|
|
514
|
+
setBigUint64(view, valueFieldOffset, overflowCursor);
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
view.setUint32(valueFieldOffset, overflowCursor, true);
|
|
518
|
+
}
|
|
519
|
+
const dest = new Uint8Array(buffer, overflowCursor, valueBytes.length);
|
|
520
|
+
dest.set(valueBytes);
|
|
521
|
+
overflowCursor += valueBytes.length;
|
|
522
|
+
// Pad to word boundary
|
|
523
|
+
if (valueBytes.length % 2 !== 0)
|
|
524
|
+
overflowCursor += 1;
|
|
525
|
+
}
|
|
526
|
+
pos += fmt.ifdEntrySize;
|
|
527
|
+
}
|
|
528
|
+
// Write next IFD offset
|
|
529
|
+
if (isBig) {
|
|
530
|
+
setBigUint64(view, pos, placed.nextIfdOffset);
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
view.setUint32(pos, placed.nextIfdOffset, true);
|
|
534
|
+
}
|
|
535
|
+
// Write tile data
|
|
536
|
+
let tilePos = placed.tileDataOffset;
|
|
537
|
+
for (const tile of placed.tiles) {
|
|
538
|
+
const dest = new Uint8Array(buffer, tilePos, tile.length);
|
|
539
|
+
dest.set(tile);
|
|
540
|
+
tilePos += tile.length;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
// ── Convenience helpers for building IFD tags ───────────────────────
|
|
544
|
+
/**
|
|
545
|
+
* Create a standard set of tags for a tiled grayscale image plane.
|
|
546
|
+
*
|
|
547
|
+
* @param width - Image width in pixels.
|
|
548
|
+
* @param height - Image height in pixels.
|
|
549
|
+
* @param bitsPerSample - Bits per sample (8, 16, 32, 64).
|
|
550
|
+
* @param sampleFormat - TIFF SampleFormat (1=uint, 2=int, 3=float).
|
|
551
|
+
* @param compression - Compression type. Default: "none".
|
|
552
|
+
* @param imageDescription - Optional OME-XML string for the first IFD.
|
|
553
|
+
* @param isSubResolution - Whether this is a SubIFD (sets NewSubfileType=1).
|
|
554
|
+
* @param tileSize - Tile width and height. Default: 256. Use 0 for strip-based.
|
|
555
|
+
*/
|
|
556
|
+
export function makeImageTags(width, height, bitsPerSample, sampleFormat, compression = "none", imageDescription, isSubResolution, tileSize = DEFAULT_TILE_SIZE) {
|
|
557
|
+
const tags = [];
|
|
558
|
+
if (isSubResolution) {
|
|
559
|
+
tags.push({ tag: TAG_NEW_SUBFILE_TYPE, type: TIFF_TYPE_LONG, values: [1] });
|
|
560
|
+
}
|
|
561
|
+
tags.push({ tag: TAG_IMAGE_WIDTH, type: TIFF_TYPE_LONG, values: [width] });
|
|
562
|
+
tags.push({ tag: TAG_IMAGE_LENGTH, type: TIFF_TYPE_LONG, values: [height] });
|
|
563
|
+
tags.push({ tag: TAG_BITS_PER_SAMPLE, type: TIFF_TYPE_SHORT, values: [bitsPerSample] });
|
|
564
|
+
tags.push({
|
|
565
|
+
tag: TAG_COMPRESSION,
|
|
566
|
+
type: TIFF_TYPE_SHORT,
|
|
567
|
+
values: [compression === "deflate" ? COMPRESSION_DEFLATE : COMPRESSION_NONE],
|
|
568
|
+
});
|
|
569
|
+
tags.push({ tag: TAG_PHOTOMETRIC, type: TIFF_TYPE_SHORT, values: [1] }); // MinIsBlack
|
|
570
|
+
tags.push({ tag: TAG_SAMPLES_PER_PIXEL, type: TIFF_TYPE_SHORT, values: [1] });
|
|
571
|
+
tags.push({ tag: TAG_PLANAR_CONFIGURATION, type: TIFF_TYPE_SHORT, values: [1] }); // chunky
|
|
572
|
+
tags.push({ tag: TAG_SAMPLE_FORMAT, type: TIFF_TYPE_SHORT, values: [sampleFormat] });
|
|
573
|
+
if (tileSize > 0 && (width > tileSize || height > tileSize)) {
|
|
574
|
+
// Tiled layout
|
|
575
|
+
tags.push({ tag: TAG_TILE_WIDTH, type: TIFF_TYPE_LONG, values: [tileSize] });
|
|
576
|
+
tags.push({ tag: TAG_TILE_LENGTH, type: TIFF_TYPE_LONG, values: [tileSize] });
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
// Strip layout (single strip = entire plane) for small images
|
|
580
|
+
tags.push({ tag: TAG_ROWS_PER_STRIP, type: TIFF_TYPE_LONG, values: [height] });
|
|
581
|
+
}
|
|
582
|
+
if (imageDescription) {
|
|
583
|
+
tags.push({ tag: TAG_IMAGE_DESCRIPTION, type: TIFF_TYPE_ASCII, values: imageDescription });
|
|
584
|
+
}
|
|
585
|
+
return tags;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Slice a 2D pixel plane into tiles suitable for TIFF tiled output.
|
|
589
|
+
*
|
|
590
|
+
* Tiles that extend beyond the image boundary are zero-padded to the
|
|
591
|
+
* full tile size (required by the TIFF spec for tiled images).
|
|
592
|
+
*
|
|
593
|
+
* @param planeBytes - Raw pixel data for the entire plane (row-major, little-endian).
|
|
594
|
+
* @param width - Image width in pixels.
|
|
595
|
+
* @param height - Image height in pixels.
|
|
596
|
+
* @param bytesPerPixel - Bytes per pixel (e.g. 2 for uint16).
|
|
597
|
+
* @param tileW - Tile width in pixels.
|
|
598
|
+
* @param tileH - Tile height in pixels.
|
|
599
|
+
* @returns Array of tile buffers, in row-major tile order (left-to-right, top-to-bottom).
|
|
600
|
+
*/
|
|
601
|
+
export function sliceTiles(planeBytes, width, height, bytesPerPixel, tileW, tileH) {
|
|
602
|
+
const tilesX = Math.ceil(width / tileW);
|
|
603
|
+
const tilesY = Math.ceil(height / tileH);
|
|
604
|
+
const tiles = [];
|
|
605
|
+
const rowBytes = width * bytesPerPixel;
|
|
606
|
+
const tileRowBytes = tileW * bytesPerPixel;
|
|
607
|
+
const tileBytes = tileW * tileH * bytesPerPixel;
|
|
608
|
+
for (let ty = 0; ty < tilesY; ty++) {
|
|
609
|
+
for (let tx = 0; tx < tilesX; tx++) {
|
|
610
|
+
const tile = new Uint8Array(tileBytes); // zero-filled (handles padding)
|
|
611
|
+
const startY = ty * tileH;
|
|
612
|
+
const startX = tx * tileW;
|
|
613
|
+
// Number of valid rows/cols in this tile
|
|
614
|
+
const validRows = Math.min(tileH, height - startY);
|
|
615
|
+
const validCols = Math.min(tileW, width - startX);
|
|
616
|
+
const validRowBytes = validCols * bytesPerPixel;
|
|
617
|
+
for (let row = 0; row < validRows; row++) {
|
|
618
|
+
const srcOffset = (startY + row) * rowBytes + startX * bytesPerPixel;
|
|
619
|
+
const dstOffset = row * tileRowBytes;
|
|
620
|
+
tile.set(planeBytes.subarray(srcOffset, srcOffset + validRowBytes), dstOffset);
|
|
621
|
+
}
|
|
622
|
+
tiles.push(tile);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return tiles;
|
|
626
|
+
}
|
|
627
|
+
// ── BigTIFF helpers ─────────────────────────────────────────────────
|
|
628
|
+
/**
|
|
629
|
+
* Write a 64-bit unsigned integer to a DataView at the given offset.
|
|
630
|
+
* Uses two 32-bit writes since DataView.setBigUint64 may not be
|
|
631
|
+
* available in all environments.
|
|
632
|
+
*/
|
|
633
|
+
function setBigUint64(view, offset, value) {
|
|
634
|
+
// Split into low 32 bits and high 32 bits (little-endian)
|
|
635
|
+
const lo = value >>> 0;
|
|
636
|
+
const hi = (value / 0x1_0000_0000) >>> 0;
|
|
637
|
+
view.setUint32(offset, lo, true);
|
|
638
|
+
view.setUint32(offset + 4, hi, true);
|
|
639
|
+
}
|
|
640
|
+
//# sourceMappingURL=tiff-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tiff-writer.js","sourceRoot":"","sources":["../src/tiff-writer.ts"],"names":[],"mappings":"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"}
|