tiffwriter
v0.1.7
Published
TIFF / BigTIFF container writer for the browser
Maintainers
Readme
tiffwriter
TIFF / BigTIFF container writer for the browser. You supply tile bytes; this package writes headers, IFDs, tags, offsets, and SubIFDs. No codecs, transforms, or OME generation. BigTIFF by default (format: "classic" when needed).
Developed for Minerva (usage).
AI assistance: Much of this package (and docs) was written with AI coding tools. Review the code and validate outputs before relying on them in production.
Install
pnpm add tiffwriterAddressed API
import {
browserFileSink,
createTiffWriter,
grayscaleDeflateTags,
grayscaleTags,
TIFF_COMPRESSION,
type PlanPyramidJob,
planPyramid,
} from "tiffwriter";
const { layouts, jobs } = planPyramid({
levels: [
{ width: 1024, height: 1024, tileSize: 256 },
{ width: 512, height: 512, tileSize: 256 },
],
channelCount: 2,
baseTags: grayscaleDeflateTags(16),
// or: grayscaleTags({ compression: TIFF_COMPRESSION.JPEG, bitsPerSample: 8 })
imageDescription: omeXml, // optional; first IFD only
});
const writer = await createTiffWriter({
sink: browserFileSink(writable),
images: layouts,
signal, // optional
});
try {
// concurrency pool over jobs → encode → writeSegment
await writer.writeSegment(job.address, jpegBytes);
await writer.finish();
} catch (e) {
await writer.abort(e);
throw e;
}Jobs carry address, x, y, index, channelIndex, levelIndex. Do not mutate bytes until writeSegment resolves. Use tileSize for square tiles, or tileWidth/tileHeight when they differ.
Sequential API
For ordered iterators (tests, demos):
import { writeTiff, tiffTag, memorySink } from "tiffwriter";
await writeTiff({
sink: memorySink(),
images: [
{
width: 64,
height: 64,
segments: {
kind: "tiles",
tileWidth: 64,
tileHeight: 64,
data: [new Uint8Array(64 * 64).fill(128)],
},
tags: [
tiffTag("BitsPerSample", "SHORT", 8),
tiffTag("Compression", "SHORT", 1),
tiffTag("PhotometricInterpretation", "SHORT", 1),
tiffTag("SamplesPerPixel", "SHORT", 1),
],
},
],
});Exports
| Symbol | Use |
| --- | --- |
| createTiffWriter, planPyramid, PlanPyramidJob | addressed / concurrent writes |
| grayscaleTags | planar grayscale sample tags (compression, bitsPerSample, optional sampleFormat / predictor) |
| grayscaleJpegTags | preset: 8-bit JPEG (Compression=7) |
| grayscaleDeflateTags | preset: unsigned zlib/Deflate (Compression=8, bits 8 / 16 / 32) |
| TIFF_COMPRESSION | NONE / LZW / JPEG / DEFLATE codes for grayscaleTags |
| browserFileSink | browsers |
| writeTiff, memorySink | sequential / tests |
| tiffTag, TIFF_TAG_IDS | custom tags beyond the preset |
New codecs stay codec-free here: encode tiles yourself, then grayscaleTags({ compression: TIFF_COMPRESSION.LZW, bitsPerSample: 16 }) (or a raw TIFF code). JPEG and Deflate presets wrap that helper.
Tile-grid helpers are not public.
Development
pnpm install && pnpm run check && pnpm run buildAttribution
IFD/tag layout ideas adapted from @fideus-labs/fiff (MIT), as used in Minerva. See NOTICE.
License
MIT
