Analyser/Docs
Documentation menu

Renderer catalog

A short reference to every module in web/assets/js/renderers/ - what file kind it owns, what it does, and any notable vendored/WASM dependency. Renderer kinds are wired into the ROUTES table in web/assets/js/core/app.js and lazy-loaded on first use (see architecture.md and pipeline.md). There are ~86 modules in renderers/ (a handful - compare.js, folder-archive-shared.js, sonify.js, media-reverse.js, proprietary-formats.js and similar - are shared helpers or data tables rather than top-level routed kinds). For full usage detail (buttons, controls, options), see the features/*.md docs; this is the module-level map.

On this page

Images#

ModuleHandlesNotes
photo.jsPhoto analysis entry pointFile preview, size/MIME/dimensions/aspect ratio, full EXIF/IPTC/XMP/ICC/GPS via exifr, derived optics (FoV/DoF/EV), RGB histogram, dominant colours, GPS map (lazy Leaflet+OSM), OCR (lazy Tesseract.js), multi-format barcode read (native BarcodeDetector + jsQR), reverse-image-search hand-off, SHA-256, and a collapsible Advanced card grouping the photo-forensics.js tools
photo-convert.jsHEIC/HEIF and camera-RAW conversion to JPEG before analysisheic2any for HEIC, embedded-JPEG scan for RAW, ImageMagick-WASM heavyweight fallback
photo-forensics.jsPixel/JPEG forensic + privacy helpers (UI-free)Error-level analysis (computeElaCanvas), JPEG quantization-table fingerprint + quality recovery (analyzeJpegQuantization), JPEG ghosts (computeJpegGhosts), chi-square LSB steganalysis (lsbChiSquare), lossless metadata strip (stripImageMetadata), XMP edit-history parse (parseXmpHistory), Photoshop IPTC-digest check (checkIptcDigest, MD5 via core/util.js). Pure canvas/typed-array maths, no WASM; photo.js builds the card chrome
photo-recover.jsBroken/truncated/corrupt still-image salvageStrip junk before JPEG SOI, append missing EOI, rebuild damaged headers from a reference photo, carve embedded images out of a blob. ensureJpegHuffman() grafts the standard JPEG Huffman tables (ITU-T T.81 Annex K) onto a JPEG that has a scan but no DHT - the Motion-JPEG frame case, where the tables live once in the video header and every browser renders the tableless frame blank; deterministic, baseline-only, a no-op for a JPEG that has its own tables
jpeg-salvage.jsFault-tolerant baseline JPEG decoderdecodeJpegPartial(bytes) decodes a JPEG MCU by MCU and, the moment the entropy stream is truncated or a Huffman code goes invalid, stops and returns the rows it got (real top + mid-grey fill) instead of failing. This recovers the picture where the browser's own decoder renders a fragmented/corrupt JPEG as nothing. It also catches the harder case where the bitstream desynced but kept matching valid Huffman codes, so the decode "succeeds" into garbage (the DC predictor runs away and blocks pin to saturated neon colour-block noise, as the browser also paints): detectCorruptCut() finds that blowout - a sustained band of channel-pinned, high-chroma pixels - then walks back to the desync onset (the first flat DC-only band a textured band led into). The raw colour pixels are kept, not greyed (that's the picture a lenient system viewer shows, and it's what the user wants to see), but corrupt: true is set and realRows records where the real image ends, so callers caption it honestly (top N% real, the rest decoder noise). A terminal-to-the-bottom guard (the blowout must reach the bottom quarter) plus the two-stage test means a real bright sky, black shadow or vivid sunset (saturated but with normal content elsewhere) never trips it. Pure/DOM-free (returns RGBA + rows + thumb + corrupt + realRows), baseline sequential only, with a standard-Huffman fallback for tableless MJPEG frames. When the main image decodes to nothing (its body overwritten) it falls back to the file's embedded EXIF thumbnail in the surviving header (findEmbeddedThumb, returned with thumb: true), so a lost photo still shows a real preview. detectCorruptCut is exported and also run on the browser's own decode by the carve galleries (diskimage.js, carve-gallery.js) and the photo view (photo.js), so a desynced-but-decodable JPEG is flagged (caption/tooltip + the photo salvage note) instead of passed off as a healthy photo
sonify.jsImage -> sound ("sonify")Inverse of spectrogram.js: each image column becomes one instant of frequency content, resynthesised as audio
tiff.jsMulti-page TIFF page extractionWalks IFD chain in pure JS; spins up ImageMagick to render pages to PNG only when there are 2+ pages, then feeds embedded-images.js
mpo.jsMPO / Multi-Picture Format image extractionParses the MPF index in the JPEG APP2 segment; pure parsing, no decode
ico.jsICO/CUR icon directory extractionRebuilds a minimal single-image blob per directory entry (PNG and classic BMP/DIB); no WASM
embedded-images.jsShared "Embedded images" cardPure-DOM layout used by ico.js, mpo.js, tiff.js, and photo.js (for every photo's cached EXIF thumbnail/RAW preview) to show each packed image on a checkerboard with size/format/download
carve-gallery.jsShared carved-image galleryBare thumbnails (no card) with Analyse/Download overlaid on hover, matching the PDF page previews. Each thumbnail decodes lazily on scroll into an IntersectionObserver-driven downscaled canvas and releases its blob URL, so nothing blocks the analysis behind it. Decodes run through a one-at-a-time queue so a scroll that reveals many large carves can't exhaust the browser's image decoder into false blanks. Browser-first with a salvage fallback: when the browser renders nothing from a fragmented/corrupt JPEG, jpeg-salvage.js recovers whatever top strip survives and that raster is shown (and used in the lightbox); when the browser instead draws a desynced JPEG into colour-block garbage, detectCorruptCut flags the cell corrupt while keeping that raster on show. Whatever decodes is shown - partial strips, grey fill and all - and only a carve with no decodable raster at all keeps its text placeholder. Used by photo.js (salvage view) and unknown.js; diskimage.js keeps its own copy for the frame toggle and lightbox paging

Audio#

ModuleHandlesNotes
audio.jsAudio module entry pointUploaded files, mic recording, live spectrogram; waveform + file info
audio-analysis.jsPure-computation audio metricsLevel stats, spectral centroid, LUFS loudness, pitch (YIN), tempo, stereo metrics - no DOM, no Web Audio
audio-forensics.jsPure-computation audio forensics (UI-free)One Welch long-average spectrum reused for a lossy-transcode / "fake lossless" verdict (spectral cutoff -> probable source bitrate), mains hum / ENF (50/60 Hz + harmonics, implied region), ultrasonic content scan (>18 kHz energy + tones) and musical key (chroma + Krumhansl-Schmuckler); plus a full EBU R128 meter (gated integrated, momentary/short-term, LRA), true-peak (4x-oversampled dBTP), a signal-health trio (crest factor, DC offset, effective bit depth) and a DTMF touch-tone decoder (Goertzel). audio.js renders the cards
audio-codec.jsContainer/codec sniffingPeeks file header for sample rate/bit depth/codec hints; wraps raw AAC (ADTS) in a minimal M4A container
audio-player.jsCustom <audio> transportPlay/pause, draggable seek track, time readout; shared by audio.js and (via re-export) video.js
spectrogram.jsSpectrogram enginePure-JS FFT/STFT pipeline, no audio-library dependency; also the image-tie-in used by sonify.js's inverse
media-reverse.jsReversed audio playback + downloadFlips channel samples of an already-decoded AudioBuffer, re-encodes as WAV via the AVI module's PCM-WAV encoder

Video#

ModuleHandlesNotes
video.jsVideo module entry pointPlayback, container/codec detection, frame rate, frame capture (routed to photo.js), audio track extraction (decoded, then the full Sound section via audio.js's renderAudio pre-decoded entry point), scene-change detection and a content timeline (movie barcode + brightness curve + black-frame/freeze flags, buildContentTimelineCard, sharing the scene sampler's seek loop)
video-avi.jsAVI (RIFF) container parsingReads header for dimensions/codec/audio format, pulls raw MJPEG frames + PCM audio from movi, re-wraps PCM as playable WAV; used when the native <video> path fails
video-recover.jsTruncated/unfinalised MP4-MOV recoveryRecovers playable video with no moov index by carving H.264/H.265 from mdat, borrowing SPS/PPS in-band or from a reference clip
video-bitstream.jsBelow-the-container metadata (UI-free)The one place H.264/H.265 SPS parsing lives: profile/tier/level, coded size + conformance window, bit depth, chroma, progressive/interlaced, and the VUI colour description and frame rate (which for H.265 sits past the short-term reference picture sets and the scaling lists, so a naive parser desynchronises before reaching it). parseAvcC() / parseHvcC() read the codec-configuration records MP4 sample entries and Matroska CodecPrivate both use - including the SPS they embed, so colour and frame rate are recovered even with no colr box. parseMatroskaTracks() walks EBML by seeking past the clusters for Segment Info (duration, title, muxing/writing app, date) and the full Tracks list, returning the same { video, audio, durationSec } shape as the ISOBMFF walk so video.js has one readout path for every container. Consumed by video.js and video-forensics.js
video-forensics.jsISOBMFF container-structure + bitstream parser (UI-free)analyzeMp4Structure() walks the MP4/MOV boxes with zero decoding to return a recursive box (atom) tree, full track enumeration (handler/codec/language/duration/samples/edit-list/tmcd start-timecode/timed-metadata streams), provenance "tells" (faststart, ftyp brands, multi-segment edit lists, padding, multiple mdat, fragmentation, trailing data) and a GOP/keyframe/per-second-bitrate map with a VFR-vs-CFR verdict. analyzeBitstream() goes a layer deeper, on the shared SPS parsers in video-bitstream.js (profile/level, coded size, chroma, bit depth, progressive/interlaced, VUI colour + frame rate): a stream-vs-container consistency verdict (re-encode/re-tag tell), the x264/x265 encoder fingerprint from the first frame's user_data_unregistered SEI, HDR mastering-display (mdcv) / content-light (clli) values and Dolby Vision config, and detection of a C2PA / Content Credentials manifest in a top-level uuid box. video.js's Advanced card renders the chrome
video-sync.js (core/)Shared player↔analysis scrubbing syncNot a renderer module itself but the shared helper video/audio renderers use to sync playback position with readouts
sony-rtmd.jsSony rtmd (Real-Time MetaData) gyro/IMU extractionReads Sony Alpha/FX/RX cameras' timed-metadata track (exposure/lens/GPS + gyro/accelerometer samples)
video-telemetry.jsGoPro GPMF / Android CAMM / container-GPS telemetryextractGpmf() KLV-walks the gpmd track (GPS5/GPS9 position+speed, ACCL/GYRO with SCAL divisors, per-frame ISOE/SHUT/WBAL exposure, TMPC temperature, GPSF fix) and collects every stream's STNM self-describing name so a clip with no GPS still surfaces its full telemetry inventory; extractCamm() reads little-endian camm packets (gyro/accel/GPS); extractContainerLocation() parses a single ISO-6709 point (©xyz / Apple location key). Draws the GPS track on a local canvas (no map tiles fetched) with an opt-in OpenStreetMap link, and reuses sony-rtmd.js's buildImuTimeline for the motion traces. appendTelemetryCards() is the entry point

Animation / frames#

ModuleHandlesNotes
gif-frames.jsGIF frame-by-frame decodeHand-written LZW decoder + disposal/transparency/interlace compositing; pure logic, no DOM
gif-encode.jsAnimated-GIF re-encodingMedian-cut quantisation + custom GIF-variant LZW writer; used by the reverse-playback download feature
webp-frames.jsAnimated WebP frame decodeUses the browser's ImageDecoder (WebCodecs) rather than hand-rolled VP8/VP8L decoding
lottie.jsLottie/Bodymovin JSON vector animation playerPlays via vendored lottie-web; handles plain .json, dotLottie .lottie ZIPs, and Telegram .tgs gzip stickers

Documents#

ModuleHandlesNotes
pdf.jsPDF viewerLazy-loads pdf.js; metadata, text, page thumbnails
paged.jsShared "page preview" presentationMirrors the PDF page experience for formats with no native page geometry (Word/ODF text, spreadsheets, presentations). Also owns pagePreviewSkeleton(), the empty page-shaped placeholder card every paged renderer (pdf.js included) shows until its real sheets exist
djvu.jsDjVu scanned-document viewerVendored pure-JS DjVu.js; decodes pages to ImageData, paints to canvas with prev/next paging
docx.jsDOCX (OOXML) viewerMetadata, formatted text, tables, text extraction
xlsx.jsXLSX (OOXML) viewerEach worksheet as a table with sheet tabs and metadata
xlsb.jsExcel Binary Workbook viewerVendored SheetJS community build decodes BIFF12, rendered with the same table UI as xlsx.js
pptx.jsPPTX slide viewerEach slide as a card: title + body text and embedded images, in order
odf.jsOpenDocument viewer (ODT/ODS/ODP)Converts content.xml into the shared paged.js presentation, reusing the DOCX/XLSX/PPTX-style views
legacy-office.jsLegacy binary Office (DOC/XLS/PPT 97-2003)OLE2/CFBF containers; best-effort text extraction (Word FIB piece table) shown via the page-sheet preview
textdoc.jsText and lightweight-markup familyRTF (control words stripped), AbiWord, FictionBook, HWPX, MHTML, plus DITA/TEI/JATS/reStructuredText/AsciiDoc/Org/Textile/TeX/BibTeX as selectable source
iwork.jsApple iWork viewer (Pages/Numbers/Keynote)Shows the baked-in QuickLook preview (Preview.pdf via pdf.js, or the largest thumbnail) - iWork's real content (Snappy-compressed protobuf) isn't reconstructable
epub.jsEPUB readerMetadata, cover, chapter-by-chapter reading with navigation
mobi.jsKindle/Mobipocket e-book readerVendored foliate-js mobi.js decodes MOBI6/KF8; section-by-section sandboxed-iframe reader
mdb.jsMicrosoft Access database viewerVendored mdb-reader; lists tables with columns/row counts + sample rows
notebook.jsJupyter notebook (.ipynb) viewerRenders markdown/code/raw cells with captured outputs (text, images, errors)
markdown.jsMarkdown rendererSelf-contained CommonMark-ish + GFM parser (headings, tables, task lists, fenced code); all text HTML-escaped

Design / CAD / 3D#

ModuleHandlesNotes
svg.jsSVG inspectorRenders at actual size; stats, element counts, colour palette, text content; strips active/unsafe content
illustrator.jsAdobe Illustrator (.ai) viewerModern .ai is PDF-compatible, opens via pdf.js; older EPS-based .ai falls back to identification
psd.jsPhotoshop PSD/PSB viewerLightweight header read (dimensions, colour mode, embedded thumbnail) plus a full composite render + layer tree
paint.jsKrita/Procreate raster appsReads the baked-in flattened preview (mergedimage.png / Thumbnail.png); per-layer data isn't reconstructable
diagram.jsdraw.io/diagrams.net and DXF vector diagramsDecodes mxGraph XML (incl. deflate+base64) or DXF entities to an SVG preview
lut.jsColour LUT (.cube) viewer + visualiserParses Adobe/Iridas/Resolve LUT text format; also handles .look Adobe SpeedGrade grade stacks
font.jsFont specimen viewer (TTF/OTF/WOFF/WOFF2/TTC)Live FontFace API specimen (true rendering, variable-font axis sliders) plus vendored opentype.js for glyph grid/metadata
stl.jsSTL 3D viewerParses binary+ASCII STL; self-contained WebGL viewer (orbit/zoom/spin) with geometry stats
model3d.js3MF / STEP / IGES / OBJ / PLY / glTF / FBX viewer3MF parsed natively (fflate+regex); STEP/IGES tessellated via lazy OpenCASCADE WASM; shares stl.js's WebGL viewer
gcode.jsUniversal G-code analyser & 3D reconstructorParses slicer and CNC/CAM G-code dialects; reconstructs deposited filament (not just centreline) in an interactive WebGL viewer
unity.jsUnity asset viewerParses Unity's YAML object-stream dialect (scenes, prefabs, materials, animators, .meta)
dwg.jsAutoCAD DWG viewerVendored libredwg-web (WASM, lazy) parses the drawing to an entity database, rendered as an SVG 2D preview
solidworks.jsSolidWorks part/assembly/drawing readerOlder files (OLE2) expose a render preview + metadata; modern encrypted files are identify-only
f3d.jsAutodesk Fusion 360 (.f3d/.f3z) readerZstd-compressed ZIP; shows the baked thumbnail + manifest/contents - the proprietary BREP geometry isn't reconstructable

EDA / NLE#

ModuleHandlesNotes
altium.jsAltium Designer schematic/PCB/library viewerOLE2 Compound Files (shared cfbf.js reader), rebuilt as an interactive vector view
kicad.jsKiCad schematic/PCB/library/project viewerS-expression text format (KiCad 6-9), rebuilt as an interactive vector view
spice.jsSPICE/LTspice raw waveform viewerBinary or ASCII .raw dumps from ngspice/LTspice; parses header key/value block + sample data
ipcnet.jsIPC-D-356(A) fabrication/test netlist viewerFixed-column text format: parameter lines + one feature record per test point
aftereffects.jsAdobe After Effects project (.aep) viewerReverse-engineered RIFX (big-endian RIFF) chunk-list parser rebuilding comp timelines
premiere.jsAdobe Premiere Pro project (.prproj/.prel) viewerGzip-compressed XML object graph (ObjectID/ObjectUID references) rebuilt into sequences
davinci.jsDaVinci Resolve project (.drp/.drt) viewerZIP of exported XML documents; rebuilds each timeline's track/clip layout
vegas.jsSony/MAGIX VEGAS Pro project (.veg/.vf) viewerRIFF-GUID container; per-event/track layout keyed by undocumented GUIDs, so recoverable metadata is surfaced rather than a full timeline
timeline.jsEditing-timeline viewer (EDL/FCPXML/OTIO)Normalises the standard NLE interchange formats into one visual tracks×time clip view

Data / archive#

ModuleHandlesNotes
csv.jsCSV/TSV previewDelimiter detection, quoted-field parsing, per-column type inference, numeric stats, first-100-row preview
gcsv.jsGyroflow .gcsv IMU log viewerParses the generic IMU-log interchange text format (gyro/accelerometer traces)
dataview.jsHAR / JSON5-JSONC-Hjson / .nfo text-art viewersThree lightweight viewers sharing a "show what people care about" goal
gitobject.jsGit object viewerLoose objects inflated with the browser's DecompressionStream (no library); pack files/indexes read for header info
email.jsEmail message viewer (.eml/.emlx/.mbox)Parses RFC 822/MIME headers (RFC 2047 decoding) and walks the MIME tree for a displayable body
archive.jsZIP archive inspectionLazy-loads fflate; shares folder-archive-shared.js for treemap/breakdown/tree views
zip.jsShared ZIP readerCentral-directory-first reads with ranged fetches per entry (order-independent, no full-file load); sequential fallback for truncated archives
folder.jsDropped-folder overviewRecursive webkitGetAsEntry walk; treemap + summary via the shared folder/archive modules
treemap.jsNested squarified treemap (WizTree-style)Canvas-based, files sized by bytes and coloured by category, with hover tooltips and click-to-analyse
folder-archive-shared.jsShared folder/archive helpersCategory classification, breakdown cards, view toggle (treemap/tree), used by folder.js and archive.js
diskimage.jsRaw disk-image browser (.img/.ima/.dsk)Mounts a FAT12/16/32 volume - bare "superfloppy" or first FAT partition of an MBR disk - and reuses renderHandleTree for the tree/treemap. Reads a prefix, not the whole image: the layout is settled from the first sector, then the tree is parsed from candidate + 16 MB, quadrupling only while vol.shortRead says the walk ran off the end (a 488 MB card settles on one 16 MB read). The full image is read lazily - on first click of a file whose bytes sit beyond the prefix, and by the sector-carve scan. The "Images in this disk" section sits directly under the file tree and is opt-in: it shows a "Scan for images" button rather than running automatically (the scan reads the whole image and carves every signature). The carve scan is chain-aware (recoverViaChain): a carve starting on a cluster with a surviving, fragmented FAT chain is read along that chain so a scattered file reassembles correctly, instead of the straight contiguous carve splicing in another file's body. Carved JPEGs pass through ensureJpegHuffman (photo-recover.js), so a tableless Motion-JPEG frame - the bulk of what a scan turns up on a card that held video - gets the standard Huffman tables grafted on and previews instead of rendering blank. Thumbnails decode through a one-at-a-time queue (a scroll can bring dozens of full-size photos into view at once, and decoding them concurrently exhausts the image decoder into false blanks). Nothing is hidden by content: every carve that produces any raster is shown - a partial top strip, flat grey, noise and all - so the gallery reflects everything the scan found, not just the intact photos. Decoding is browser-first with a salvage fallback: a fragmented/corrupt JPEG the browser refuses is handed to jpeg-salvage.js, which recovers the surviving top rows (shown, and used full-res in the lightbox); only a carve nothing can decode keeps a text placeholder. Carve previews and the lightbox draw the raw stored raster (image-orientation: none), ignoring any EXIF orientation tag, so a preview always matches the reported pixel dimensions and the salvage decoder (which never rotates) - a landscape carve with a spurious rotate tag is shown as-stored, not silently flipped to portrait. The transparent/mid-grey fill fraction (emptyFraction / classifyFill) is kept purely as a forensic label - ok / partial / empty - surfaced in the hover tooltip. When a photo's full-size image was overwritten but its header cluster (with its EXIF thumbnail) survived, the salvage decoder falls back to that embedded thumbnail, so even a lost photo shows a real preview of its scene (labelled "embedded thumbnail") rather than nothing. Each carved photo's EXIF capture date is read from its header (carveExifDate, a bounded byte-scan for the Exif block - survives carving even for deleted files), shown on the cell and offered as a Sort control (newest first by default, then oldest or largest); the sort re-orders the existing cells in place, and photos with no date sink to the bottom
diskimage-fat.jsFAT + MBR parser (pure, no DOM)Byte half of the above, dependency-free so it runs under Node against a real image. Cluster-chain loop guards, entry/depth caps, bounds-checked reads. Reports shortRead when any read fell outside the buffer (the prefix-growth signal) and exposes geom + readFileBytes() so contents can be read from a different, fuller buffer without re-parsing
comic.jsComic book archive viewer (CBZ/CBR/CBT/CB7)Metadata card + page-thumbnail grid + lightbox reader; CBZ is ZIP, CBT is TAR, CBR/CB7 via lazy libarchive WASM
midi.jsStandard MIDI File (.mid/.midi) readerHand-written SMF parser: tempo map, time/key signature, track names, GM instruments, note counts - no playback
subtitles.jsSubtitle files (SRT/WebVTT/ASS/SSA/MicroDVD/SubViewer)Parses cues into a timed list with counts/timing/styling; sniffs which format an overloaded .sub actually is
lrc.jsLRC timed-lyric filesParses ID tags and timestamped lines, including word-level enhanced tags
geo.jsGeospatial files (GPX/KML/GeoJSON)Tracks/placemarks/features with distance/bounds/time span; plotted on lazy-loaded Leaflet/OSM
tablekit.jsTable-analysis workbenchMounted below CSV/XLSX/XLSB/ODS analyses: virtualised grid, stats bar, hand-drawn chart builder, PNG/JSON/CSV export
vssolution.jsVisual Studio solution (.sln/.slnx) manifest viewerLine-based text parser for projects + build configurations

Cross-cutting / fallback / infrastructure#

ModuleHandlesNotes
unknown.jsUnknown-file inspector (fallback renderer)Magic-byte format guess, hex/ASCII dump, SHA-256, enhanced previews for text/JSON/XML; byte-entropy heatmap for binary blobs. Embedded-image carving is button-gated ("Scan for images"), not automatic - sweeping and decoding up to 128 MB is heavy on a large blob (a disk image, a system backup), matching the disk-image renderer's control. Can hand off to photo-recover.js/photo.js
proprietary.jsProprietary-format identificationIdentifies 200+ formats by extension/magic bytes; dispatches to lazy parsers/parsers-<chunk>.js modules for deeper metadata
proprietary-formats.jsProprietary format catalog (data only)The FORMATS table proprietary.js drives; pure data, no logic
compare.js/compare two-file side-by-side viewRuns each file through its normal renderer off-screen, merges readout cells into Field | A | B tables

See docs/features/*.md for the user-facing usage detail behind each of these modules, and parsers-and-libs.md for the lazy parser chunks and shared binary/WASM helpers they depend on.