@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.
@@ -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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"}