Part of the QPSC (QuPath Scope Control) system For complete installation instructions and system overview, see: https://github.com/uw-loci/QPSC
A basic image stitching extension for QuPath that combines multiple image tiles into seamless pyramidal images. This extension supports multiple stitching strategies, dual output formats (OME-TIFF and OME-ZARR), and is designed for high-throughput microscopy workflows.
- Multiple Stitching Strategies: Support for filename-based coordinates, TileConfiguration.txt files, and Vectra metadata
- Dual Output Formats: Choose between traditional OME-TIFF or cloud-native OME-ZARR
- Pyramidal Output: Generates multi-resolution pyramids for efficient viewing at all scales
- Flexible Compression: Supports various compression formats (TIFF: JPEG, LZW, ZIP; ZARR: zstd, lz4, blosc)
- Cloud-Native ZARR: Directory-based format optimized for cloud storage and parallel access
- Batch Processing: Process multiple slides simultaneously with matching criteria
- Multi-subdirectory Support: Automatically creates separate outputs for each matched subdirectory
- Robust Error Handling: Comprehensive logging and validation for troubleshooting
- Memory Efficient: Optimized for large datasets with configurable downsampling
- Parallel Writing: ZARR format utilizes multi-threaded tile writing for faster output
- QuPath: Version 0.6.0 or greater
- Java: Java 11 or higher
- Memory: Recommended 8GB+ RAM for large image datasets
- Download the latest
.jarfile from the Releases page - Copy the JAR file to your QuPath extensions directory:
- Windows:
%USERPROFILE%/QuPath/extensions - macOS:
~/QuPath/extensions - Linux:
~/QuPath/extensions
- Windows:
- Restart QuPath
Alternatively, drag and drop the extension into QuPath.
git clone https://github.com/yourusername/qupath-basic-stitching.git
cd qupath-basic-stitching
./gradlew build
# Copy build/libs/qupath-extension-basic-stitching-*.jar to your QuPath extensions directoryDevelopers of qpsc may want to also run the following to enable working with qpsc in IntelliJ.
./gradlew publishToMavenLocal
- Open QuPath
- Navigate to Extensions β Basic Stitching β Stitch Images
- The stitching dialog will open
For images with coordinates embedded in filenames:
image_tile[1000,2000].tif
image_tile[1500,2000].tif
image_tile[1000,2500].tif
Usage:
- Select folder containing subdirectories with tiles
- Coordinates in brackets represent physical positions in microns
- Extension automatically calculates tile positions and overlaps
For ImageJ/Fiji tile configuration format:
# Define the number of dimensions we are working on
dim = 2
# Define the image coordinates
tile_001.tif; ; (0.0, 0.0)
tile_002.tif; ; (1024.0, 0.0)
tile_003.tif; ; (0.0, 1024.0)
tile_004.tif; ; (1024.0, 1024.0)
Usage:
- Each subdirectory must contain a
TileConfiguration.txtfile - Coordinates represent pixel positions
- Automatically scaled based on pixel size and downsample settings
Batch Processing Multiple Subdirectories: When the matching string matches multiple subdirectories, each subdirectory is stitched independently:
input_folder/bounds/
βββ -5.0/
β βββ TileConfiguration.txt
β βββ [tile files]
βββ 0.0/
β βββ TileConfiguration.txt
β βββ [tile files]
βββ 5.0/
βββ TileConfiguration.txt
βββ [tile files]
With matching string "." results in:
-5.0.ome.tif0.0.ome.tif5.0.ome.tif
For Akoya/PerkinElmer Vectra imaging systems:
- Reads positioning information directly from TIFF metadata tags
- Uses
TAG_X_POSITION,TAG_Y_POSITION, and resolution tags - No additional configuration files required
| Parameter | Description | Default |
|---|---|---|
| Input Folder | Root directory containing image subdirectories | Required |
| Output Folder | Directory for stitched output files | Required |
| Pixel Size (ΞΌm) | Physical size of each pixel in microns | 0.5 |
| Base Downsample | Downsampling factor for output | 1.0 |
| Compression | Compression algorithm (TIFF: LZW, JPEG; ZARR: zstd, lz4) | LZW |
| Output Format | OME-TIFF (single file) or OME-ZARR (directory) | OME-TIFF |
| Matching String | Filter subdirectories by name pattern. Use "." to process all subdirectories separately | "" (all) |
| Z-Spacing (ΞΌm) | Z-axis spacing for 3D datasets | 1.0 |
- Structure: Single pyramidal TIFF file
- Compatibility: Widely supported by QuPath, ImageJ, and most imaging software
- Use Case: General purpose, local storage, maximum compatibility
- Extension:
.ome.tif - Compression: LZW, JPEG, JPEG-2000, Uncompressed
- Best For: Desktop workflows, maximum software compatibility
- Structure: Directory containing chunked arrays
- Compatibility: QuPath 0.6.0+, napari, Python imaging libraries
- Use Case: Cloud storage, large datasets, parallel processing
- Extension:
.ome.zarr(directory) - Compression: zstd (best balance), lz4 (fastest), lz4hc, blosclz, zlib
- Best For: Cloud storage, collaborative access, very large images (> 10GB)
Key Advantages of ZARR:
- Faster Writing: Multi-threaded tile writing (typically 2-3x faster than TIFF)
- Better Compression: Blosc/zstd compression achieves 20-30% smaller files than LZW
- Cloud-Optimized: Native support for S3, Azure Blob, Google Cloud Storage
- Partial Access: Read specific regions without downloading entire file
- Parallel Processing: Multiple processes can read different regions simultaneously
- Progress Tracking: Per-tile progress callbacks for better user feedback
Compression Recommendations:
- zstd (default): Best balance of speed and compression ratio
- lz4: Fastest compression/decompression, slightly larger files
- lz4hc: Better compression than lz4, slower writing
- zlib: Compatible with standard zip compression
- blosclz: Optimized for binary data
When to Use ZARR:
- Stitched images > 5GB in size
- Cloud storage or collaborative workflows
- High-throughput batch processing
- Need for parallel data access
- Long-term archival with cloud backup
When to Use OME-TIFF:
- Need maximum software compatibility
- Working with legacy analysis pipelines
- Smaller images (< 2GB)
- Desktop-only workflows
- Sharing with users without ZARR support
// Programmatic usage example - traditional OME-TIFF output
StitchingConfig config = new StitchingConfig(
"Filename[x,y] with coordinates in microns", // Strategy
"/path/to/input/folder", // Input path
"/path/to/output/folder", // Output path
"LZW", // Compression
0.5, // Pixel size (ΞΌm)
1.0, // Base downsample
"slide", // Matching string
1.0, // Z-spacing (ΞΌm)
StitchingConfig.OutputFormat.OME_TIFF // Output format
);
String result = StitchingWorkflow.run(config);// High-performance ZARR output with fast compression
StitchingConfig config = new StitchingConfig(
"Coordinates in TileConfiguration.txt file",
"/data/microscopy/slides",
"/data/output/stitched",
"zstd", // ZARR compression (fast + good ratio)
0.25, // 0.25 ΞΌm/pixel
1.0, // Base downsample
".", // Process all subdirectories
1.0, // Z-spacing
StitchingConfig.OutputFormat.OME_ZARR // ZARR format
);
String result = StitchingWorkflow.run(config);
// Output: multiple .ome.zarr directories, one per subdirectoryStitchingConfig config = new StitchingConfig(
"Coordinates in TileConfiguration.txt file",
"/data/microscopy/slides",
"/data/output/stitched",
"JPEG", // TIFF compression
0.25, // 0.25 ΞΌm/pixel
4.0, // 4x downsample
"H&E", // Process only H&E slides
1.0,
StitchingConfig.OutputFormat.OME_TIFF // Traditional TIFF
);
String result = StitchingWorkflow.run(config);For workflows with multiple rotation angles stored in separate folders:
bounds/
βββ -5.0/
β βββ TileConfiguration.txt
β βββ [9 tiles]
βββ 0.0/
β βββ TileConfiguration.txt
β βββ [9 tiles]
βββ 5.0/
βββ TileConfiguration.txt
βββ [9 tiles]
Using matching string "." will create three separate stitched images, one for each angle.
input_folder/
βββ slide001_tumor/
β βββ tile_001[0,0].tif
β βββ tile_002[1000,0].tif
β βββ tile_003[0,1000].tif
βββ slide002_normal/
β βββ tile_001[0,0].tif
β βββ tile_002[1000,0].tif
βββ slide003_control/
βββ TileConfiguration.txt
βββ image_001.tif
βββ image_002.tif
Output files are named based on the subdirectory being processed:
- When matching string equals folder name: uses folder name
- When processing multiple subdirectories: each gets its own output file named after the subdirectory
output_folder/
βββ slide001_tumor.ome.tif
βββ slide002_normal.ome.tif
βββ slide003_control.ome.tif
When processing subdirectories:
output_folder/
βββ -5.0.ome.tif
βββ 0.0.ome.tif
βββ 5.0.ome.tif
- Large Datasets: Use higher downsample values (2x, 4x) for initial processing
- RAM Usage: Monitor memory usage; increase JVM heap size if needed:
java -Xmx16G -jar QuPath.jar
- Parallel Processing: Extension automatically uses multiple CPU cores
- SSD Storage: Use SSD drives for input/output to improve I/O performance
- Network Storage: Avoid network drives for temporary processing
- Small Tiles (< 2048px): Fast processing, more metadata overhead
- Large Tiles (> 8192px): Slower processing, less overhead
- Optimal Range: 2048-4096 pixels per tile dimension
- Cause: Directory structure doesn't match expected format
- Solution: Verify subdirectory naming and tile file patterns
- Check: Enable debug logging to see which directories are processed
- Cause: Corrupted or unsupported image format
- Solution: Verify TIFF files are valid and readable
- Check: Test individual files in QuPath or ImageJ
- Cause: TileConfiguration.txt references files not present in directory
- Solution: Ensure all referenced files exist and names match exactly
- Check: Case sensitivity on Linux/macOS systems
- Cause: Using substring matching that matches unintended folders
- Solution: Use exact matching or "." to process each subdirectory separately
- Example: "5.0" matches both "5.0" and "-5.0"; use "." instead
- Cause: Insufficient JVM heap space for large datasets
- Solution: Increase heap size or use higher downsample values
- Command:
java -Xmx16G -jar QuPath.jar
Enable detailed logging by setting log level to DEBUG:
# In QuPath logging configuration
logger.qupath.ext.basicstitching=DEBUG- File Integrity: Verify all input TIFF files open correctly
- Coordinate Extraction: Check log output for parsed coordinates
- Directory Matching: Confirm subdirectories match the filtering criteria
- Output Verification: Open resulting OME-TIFF in QuPath to verify stitching quality
Main coordination class for stitching operations.
Key Methods:
stitchCore(): Primary stitching methodsetStitchingStrategy(): Configure stitching algorithm
FileNameStitchingStrategy: Parse coordinates from filenamesTileConfigurationTxtStrategy: Read ImageJ tile configurationsVectraMetadataStrategy: Extract Vectra TIFF metadata
The extension supports custom stitching strategies by implementing the StitchingStrategy interface:
public interface StitchingStrategy {
List<Map<String, Object>> prepareStitching(
String folderPath,
double pixelSizeInMicrons,
double baseDownsample,
String matchingString
);
}We welcome contributions! Please see our Contributing Guidelines for details.
git clone https://github.com/yourusername/qupath-basic-stitching.git
cd qupath-basic-stitching
./gradlew build
./gradlew test- Follow standard Java conventions
- Add comprehensive logging for debugging
- Include unit tests for new functionality
- Update documentation for API changes
This project is licensed under the MIT license - see the LICENSE file for details.
If you use this extension in your research, please cite:
@software{qupath_basic_stitching,
title={QuPath Basic Stitching Extension},
author={Your Name},
year={2025},
url={https://github.com/yourusername/qupath-basic-stitching},
version={1.0.0}
}- Issues: Report bugs and feature requests via GitHub Issues
- Discussions: Join the conversation in GitHub Discussions
- QuPath Forum: Get help from the community at image.sc
- NEW: OME-ZARR output format support (cloud-native, directory-based)
- NEW: Multi-threaded parallel tile writing for ZARR format
- NEW: Advanced compression options (zstd, lz4, lz4hc, blosclz)
- NEW: Per-tile progress tracking for ZARR writes
- ENHANCED: GUI now includes output format selection dropdown
- ENHANCED: Automatic compression mapping (TIFF types to ZARR equivalents)
- ENHANCED: Comprehensive unit tests for format support
- PERFORMANCE: 2-3x faster writing speed with ZARR parallel processing
- PERFORMANCE: 20-30% smaller file sizes with Blosc compression
- Backward compatible: existing code defaults to OME-TIFF format
- Initial Java conversion from Groovy implementation
- Support for QuPath 0.6.0+
- Three stitching strategies implemented
- Multi-subdirectory batch processing with separate outputs
- Comprehensive error handling and logging
- Performance optimizations for large datasets