// The chunks a segmentation model adds to a capture (no new file version: chunks came in version 3), // each keyed by the model's name: // // "segs", in front: what is in the image, as text in the style of the Ex4 text formats // // @version 1 // engine: "onnxruntime 1.30.0, CUDA" // date: 2026-10-12T09:30:00Z // image: rendered 4032 3024 // classes: 5c1e9a0d77b2f413 // segment: 1 0.981 0.2140 1210 380 900 2210 "person" // // image: which image was read (rendered or original) and its size, which the boxes are in. classes: // a hash of the model's class list, so segments from another list can be told apart. segment: its // id in the mask, its score (0 to 1), its area (a fraction of the image), its box (x y width // height), and its class, quoted with "" for a quote; largest first. A line that cannot be read is // skipped, as are unknown keys. // // "mask", after the images: the segment id of every pixel, run-length encoded: // // u8 format 1 // u16 width the map's: the image's shape, its longest side at most 1024 (or so the model says) // u16 height // u8 id bits 8 // then runs, row by row, wrapping from one row to the next: a u8 id (0: no segment) and a length, // LEB128 (7 bits a byte, low first, the top bit set on all but the last). The runs cover every // pixel exactly. MCAP_SEGMENTS_TAG :: "segs"; MCAP_MASK_TAG :: "mask"; MCAP_SEGMENTS_TEXT_VERSION :: 1; MCAP_MASK_RLE :: 1; Mcap_Segment :: struct { id: u8; // its pixels' id in the mask score: float; // the model's confidence in its class, 0 to 1 area: float; // a fraction of the image x, y, width, height: s32; // its box, in the image's pixels class: string; // as people see and search it: "person", "wall" } Mcap_Segments :: struct { engine: string; // what ran it, such as "onnxruntime 1.30.0, CUDA" date: string; // when, UTC: 2026-10-12T09:30:00Z image: string; // which image was read: "rendered" or "original" image_width, image_height: s32; classes: string; // the class list's hash segments: [..] Mcap_Segment; // largest first } Mcap_Mask :: struct { width, height: s32; map: [] u8; // a segment id per pixel, row by row; 0: none } // A segs chunk's text. Temp. mcap_segments_text :: (s: Mcap_Segments) -> string { builder: String_Builder; builder.allocator = temp; print_to_builder(*builder, "@version %\n", MCAP_SEGMENTS_TEXT_VERSION); print_to_builder(*builder, "engine: %\n", mcap_quote(s.engine)); print_to_builder(*builder, "date: %\n", s.date); print_to_builder(*builder, "image: % % %\n", s.image, s.image_width, s.image_height); print_to_builder(*builder, "classes: %\n", s.classes); for s.segments { print_to_builder(*builder, "segment: % % % % % % % %\n", it.id, formatFloat(it.score, trailing_width = 3, zero_removal = .NO), formatFloat(it.area, trailing_width = 4, zero_removal = .NO), it.x, it.y, it.width, it.height, mcap_quote(it.class)); } return builder_to_string(*builder,, temp); } // A segs chunk's segments; strings and arrays from the context allocator. mcap_segments_parse :: (text: string) -> Mcap_Segments, ok: bool, error: string { result: Mcap_Segments; version_seen := false; for raw: split(text, "\n",, temp) { line := trim(raw); if !line.count || line[0] == #char "#" continue; if begins_with(line, "@version") { rest := trim(advance(line, 8)); version, ok := string_to_int(rest); if !ok || version < 1 || version > MCAP_SEGMENTS_TEXT_VERSION return result, false, tprint("its segments are version %, but this build reads up to %", rest, MCAP_SEGMENTS_TEXT_VERSION); version_seen = true; continue; } if !version_seen return result, false, "its segments do not start with @version"; colon := find_index_from_left(line, #char ":"); if colon < 0 continue; key := trim(slice(line, 0, colon)); value := trim(advance(line, colon + 1)); if key == { case "engine"; quoted, _, ok := mcap_read_quoted(value); if ok result.engine = copy_string(quoted); case "date"; result.date = copy_string(value); case "classes"; result.classes = copy_string(value); case "image"; parts := split(value, " ",, temp); if parts.count == 3 { w, w_ok := string_to_int(parts[1], T = s32); h, h_ok := string_to_int(parts[2], T = s32); if w_ok && h_ok { result.image = copy_string(parts[0]); result.image_width, result.image_height = w, h; } } case "segment"; // Seven numbers, then the quoted class. quote := find_index_from_left(value, #char "\""); if quote < 0 continue; numbers := split(trim(slice(value, 0, quote)), " ",, temp); if numbers.count != 7 continue; id, id_ok := string_to_int(numbers[0]); score, score_ok := string_to_float(numbers[1]); area, area_ok := string_to_float(numbers[2]); box: [4] s32; box_ok := true; for 0..3 { n, ok := string_to_int(numbers[3 + it], T = s32); box[it] = n; box_ok &&= ok; } class, after, class_ok := mcap_read_quoted(advance(value, quote)); if !id_ok || id < 1 || id > 255 || !score_ok || !area_ok || !box_ok || !class_ok || trim(after).count continue; array_add(*result.segments, .{cast(u8) id, score, area, box[0], box[1], box[2], box[3], copy_string(class)}); } } return result, true, ""; } // A mask chunk's data for a map of width x height segment ids. Temp. mcap_mask_bytes :: (width: s32, height: s32, map: [] u8) -> [] u8 { assert(map.count == cast(s64) width * height && width > 0 && height > 0 && width <= 0xFFFF && height <= 0xFFFF); out: [..] u8; out.allocator = temp; array_reserve(*out, 64 + map.count / 16); array_add(*out, MCAP_MASK_RLE); array_add(*out, cast(u8) (width & 0xFF), cast(u8) (width >> 8), cast(u8) (height & 0xFF), cast(u8) (height >> 8)); array_add(*out, 8); at := 0; while at < map.count { id := map[at]; run := 1; while at + run < map.count && map[at + run] == id run += 1; array_add(*out, id); length := cast(u64) run; while true { // LEB128 byte := cast(u8) (length & 0x7F); length >>= 7; if length { array_add(*out, byte | 0x80); } else { array_add(*out, byte); break; } } at += run; } return out; } // A mask chunk's map; the map from the context allocator. mcap_mask_parse :: (data: [] u8) -> Mcap_Mask, ok: bool, error: string { mask: Mcap_Mask; if data.count < 6 return mask, false, "its mask is cut short"; if data[0] != MCAP_MASK_RLE return mask, false, tprint("its mask is in format %, which this build does not read", data[0]); mask.width = (cast(s32) data[1]) | ((cast(s32) data[2]) << 8); mask.height = (cast(s32) data[3]) | ((cast(s32) data[4]) << 8); if data[5] != 8 return mask, false, tprint("its mask has %-bit ids, which this build does not read", data[5]); if !mask.width || !mask.height return mask, false, "its mask has no size"; total := cast(s64) mask.width * mask.height; mask.map = NewArray(total, u8, initialized = false); filled := 0; at := 6; while at < data.count { id := data[at]; at += 1; length: u64; shift: u32; while true { if at >= data.count || shift > 35 { array_free(mask.map); mask.map = .[]; return mask, false, "its mask's runs are cut short"; } byte := data[at]; at += 1; length |= (cast(u64) (byte & 0x7F)) << shift; shift += 7; if !(byte & 0x80) break; } if !length || cast(s64) length > total - filled { array_free(mask.map); mask.map = .[]; return mask, false, "its mask's runs do not fit its size"; } memset(mask.map.data + filled, id, cast(s64) length); filled += cast(s64) length; } if filled != total { array_free(mask.map); mask.map = .[]; return mask, false, "its mask's runs do not cover it"; } return mask, true, ""; } // The chunks for segments by model, ready to store together with mcap_store (segs in front, mask in // back). Their data is temp. mcap_segments_chunk :: (model: string, segments: Mcap_Segments) -> Mcap_Chunk { return .{tag = mcap_tag(MCAP_SEGMENTS_TAG), key = model, data = cast([] u8) mcap_segments_text(segments)}; } mcap_mask_chunk :: (model: string, width: s32, height: s32, map: [] u8) -> Mcap_Chunk { return .{tag = mcap_tag(MCAP_MASK_TAG), key = model, data = mcap_mask_bytes(width, height, map)}; }