mcap/modules/Capture_File
2026-10-07 21:51:18 +01:00
..
module.jai [0.0.0] .mcap version 2: OCR stored in each capture, search, a library scan, sorting by date; turned text 2026-10-07 21:51:18 +01:00
ocr_text.jai [0.0.0] .mcap version 2: OCR stored in each capture, search, a library scan, sorting by date; turned text 2026-10-07 21:51:18 +01:00
README.md [0.0.0] .mcap version 2: OCR stored in each capture, search, a library scan, sorting by date; turned text 2026-10-07 21:51:18 +01:00

The .mcap file

One capture in one file: a fixed magic, a file version stamp, the capture's data as Capture Text, what OCR read in it, a small preview, then the images. There is no ZIP and no compression around it; the images keep their own PNG compression.

The parts a library browser needs (header, text, OCR and preview) come first, so it reads the start of each file and never touches the images; a search, which needs no preview, reads less still.

Layout, version 2

All integers are little-endian. Sizes count bytes.

Field Type
magic 8 bytes 89 4D 43 41 50 0D 0A 1A, which is \x89MCAP\r\n\x1A. Says this is an .mcap, in every version.
file version u32 2. Version 1 files are still read; see below.
text size, text u32, bytes Capture Text, UTF-8: every JSON file of the capture, as [[file]] sections.
OCR size, OCR u32, bytes OCR text, UTF-8 (below): what each OCR model read. Size 0 when none has.
preview width, height u16, u16 In pixels.
preview size, preview u32, bytes PNG. Size 0 when there is none.
original name size, name u16, bytes The original image's name in the .snagx, such as {GUID}.png; the page's CaptureBackgroundImage names it too.
original size, original u32, bytes The capture as taken: PNG, exactly as it was in the .snagx.
rendered kind u8 0: none. 1: the same as the original (stored once). 2: its own, below.
rendered size, rendered u32, bytes Only for kind 2. The capture with its annotations drawn in (Snagit's thumbnail.png): PNG, exactly as it was.

The file ends there: anything after the last part is a mistake.

The magic borrows PNG's: the first byte has its high bit set, so a channel that strips it shows; \r\n shows line endings being converted; and \x1A stops type on Windows.

Version 1 is the same without the OCR size and OCR. A reader takes both; anything written is version 2, so a version 1 file becomes version 2 the first time OCR is stored in it.

The parts

  • Text. Everything the capture's JSON held: index.json, metadata.json, the page's {GUID}.json, and {GUID}.backup.json when there is one.
  • OCR. One section per OCR model, so a capture read by several models keeps every reading; reading it again with a model replaces only that model's section. See OCR text below.
  • Preview. The rendered image (or the original, when there is no rendered one) scaled so its longest side is at most 320 pixels, as a PNG. An image already that small is used as it is, never scaled up.
  • Original and rendered. A capture with no annotations has a rendered image identical to the original, byte for byte; it is then stored once, as kind 1.
  • One page. An .mcap holds one page, as every capture so far does; a .snagx with more is not converted.
  • Left out: {GUID}.backup.png, Snagit's image from before an edit. Its {GUID}.backup.json is kept, as plenty of captures have one without the image.

Versions

A reader checks the magic, then the file version. It refuses a version above its own, never writing over a file from a later version, and reads every version up to its own. Version 0 does not exist.

Converting

snagit-converter mcap converts .snagx files (or extracted captures) to .mcap, and snagit-converter snagx converts .mcap files back to a .snagx Snagit can open. See the README for what each checks.

Back in a .snagx, the JSON is laid out as Snagit writes it, the images are the same bytes, and only the backup image is missing. JSON numbers come back as values: 3.0 is written 3.

OCR text

In the style of the Ex4 text formats:

@version 2

[ocr ppocr-v5-mobile]
engine: "onnxruntime 1.30.0, CUDA"
image:  rendered 1920 1080
date:   2026-10-08T21:04:11Z
line: 412 96 640 18 412 96 1052 96 1052 114 412 114 0.993 "Assign Footprints - KiCad"
line: 20 140 220 14 20 140 240 140 240 154 20 154 0.981 "Symbol : Footprint Assignments"
line: 1700 300 20 160 1720 300 1720 460 1700 460 1700 300 0.952 "Read downwards"
Key Value
[ocr NAME] A section: the model's name, as in its models.config.
engine What ran it, quoted.
image Which image was read (rendered or original) and its width and height; the lines' boxes are in its pixels.
date When it was read, UTC.
line A text line: x, y, width and height, then its four corners as x y pairs, its confidence (0 to 1), and its text, quoted with "" for a quote. A control character in the text is written as a space.

The corners go clockwise from the text's top left: top left, top right, bottom right, bottom left, as the text reads. Level text has the box's corners; a turned line's say which way it reads (the third line above reads downwards, so its top left is the box's top right). x, y, width and height bound them.

A line that cannot be read is skipped, as are keys this version does not know. Version 1 OCR text had no corners (line: x y width height confidence "text"); it is still read, with the box's corners. The OCR text carries its own version, so this did not change the .mcap file version. mcap_store_ocr (modules/Capture_File/ocr_text.jai) stores a section in a file.