Skip to content

napachan/tifx

Repository files navigation

tifx

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.

License

  • 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.

New Features

C++ Extension (Performance)

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.

Camera Calibration Module

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()

GPU Acceleration

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

mmap Optimization

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.

Modular Architecture

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 Parser Plugin System

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.

Original Functionality

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.

Quickstart

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)"

Requirements

Optional:

  • C++17 compiler + CMake + scikit-build-core + nanobind (for C++ extension)
  • PyTorch (for GPU support)
  • pycolmap (for camera calibration pycolmap bridge)

Credits

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.

About

Tifffiles 2-50x faster

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors