An extended fork of tifffile by Christoph Gohlke, adding a C++ acceleration layer, GPU support, camera calibration storage, and a modular architecture.
The PyPI package name is tifx, but the Python import name remains
tifffile for full compatibility with existing code:
pip install tifx python -c "import tifffile; print(tifffile.__version__)"
The original tifffile library is a Python library to store NumPy arrays in TIFF files and read image and metadata from TIFF-like files used in bioimaging. It supports 20+ proprietary microscopy and pathology formats, BigTIFF, OME-TIFF, ImageJ hyperstacks, Zarr integration, and 30+ compression codecs via imagecodecs. All original functionality is preserved.
- Original tifffile code: BSD-3-Clause, copyright (c) 2008-2026
Christoph Gohlke. Files retaining the original copyright header
(
tifffile.py,zarr.py,test_tifffile.py). - New modules in this fork: MIT, copyright (c) 2025-2026 napachan. All new files (camera, gpu, C++ extension, extracted modules, etc.).
See the LICENSE file for full text of both licenses.
An optional C++ extension (nanobind) accelerates the hot paths in TIFF
parsing. It is fully optional -- set TIFFFILE_NO_CPP=1 to disable.
| Operation | C++ | Python | Speedup |
|---|---|---|---|
| Series parsing (30K pages) | 46 ms | 1,872 ms | 41x |
len(pages) (30K) |
3.6 ms | 20 ms | 5.6x |
len(pages) (100K) |
14 ms | 73 ms | 5.1x |
| Iterate 30K pages | 0.8 ms | 1,574 ms | 1,968x |
Key functions: scan_ifd_chain_file (mmap-based IFD chain scan),
bulk_extract_tag_values (GIL-free bulk tag extraction),
parse_ifd / parse_ifd_filtered (single-pass IFD parsing),
selection_to_page_indices, compute_segment_positions.
Build from source:
pip install . --no-build-isolation
Requires: C++17 compiler, CMake, scikit-build-core, nanobind.
tifffile.camera stores full computer-vision camera calibration in TIFF
files using private tags 65201-65207 with a COLMAP-compatible convention.
- 18 camera models (COLMAP IDs 0-15 + equirectangular + cubemap)
- Per-frame extrinsics, filenames, timestamps, and GPS coordinates
- Two storage modes: bulk (all frames in first IFD) or per-IFD (each page self-describing with its own complete tags)
- Bridge methods:
to_transforms_json/from_transforms_json(NeRF),to_pycolmap/from_pycolmap,to_opencv/from_opencv
Bulk mode (all frames packed in first IFD):
from tifffile import TiffWriter, TiffFile
from tifffile.camera import CameraModel, camera_extratags, read_camera
tags = camera_extratags(
model=CameraModel.OPENCV,
width=640, height=480,
intrinsics=[500.0, 500.0, 320.0, 240.0],
distortion=[-0.1, 0.01, 0.001, -0.001],
extrinsics=poses,
filenames=['frame_00.png', 'frame_01.png'],
timestamps=timestamps,
gps=gps_coords,
)
with TiffWriter('calibrated.tif') as tw:
tw.write(images, extratags=tags)Per-IFD mode (each page carries its own camera parameters):
from tifffile.camera import camera_frame_extratags
with TiffWriter('calibrated.tif') as tw:
for i in range(N):
tags = camera_frame_extratags(
model=CameraModel.OPENCV,
width=640, height=480,
intrinsics=[500.0, 500.0, 320.0, 240.0],
distortion=[-0.1, 0.01, 0.001, -0.001],
extrinsic=poses[i],
filename=f'frame_{i:04d}.png',
timestamp=timestamps[i],
gps=gps_coords[i],
)
tw.write(images[i], extratags=tags)Reading auto-detects the storage mode:
with TiffFile('calibrated.tif') as tif:
cam = read_camera(tif)
K, dist = cam.to_opencv()
transforms = cam.to_transforms_json()tifffile.gpu provides optional GPU support via PyTorch, with additional
NVIDIA library integration (nvCOMP, nvImageCodec, kvikio). All GPU
dependencies are lazily imported -- zero cost when unused.
- Read images directly to GPU tensors:
page.asarray(device='cuda') - GPUDirect Storage on Linux (kvikio) for zero-copy file-to-GPU transfer
- GPU compression (Zstd via nvCOMP) for write on planes >= 48 MB
- GPU decompression registry: Zstd, JPEG, JPEG 2000
FileHandle.read_segments() uses mmap for zero-copy memoryview slicing,
providing 2-3x faster reads for tiled images. Includes a workaround for a
Windows bug where mmap on the same fd corrupts subsequent seek+read.
The original monolithic tifffile.py (~24,000 lines) has been decomposed
into focused single-responsibility modules. All 75 public symbols remain
importable via from tifffile import *.
| Module | Lines | Contents |
|---|---|---|
tifffile.py |
10,669 | TiffFile, TiffWriter, core constants |
page.py |
3,699 | TiffPage, TiffFrame, TiffPages (C++ fast paths) |
metadata.py |
3,437 | OmeXml, 30+ metadata reader functions |
sequences.py |
2,098 | TiffPageSeries, FileSequence, mmap contiguous read |
utils.py |
1,763 | Helper functions, TiffFileError |
fileio.py |
1,455 | FileHandle (mmap), FileCache, Timer, StoredShape |
tags.py |
1,251 | TiffTag, TiffTags, TiffTagRegistry |
camera.py |
1,070 | Camera calibration, CameraData, bridge methods |
gpu.py |
694 | GPU read/write, codec registries |
decoders.py |
621 | build_decode_closure (C++ segment positions) |
codecs.py |
434 | TiffFormat, CompressionCodec, PredictorCodec |
enums.py |
367 | 13 IntEnum classes |
series.py |
162 | SeriesParser base, SeriesParserRegistry |
series_parsers/ |
2,616 | 21 format-specific parsers across 7 files |
| C++ extension | 1,963 | nanobind bindings, IFD parser, file reader |
Series detection is now plugin-based. SeriesParserRegistry dispatches
to 21 format-specific parsers in priority order, with a generic fallback.
GenericSeriesParser._parse_fast() uses C++ bulk tag extraction for
files with 100+ pages, enabling the 41x series parsing speedup.
Supported formats: OME-TIFF, ImageJ, LSM, SVS, SCN, NDPI, BIF, Philips, QPI, STK, FluoView, ScanImage, MicroManager, NDTiff, NIH, EER, MDGEL, AVS, SIS, and generic/shaped/uniform fallbacks.
All original tifffile features are preserved:
- Read/write TIFF, BigTIFF, OME-TIFF, ImageJ hyperstacks
- 20+ proprietary format readers (microscopy, pathology, remote sensing)
- 30+ compression codecs via imagecodecs
- Zarr store integration, fsspec ReferenceFileSystem
- Multi-page, volumetric, pyramidal, tiled, memory-mappable I/O
- Tag inspection, patching, and multi-dimensional file sequences
For the full original documentation, examples, and API reference, see the upstream project.
Install from PyPI (includes pre-built C++ extension for Linux, macOS, Windows):
pip install tifx
Or install from source (requires C++17 compiler):
pip install . --no-build-isolation
The Python import name is tifffile (not tifx), so existing code
works unchanged:
python -c "import tifffile; help(tifffile)"
- CPython 3.11+
- NumPy 2.0+
- Imagecodecs (required for encoding or decoding compressed segments)
Optional:
- C++17 compiler + CMake + scikit-build-core + nanobind (for C++ extension)
- PyTorch (for GPU support)
- pycolmap (for camera calibration pycolmap bridge)
Original tifffile library by Christoph Gohlke (GitHub, DOI: 10.5281/zenodo.6795860). Original code licensed under BSD-3-Clause. New modules licensed under MIT. See LICENSE for details.