rustafits
High-performance FITS to JPEG converter for astronomical images with QuickFits/PixInsight-compatible auto-stretch and Bayer debayering.
Features
- Auto-Stretch: Median-based statistical stretching (robust to outliers)
- Bayer Debayering: Super-pixel 2×2 block averaging (RGGB, BGGR, GBRG, GRBG)
- Preview Mode: 2×2 binning for mono images (4× fewer pixels, ~90ms processing)
- Fast: 60-100ms for 4096×4096 images (Quickselect + SIMD + compiler optimizations)
- Multi-Platform SIMD: ARM NEON + x86_64 SSE2 with automatic selection
Installation
From crates.io (Recommended - All Platforms)
Homebrew (macOS/Linux)
Debian/Ubuntu
# Download .deb from releases
Arch Linux (AUR)
# or
Fedora/RHEL/CentOS
# Download .rpm or add COPR repository (coming soon)
From Source
Prerequisites:
# macOS
# Debian/Ubuntu
# Fedora/RHEL
# Rust (1.70+)
# Install from https://rustup.rs/
Build:
Usage
CLI
# Basic conversion
# Fast preview (mono with binning)
# Quick preview (downscaled)
# Full quality
# Options
)
)
)
Rust Library
Add to Cargo.toml:
[]
= { = "<repo-url>" }
Basic usage:
use FitsConverter;
Processing Pipeline
FITS Reading → Downscaling (optional) → Debayering (if Bayer) →
Auto-Stretch → Orientation Correction → JPEG Encoding
Key Steps:
- FITS Reading: CFITSIO loads 16-bit/32-bit data + metadata (BAYERPAT, ROWORDER)
- Debayering: Super-pixel 2×2 → RGB (no interpolation, 3-5× faster than bilinear)
- Auto-Stretch: Median + MADN-based parameter calculation, per-channel transformation
- JPEG Encoding: stb_image_write with configurable quality
Performance
Benchmarks
Test: 6252×4176 16-bit images on Apple M4
| Mode | Resolution | Time | Speedup |
|---|---|---|---|
| Mono (full) | 6252×4176 | ~220ms | Baseline |
| Mono (preview) | 3126×2088 | ~90ms | 2.4× |
| RGB (debayered) | 3124×2088 | ~100ms | 2.2× |
Optimizations
- Algorithmic: Quickselect O(n) median vs qsort O(n log n) — 20-30% faster
- SIMD: ARM NEON / x86_64 SSE2 vectorization (4 floats/cycle) — 15-25% faster
- Compiler:
-O3 -march=native -ffast-math - Preview Mode: 2×2 binning for mono images — 2.4× faster
Libraries:
- CFITSIO: NASA's FITS I/O library (handles all formats, compression)
- stb_image_write: Single-header JPEG encoder (MIT/public domain)
Architecture
Rust CLI (rustafits) → Rust Wrapper (src/lib_c.rs) → C Core (c_src/)
Why C + Rust?
- C: Performance-critical processing, direct CFITSIO access
- Rust: Safe API, error handling, easy distribution
Project Structure:
rustafits/
├── src/
│ ├── lib.rs # Library entry point
│ ├── lib_c.rs # Rust FFI wrapper
│ └── bin/
│ └── rustafits.rs # CLI tool
├── c_src/
│ ├── fits_processor.c # Main pipeline
│ ├── fits_processor.h # C API
│ └── jpeg_writer.c # JPEG encoding
├── ffi/
│ ├── debayer.c # Bayer algorithms
│ └── stretch.c # Auto-stretch
├── Cargo.toml
└── build.rs # Compiles C code
Troubleshooting
"Failed to find cfitsio library"
Slow conversion (>500ms)
- Use
--previewfor mono images - Use
--downscale 2or4for quick previews
Black/white output
- Run with
--logto see stretch parameters - Input may be all zeros or very uniform
References
- QuickLook.Plugin.FitsViewer: Original auto-stretch implementation (Siyu Zhang, GPL-3.0)
- PixInsight: Screen Transfer Function documentation
- CFITSIO: https://heasarc.gsfc.nasa.gov/fitsio/
- FITS Standard: https://fits.gsfc.nasa.gov/
License
Implements algorithms from GPL-3.0 licensed QuickLook.Plugin.FitsViewer.