Zeiss CZI
ZEISS ZEN writes .czi files for widefield, confocal, light-sheet and slide-scanner images. OpenReadout returns one image per scene with its channels, Z planes, time points and tiles, the pyramid levels of slide scans, the metadata, and the attachments.
Derived from corpus files by hex dump and a Python segment walker, cross-checked against the public documentation and source of czifile (BSD-3-Clause) and the ZEISS libCZI documentation pages (concepts only: resolution protocol, valid-pixel mask). See docs/provenance/czi.md.
CZI (“Carl Zeiss Image”) is a segmented container. Every segment starts with a 32-byte header; the file header points at the subblock directory, the XML metadata, and the attachment directory. Pixel data lives in subblocks, each a rectangular tile of one plane at one set of dimension coordinates, optionally compressed.
Byte layout (all integers little-endian)
Segment header (every segment, 32 bytes)
| offset | size | field | meaning |
|---|---|---|---|
| 0 | 16 | segment_id |
ASCII, zero-padded: ZISRAWFILE, ZISRAWDIRECTORY, ZISRAWSUBBLOCK, ZISRAWMETADATA, ZISRAWATTACH, ZISRAWATTDIR, DELETED |
| 16 | u64 | allocated_size |
bytes reserved for the payload; next segment starts at offset + 32 + allocated_size |
| 24 | u64 | used_size |
bytes actually used (≤ allocated) |
DELETED segments are tombstones and are skipped. The file starts with a ZISRAWFILE segment whose allocated size is 512.
File header payload (ZISRAWFILE)
| offset | size | field | observed |
|---|---|---|---|
| 0 | u32 | version_major |
1 |
| 4 | u32 | version_minor |
0 |
| 8 | 8 | reserved | |
| 16 | 16 | primary_file_guid |
equal to file_guid in single-file documents |
| 32 | 16 | file_guid |
|
| 48 | u32 | file_part |
0 for single-file documents and for the master of a multi-file document; k for its following part k (see Multi-file documents) |
| 52 | u64 | directory_position |
byte offset of the ZISRAWDIRECTORY segment (0 if absent) |
| 60 | u64 | metadata_position |
byte offset of the ZISRAWMETADATA segment |
| 68 | u32 | update_pending |
non-zero means the writer did not finish |
| 72 | u64 | attachment_directory_position |
byte offset of ZISRAWATTDIR (0 if none) |
Metadata payload (ZISRAWMETADATA)
| offset | size | field |
|---|---|---|
| 0 | u32 | xml_size |
| 4 | u32 | attachment_size (always 0 in the corpus) |
| 8 | 248 | reserved |
| 256 | xml_size |
UTF-8 XML, root ImageDocument |
Subblock directory payload (ZISRAWDIRECTORY)
| offset | size | field |
|---|---|---|
| 0 | u32 | entry_count |
| 4 | 124 | reserved |
| 128 | var | entry_count × directory entry (below) |
Directory entry (schema DV; also the first thing in a subblock header)
| offset | size | field | meaning |
|---|---|---|---|
| 0 | 2 | schema |
ASCII DV |
| 2 | u32 | pixel_type |
see table |
| 6 | u64 | file_position |
byte offset of the ZISRAWSUBBLOCK segment |
| 14 | u32 | file_part |
|
| 18 | u32 | compression |
see table |
| 22 | u8 | pyramid_type |
0 none, 1 single, 2 multi (subblock belongs to a downsampled level) |
| 23 | 5 | reserved | |
| 28 | u32 | dimension_count |
|
| 32 | 20 × n | dimension_entry |
one per dimension |
Entry length = 32 + 20 * dimension_count.
Dimension entry (20 bytes)
| offset | size | field | meaning |
|---|---|---|---|
| 0 | 4 | dimension |
ASCII, zero-padded: X, Y, Z, C, T, R, S, I, H, V, B, M |
| 4 | i32 | start |
coordinate of the first element (pixels for X/Y; index otherwise) |
| 8 | u32 | size |
extent in the full-resolution coordinate system |
| 12 | f32 | start_coordinate |
physical start (unused by us) |
| 16 | u32 | stored_size |
extent actually stored; stored_size < size means a pyramid level |
Level-0 (full resolution) subblocks have stored_size == size for X and Y and pyramid_type == 0.
Subblock payload (ZISRAWSUBBLOCK)
| offset | size | field |
|---|---|---|
| 0 | u32 | metadata_size |
| 4 | u32 | attachment_size |
| 8 | u64 | data_size |
| 16 | var | directory entry (as above) |
max(256, 16 + entry_len) |
metadata_size |
UTF-8 XML <METADATA> (per-subblock tags such as AcquisitionTime, stage position) |
| + | data_size |
pixel data, compressed per compression |
| + | attachment_size |
optional attachment; may carry a valid-pixel mask (below) |
Invariant checked by check: used_size == header_len + metadata_size + data_size + attachment_size.
Attachment directory (ZISRAWATTDIR) and attachments (ZISRAWATTACH)
ZISRAWATTDIR: u32 entry_count, reserved to 256, then 128-byte entries. ZISRAWATTACH: u32 data_size, 12 reserved, one 128-byte entry, padding to 256, then data.
Attachment entry (128 bytes): schema A1 (2), reserved (10), u64 file_position, u32 file_part, 16-byte content_guid, 8-byte ASCII content_file_type (JPG, CZTIMS, CZEVL, CZI, Zip-Comp, …), 80-byte name (Thumbnail, TimeStamps, EventList, Label, SlidePreview, Profile, InteractiveMeasurement, …). The payload of an attachment starts ATTACHMENT_DATA_OFFSET = 32 + 256 bytes after its segment start; its length is the ZISRAWATTACH data_size (read at open, one small read per attachment, so info --view structure can show sizes).
Payloads we interpret or expose (corpus evidence in docs/provenance/czi.md):
content_file_type |
typical name |
payload | what we do |
|---|---|---|---|
CZTIMS |
TimeStamps |
u32 size (unreliable across writers), u32 count, count × f64 seconds |
parse_time_stamps → images[].extra.time_stamps_s (per T, relative clock) and planes[].extra.time_stamp_s |
CZEVL |
EventList |
u32 size, u32 count, then records: i32 entry_size, f64 time_s, i32 event_code, i32 text size, text (NUL-terminated) |
parse_event_list → images[].extra.events (kind: marker, interval_change, bleach_start, bleach_stop, trigger) |
JPG |
Thumbnail |
a JPEG file | listed; export --attachment writes it (.jpg) |
CZI |
Label, SlidePreview |
a complete embedded CZI file | listed; export --attachment writes it (.czi), which every command then reads |
Zip-Comp |
Profile |
gzip-compressed XML | listed; export --attachment writes it (.gz) |
| anything else | opaque | listed; export --attachment writes it (.bin, .xml for CZEXP/CZHWS) |
extension_for maps content types to file extensions. Payloads larger than MAX_INTERPRETED_ATTACHMENT (64 MiB) are never interpreted, only extracted.
Valid-pixel mask (subblock attachment)
From the libCZI documentation page valid-pixel mask (concept page, not source) and czifile’s mask() (BSD-3): a subblock’s attachment may be a chunk container, a sequence of (16-byte GUID, i32 size, payload). The chunk whose GUID is MASK_CHUNK_GUID ({CBE3EA67-5BFC-492B-A16A-ECE378031448}, stored 67 EA E3 CB FC 5B 2B 49 A1 6A EC E3 78 03 14 48) holds:
| offset | size | field |
|---|---|---|
| 0 | u32 | mask_width |
| 4 | u32 | mask_height |
| 8 | u32 | representation (must be 0) |
| 12 | u32 | stride (bytes per row) |
| 16 | stride × mask_height |
bits, most significant bit = leftmost pixel; 1 = valid |
parse_valid_mask also accepts the variant czifile handles, where the GUID follows 16 leading bytes. When compositing a plane, only valid pixels of a masked subblock are pasted (ValidMask::is_valid); a mask that is all valid (all_valid) or malformed is ignored. In the corpus, masks occur on pyramid-level subblocks of tiled scans (aics-*, openslide-zeiss-5-*, zenodo7015307-* mosaics), where they stop a tile’s padding from covering its neighbour.
Pixel types (pixel_type)
| id | our name | samples | sample type | notes |
|---|---|---|---|---|
| 0 | gray8 |
1 | uint8 | |
| 1 | gray16 |
1 | uint16 | ComponentBitCount in XML may say 12 or 14 |
| 2 | gray32_float |
1 | float | |
| 3 | bgr24 |
3 | uint8 | stored B,G,R; we return R,G,B |
| 4 | bgr48 |
3 | uint16 | stored B,G,R |
| 8 | bgr96_float |
3 | float | |
| 9 | bgra32 |
4 | uint8 | alpha dropped on read |
| 10 | gray64_complex_float |
2 | float | unsupported |
| 11 | bgr192_complex_float |
6 | float | unsupported |
| 12 | gray32 |
1 | int32 | signed (czifile maps it to <i4); no corpus sample |
| 13 | gray64 |
1 | double |
The directory entry’s pixel_type is authoritative for the subblock; the XML PixelType can disagree (the OpenSlide previews say Bgr24 in XML but store Bgr48).
Compression (compression)
| id | our name | payload | status |
|---|---|---|---|
| 0 | uncompressed |
raw samples, row-major, no padding | supported |
| 1 | jpeg |
a complete JPEG stream (SOI … EOI); 3-sample streams decode to R,G,B (no B/R swap, as czifile) | supported via jpeg-decoder: 8-bit baseline/progressive gray and YCbCr, lossless (SOF3) up to 16 bit; 12-bit DCT is exit 6 |
| 2 | lzw |
LZW (TIFF flavour) | planned |
| 3 | jpeg_lossless |
undocumented; no public sample | not supported (exit 6) |
| 4 | jpeg_xr |
JPEG XR codestream, starts 49 49 BC 01 |
supported via openreadout-jpegxr (our safe port of jxrlib’s decoder; bit-exact with jxrlib/imagecodecs on every corpus subblock); alpha planes, CMYK and packed pixel formats are exit 6 |
| 5 | zstd0 |
plain zstd frame, starts 28 B5 2F FD |
supported |
| 6 | zstd1 |
small header then a zstd frame | supported |
| 7, ≥ 1000 | chunked / system raw |
experimental chunked container; camera/system raw | not supported (exit 6) |
JPEG decoding differs from libjpeg-turbo (czifile’s decoder) by rounding in the inverse DCT and chroma upsampling: on the synthetic fixtures the largest per-sample difference is 1 grey level for 8-bit gray and 3 for 4:2:0 colour. Lossless JPEG is bit-exact. The corpus harness therefore compares lossy JPEG fixtures against czifile’s decoded planes with a tolerance (pixel_tolerance in corpus/manifest.toml).
Resolution protocol (decoded bitmap vs directory entry)
After decoding a JPEG or JPEG XR subblock, conform brings the bitmap to what the directory entry declares (libCZI documentation page resolution protocol: the directory entry is authoritative):
- size: crop or zero-pad at the top-left origin to
stored_sizeX × Y; - pixel type: convert samples to the declared type. 16 → 8 bit keeps the high byte (
>> 8); 8 → 16 bit zero-extends; gray → RGB replicates; RGB → gray is(R + G + B + 1) / 3(integers) or the mean (floats); RGBA → RGB drops alpha; floats clip to the integer range. These are czifile’s pixel-type conversions; pylibCZIrw (run as an oracle) agrees on 48 → 24 bit (>> 8) and 8 → 16 bit (zero-extend), and czifile itself, which casts instead of converting, returns the low byte for 48 → 24 bit; - the result is a
Conformedbitmap plus the list ofadjustmentsmade.checkdecodes one JPEG/JPEG XR subblock per (compression, pixel type) and reports a non-empty list as aresolution_protocolwarning.
The OpenSlide Zeiss-5-* slide previews are the corpus case of XML/directory disagreement: the XML says Bgr24, the directory says Bgr48 and the JPEG XR stream is 48-bit, so we return uint16 RGB, as czifile does; images[].extra.xml_pixel_type records the XML’s claim when it differs.
zstd1 header (derived from openslide-zeiss-5-slidepreview-zstd1-hilo): byte 0 = header_size (observed 3), byte 1 = chunk_kind (observed 1), byte 2 = flags where bit 0 = hilo byte shuffle. After decompression with hilo set, the buffer holds all low bytes of the 16-bit samples first, then all high bytes; unshuffle_hilo re-interleaves them.
XML model (ImageDocument/Metadata, the subset we normalize)
Information/Image/{SizeX,SizeY,SizeZ,SizeC,SizeT,SizeS,SizeM,SizeH,SizeB,PixelType,ComponentBitCount,AcquisitionDateAndTime}Information/Image/Dimensions/Channels/Channel[@Id,@Name]/{ExcitationWavelength,EmissionWavelength,Color,Fluor,ExposureTime,AcquisitionMode,IlluminationType,ContrastMethod}Information/Image/Dimensions/Channels/Channel/DetectionWavelength/Ranges ("415-735" → emission_range_nm) (AcquisitionMode + ContrastMethod, OME enumeration tokens → one acquisition_mode label: WideField + Fluorescence → "Widefield Fluorescence")Information/Image/Dimensions/S/Scenes/Scene[@Index,@Name]/{CenterPosition,ContourSize,Shape[@Name,@Id]/{RowIndex,ColumnIndex}}Information/Image/Dimensions/T/StartTime ; Z/StartPositionInformation/Instrument/Objectives/Objective[@Name]/{LensNA,NominalMagnification,Immersion,WorkingDistance}Information/Instrument/Microscopes/Microscope[@Name]/{Type,System} (System = the model when @Name is absent: LSM files)Information/Document/UserName ; Information/User/DisplayName (the user account → extra.experimenter.user_name)Information/Application/{Name,Version}Scaling/Items/Distance[@Id=X|Y|Z]/Value (metres per pixel)DisplaySetting/Channels/Channel[@Id,@Name]/{Color,DyeName,DyeMaxEmission,DyeMaxExcitation,IlluminationType} (matched to image channels by Id)Experiment[@Version]/ExperimentBlocks/AcquisitionBlock/SubDimensionSetups/*Setup[@IsActivated] (nested; TimeSeriesSetup/{Duration/Cycles,Interval/TimeSpan/{Value,DefaultUnitFormat}})Per-subblock <METADATA> (read only by info --view full, one small read per plane):
METADATA/Tags/{AcquisitionTime, StageXPosition, StageYPosition, FocusPosition, DetectorState (escaped XML with ExposureTime ns)}Colours are #AARRGGBB; we drop the alpha byte. Where the image channel lacks a colour, name, dye or wavelength, the DisplaySetting channel with the same Id fills it (by position when no ids match).
Normalized extras per image (images[].extra): experimenter ({user_name}: Document/UserName, else User/DisplayName), scene (index, center_position_um, contour_size_um, well {name, id, row_index, column_index}), experiment (version, acquisition_blocks, active_setups, time_series_cycles, time_series_interval_s), time_stamps_s, events, pyramid. Per-frame records in info --view full (images[].extra.frames, the core’s Dataset::frames; one record per plane, ordered t, then z, then c; first 100 per image unless --all-frames): frame (running index), c, z, t, acquired_at (subblock AcquisitionTime), time_ms (milliseconds since the image’s earliest record, from those times when every record has one, else from the time stamps), stage_x_um/stage_y_um/stage_z_um (subblock StageXPosition/StageYPosition/FocusPosition), exposure_ms (subblock DetectorState, else the channel’s ExposureTime), time_stamp_s (the TimeStamps value for that T). Field names follow the ND2 frame records.
Image geometry
- One exposed image per scene (
Sindex); files withoutShave one image. - Full-resolution planes are the union of level-0 subblocks of that scene. The image’s X/Y size is the bounding box of those subblocks (
max(start + size) - min(start)); mosaics (M) are stitched by placing each tile atstart - min_start. size_z/c/t=max(start) + 1over level-0 subblocks of the scene (indices start at 0 per scene in the corpus; when a scene’s minimum start is non-zero we subtract it).- Pyramid levels (inferred from the corpus; geometry checked against pylibCZIrw run as a black box; see
docs/provenance/czi.md): a level is one downsampling factor per axis for a whole scene. Subblocks withpyramid_type != 0belong to a level; ZEN builds each level from the one below, so a subblock’s own ratiosize / stored_sizeis the level’s factor distorted by the rounding of its stored size (128.158for a 1/128 tile ofzenodo10577621-Young-mouse). A subblock is consistent with every factor in[size / (stored + 2), size / (stored - 2)]per axis (level_scale_range,STORED_SIZE_SLACK). Levels are formed from the largest subblocks first: a subblock joins the level whose factors lie inside its interval (the nearest, when several do) or starts one whose factor is the power of two inside the interval, else the nearest integer, else the ratio (snap_factor). Levels are ordered finest first: level 0 is full resolution. Level k of a scene whose level-0 rectangle isx0, y0, w, hisfloor(w / f) × floor(h / f)pixels, and a subblock starting at level-0startis placed atfloor((start - x0) / f)(level_place), stored pixels unscaled, clipped to the level. That is the grid pylibCZIrw returns atzoom = 1/fover the scene rectangle, solevel pixel × f + originis a level-0 coordinate; czifile instead sizes a level as the bounding box of its subblocks and keys levels by exact ratios.pyramid_levels= 1 + number of levels;extra.pyramidlists each level’s size and factors.read_plane_levelcomposites a level exactly like level 0 (tile order by M index, valid-pixel masks honoured). Where pylibCZIrw differs: it resamples a subblock whose ratio is not exactly f to its logical footprint, and where a subblock’s grid position is fractional it leaves the subblock’s first row or column to its neighbour or the background (one pixel along tile seams). - Canvas no subblock covers (the gaps of a mosaic inside its bounding box, at level 0 and at every pyramid level) is 0 in every sample, as in czifile and pylibCZIrw (default background). Pyramid subblocks are returned as stored: in the Axioscan RAC scans (
zenodo10577621-Intestine-3color-RAC,-Kidney-RAC-3color, 12-bit data in uint16) ZEN’s pyramid tiles extend past the acquired tiles and hold 65535 there, and 65535 averaged with data along the scanned area’s edge (values from 4096 up), with no valid-pixel mask. A level therefore shows 65535 where level 0 shows 0; czifile and pylibCZIrw (read(zoom=1/f), black box) return the same values, so the reader does not rewrite them. Consumers that know the recorded depth (images[].extra.component_bit_count) can tell the fill from data:previewdraws samples above it as background when most of them are 65535 (seebook/src/reference/commands/index.md; checks indocs/provenance/czi.md). - Super-resolved renderings: full-resolution subblocks can store more pixels than their logical extent (an ELYRA PALM rendering: 1206 × 1206 stored for 512 × 512 logical; 2560 for 256). A scene’s full-resolution subblocks are grouped by their stored-to-logical ratio on X (
stored_ratio); a scene with several ratios becomes one image per ratio (its channels only; the rendering’s name gets(rendered at <ratio>x)), subblocks are placed atround(start × ratio)and the pixel size is the logical one divided by the ratio (images[].extra.rendering_scale). Nothing is resampled: the widefield channel keeps its 512 grid, the rendering its own. Validated against czifile’sasarray(storedsize=True, C=c)on the three PALM files of Zenodo 10577621. - Dimensions
H,I,R,V,B: a subblock’s coordinates on the dimensions other than X, Y, Z, C, T, S and M, sorted by letter, are itsextra_key. A scene’s full-resolution subblocks are grouped by that key (and by stored-to-logical ratio); when the coordinates vary within the scene (extra_varying), each combination is its own image, in key order (letters alphabetical, the last varying fastest), named<scene> <D>=<k>(Scene <s> <D>=<k>for an unnamed scene of a multi-scene file,<D>=<k>alone for a single unnamed scene), withimages[].extra.dimension_index({"H": 3}) and its pyramid subblocks those with the same coordinates. A plane reads only the subblocks at the image’s coordinates on every such dimension (extra_index; a dimension constant across the scene is matched at its constant value).extra.other_dimensionsstill lists each varying dimension’s extent across the scene. Validated on an ELYRA 7 SIM raw acquisition (H = 13 phases × C 3 × T 14,zenodo16419509-Rizzollo-Example1-SIM-raw) against czifile’sasxarrayindexed on H. No public file with I, R, V or B varying was found (light-sheet Z.1 and Lightsheet 7 files surveyed carry them at extent 1). - Pyramid factors other than 2: ZEN 3.7 slide scans can build pyramids by 3 (subblock ratios 3, 9, 27, 81;
zenodo12509122-PSR-LXR-KO-WT-1054).snap_factorpicks the integer inside each subblock’s interval, so levels are 1/3, 1/9, 1/27, 1/81 withfloor(w / f)sizes, equal to pylibCZIrw’sread(zoom=1/3^k)over the scene rectangle (black box).
Multi-file documents (inferred)
No public multi-file CZI exists in the corpus; this section is inferred from the header fields and tested only against synthetic fixtures (synthetic-multifile*, made by oracle/make_czi_fixtures.py). Confidence: inferred.
- The master (
file_part0) holds the XML, the subblock directory and the attachment directory. Directory and attachment entries whosefile_partis k > 0 point into following part k. - Part k is looked for next to the master as
<master stem> (k).<ext>(part_path; e.g.slide.czi→slide (1).czi), then as<master stem>(k).<ext>(the spelling ZEN gives separately saved Lightsheet tiles, e.g. Zenodo 19047136Image_1_…964(1).czi; those files are independent documents withfile_part0, so they never trigger part discovery). It must start with aZISRAWFILEsegment whosefile_partis k and whoseprimary_file_guidequals the master’sprimary_file_guid; otherwisecheckreportsbad_part. - Parts referenced by any entry are probed at open (
FilePart:path,present,file_len,part_problem);info --view structurelists them asfile-partrows,infoadds a note,checkreportsmissing_part(error, exit 4) for each absent one, and reading a plane stored in a missing part is anio“not found” error (exit 5) naming the expected part file, while the other planes stay readable. - Opening a following part directly is exit 6 with a hint naming the master (
master_path).
Vocabulary (every public identifier in openreadout-czi must appear here)
| identifier | meaning |
|---|---|
CziReader, CziFile, FORMAT_ID, FILE_MAGIC, SEGMENT_HEADER_LEN |
entry points and constants |
SegmentHeader, segment_id, allocated_size, used_size, SegmentId { File, Directory, SubBlock, Metadata, Attachment, AttachmentDirectory, Deleted, Unknown } |
segment chain |
FileHeader, version_major, version_minor, primary_file_guid, file_guid, file_part, directory_position, metadata_position, update_pending, attachment_directory_position |
file header |
DirectoryEntry, schema, pixel_type, file_position, compression, pyramid_type, dimension_count, dimensions |
subblock directory |
DimensionEntry, dimension, start, size, start_coordinate, stored_size |
per-dimension extent |
SubBlockHeader, metadata_size, attachment_size, data_size, header_len, entry |
subblock header |
AttachmentEntry, content_guid, content_file_type, name |
attachment directory |
PixelTypeId { Gray8, Gray16, Gray32Float, Bgr24, Bgr48, Bgr96Float, Bgra32, Gray64ComplexFloat, Bgr192ComplexFloat, Gray32, Gray64, Unknown }, sample_type, samples_per_pixel, bytes_per_pixel |
pixel types |
CompressionId { Uncompressed, Jpeg, Lzw, JpegLossless, JpegXr, Zstd0, Zstd1, Chunked, Unknown } |
compression ids |
detector_id, detectors |
DetectorSettings/Detector/@Id of a channel; Information/Instrument/Detectors id → label (Manufacturer/Model, else @Name, else Type), the image’s instrument.detector (distinct labels of its channels joined by +) |
Scene, scene_index, scene_name, level0, bounds, min_x, min_y, width, height, size_z, size_c, size_t, pyramid_levels, other_dims, extra_index, extra_varying, extra_key, ExtraKey, absent_channels |
per-scene geometry; absent_channels: channels with no subblock at the image’s H/I/R/V/B coordinates (read as 0); extra_index/extra_varying: the image’s H/I/R/V/B coordinates and which of them vary within the scene |
Bounds, ImageXml, ChannelXml, ObjectiveXml, ScalingXml, channel_name, excitation_nm, emission_nm, color_argb, fluor, exposure_ns, acquisition_mode, illumination_type, objective_name, lens_na, nominal_magnification, immersion, microscope_name, user_name, application_name, application_version, acquisition_time, distance_x, distance_y, distance_z |
normalized XML fields |
decode_subblock, unshuffle_hilo, zstd1_header, header_size, chunk_kind, hilo |
codec plumbing (in openreadout-codecs) |
paste_tile, bgr_to_rgb, drop_alpha |
plane assembly |
CziDataset, open, path, file_len, problems |
opened-file state and structural problems collected while walking |
parse, from_raw, encoded_len, is_level0, scale, covers, upsample_factor, stored_ratio, bytes_per_sample, pixel_scale |
directory-entry helpers: id parsing, level-0 test, downsampling factor, index coverage, stored/logical ratio |
parse_image_xml, argb_to_rgb, channels, scaling, scene_names, t_increment_s, component_bit_count, contrast_method |
XML normalization helpers and fields |
min_z, min_c, min_t, tile_count |
per-scene index origins and tile count |
Level, levels, scale_x, scale_y, level_scale_range, AxisScale, STORED_SIZE_SLACK, snap_factor, level_place |
pyramid levels: downsampling factors, grouping of subblocks and the level pixel grid |
FilePart, parts, present, part_problem, part_file, part_path, master_path |
multi-file documents: following parts and their discovery |
ATTACHMENT_DATA_OFFSET, MAX_INTERPRETED_ATTACHMENT, extension_for |
attachment payload offset, interpretation size cap, extension for export --attachment |
EventRecord, time_s, event_code, event_kind, description, parse_event_list, parse_time_stamps |
CZEVL and CZTIMS attachment payloads |
ValidMask, MASK_CHUNK_GUID, mask_width, mask_height, stride, bits, is_valid, all_valid, parse_valid_mask |
valid-pixel mask in a subblock attachment |
Conformed, conform, adjustments |
resolution protocol: a decoded bitmap brought to the declared size and pixel type |
SceneXml, scenes, center_x_um, center_y_um, contour_width_um, contour_height_um, well_name, well_id, row_index, column_index |
Scenes/Scene XML: stage centre, contour, well |
ExperimentXml, experiment, experiment_version, block_count, active_setups, time_series_cycles, time_series_interval_s |
Experiment XML summary |
detection_range_nm, dye_name |
channel detection band and display-setting dye |
SubBlockTags, parse_subblock_tags, stage_x_um, stage_y_um, focus_um |
per-subblock <METADATA><Tags> |
fuzz_directory_entries, fuzz_subblock_header, fuzz_attachment_entries, fuzz_metadata_xml |
byte-slice entry points for the cargo-fuzz targets (fuzzing feature only; not a stable API) |
Performance / robustness merge (2026-09-23)
Tile sizes are checked once before worker decoding using the common file-relative plane limit, capped at 4 GiB. Parallel tiles retain bounded JPEG decoding and checked stack offsets; decoded buffers remain in place for colour conversion.
How this reader was derived, file by file: provenance log.