XISF Image Library for Swift.
This library provides a simple interface to read XISF (Extensible Image Serialization Format) files in Swift, based on the XISF 1.0 specification. XISF is the native image format of PixInsight.
It is a natural counterpart to SwiftFITS: a single
XISFFile entry point, opened from a URL or Data, exposes the file's images, properties,
embedded FITS keywords and metadata. Pixel data is surfaced as fully decoded (decompressed and
un-shuffled) opaque bytes plus typed geometry and format metadata — interpretation of the samples
is left to the consumer.
SwiftXISF is currently read-only: it parses existing monolithic XISF files into their header/data structure. Write and serialization (XISF authoring) support is not implemented and is not currently planned.
- Monolithic files: reads and validates the 16-byte binary preamble (
XISF0100signature, little-endian header length, reserved field) and the UTF-8 XML header. - Images: multiple images per file, each exposing typed
geometry,sampleFormat,colorSpace,pixelStorage,byteOrderandbounds, plus its fully decoded pixel bytes. - Properties & FITS keywords: typed scalar, complex, time-point and string properties, plus
vector/matrix/
ByteArrayvalues backed by data blocks, and embedded FITS keywords. - Data blocks:
inline(base64 / hex),embedded(<Data>child), andattachment(in-file) locations, plus opt-in external/distributedurl(...)/path(...)locations and the.xisbdistributed block index. - Compression:
zlib,lz4andlz4hcvia Apple's Compression framework, andzstdvia the upstream Zstandard library, all with optional byte-shuffling (+sh) and split sub-blocks. - Checksums: opt-in verification of
sha-1,sha-256andsha-512(andsha3-256/sha3-512where the platform provides them) data-block digests. - Color & ancillary metadata: unit-level
Metadata, per-image ICC profiles, RGB working space, display function, color filter array, resolution and thumbnails. - Strict vs. lenient:
XISFParsingOptionstoggles spec-faithful validation against real-world tolerance, and gates checksum verification and external-location resolution.
SwiftXISF targets the base XISF 1.0 specification. The following properties are intentional, not latent surprises:
- Read-only: there is no XISF authoring or serialization API.
- Opaque pixel data: samples are exposed as the fully decoded raw bytes plus typed metadata;
the library does not decode them into typed Swift sample arrays. The consumer interprets the
bytes using
sampleFormat,byteOrder,geometryandpixelStorage. - External/distributed data blocks are opt-in:
url(...)/path(...)locations are resolved only whenXISFParsingOptions.allowExternalLocationsis set (off in both.strictand.lenient), because resolving them reads files outside the parsed document. Resolution is lazy: a unit referencing external blocks still opens, and only accessing such a block requires the option. Only localfile://URLs and bothpath(...)forms are supported — remote (network) URLs are not fetched. - SHA-3 checksums require a recent OS:
sha3-256/sha3-512verification is available only where the system CryptoKit provides SHA-3 (macOS 26+); below that, requesting it yields a clean "unsupported" error rather than silently passing.sha-1/sha-256/sha-512are always available. Reference/uidassociation is not implemented: ancillary elements (ICC profile, display function, etc.) are parsed only as direct children of their<Image>(andMetadataas a direct child of the root). Root-level elements shared across images via<Reference>are not resolved.Metadatais treated as optional: the specification makes the unit<Metadata>element mandatory, but SwiftXISF exposes it as an optional (nilwhen absent) rather than rejecting files that omit it.- Tables are out of scope:
Structure/Tableelements are not parsed. - Strict vs. lenient:
.strictverifies data-block checksums and rejects input the spec forbids (a non-zero reserved field, an out-of-range value, a missingversion="1.0", a float image withoutbounds, an invalid identifier, and so on), while.lenienttolerates common real-world deviations (a non-zero reserved field, a missing/mismatched version, unknown enumerated values falling back to their defaults, and a declared-size mismatch) and does not force checksum verification. - Not thread-safe:
XISFFile,XISFImage,XISFDataBlock,XISFICCProfileandXISFThumbnaildecode and cache their bytes lazily on read, so they are notSendableand must not be shared across threads without external synchronization.
SwiftXISF is written in Swift and depends on:
- Foundation — for
Data,XMLParser, URL handling and the Compression framework (zlib/lz4/lz4hcdecoding). - CryptoKit — for data-block checksum verification. Its use is guarded by availability, so the library still builds where CryptoKit is unavailable (checksum verification then reports "unsupported").
- Zstandard (
libzstd) — forzstddecompression, the one XISF codec Apple's Compression framework does not provide. This is fetched automatically as a Swift package dependency; unlike SwiftFITS, SwiftXISF is therefore not dependency-free.
The library is developed, built and tested on macOS (deployment target macOS 15.0; see the CI badge
above). Portability to other Swift platforms depends on the availability of Foundation's Compression
framework, CryptoKit and libzstd, and has not been verified.
SwiftXISF ships a Package.swift and can be consumed as a Swift package. Add it to your
dependencies:
.package( url: "https://github.com/macmade/SwiftXISF.git", branch: "main" )The libzstd dependency is resolved transitively, so no additional setup is required. The Xcode
project (SwiftXISF.xcodeproj) is also provided for development.
This project uses submodules.
To clone it, use the following command:
git clone --recursive https://github.com/macmade/SwiftXISF.gitimport Foundation
import SwiftXISF
do
{
let file = try XISFFile( url: URL( fileURLWithPath: "/path/to/file.xisf" ), options: .lenient )
for image in file.images
{
print( "Image \( image.id ?? "<unnamed>" ): \( image.geometry ), \( image.sampleFormat ), \( image.colorSpace )" )
// Fully decoded (decompressed and un-shuffled) opaque pixel bytes.
let pixels = try image.data
print( "\( pixels.count ) bytes of pixel data" )
}
// Unit-level properties and embedded FITS keywords.
print( file.properties )
print( file.keywords )
}
catch // SwiftXISF.XISFError
{
print( error )
}Project is released under the terms of the MIT License.
Owner: Jean-David Gadina - XS-Labs
Web: www.xs-labs.com
Blog: www.noxeos.com
Twitter: @macmade
GitHub: github.com/macmade
LinkedIn: ch.linkedin.com/in/macmade/
StackOverflow: stackoverflow.com/users/182676/macmade