Skip to content
| Marketplace
Sign in
Visual Studio Code>Data Science>TIFF Scientific ViewerNew to Visual Studio Code? Get it now.
TIFF Scientific Viewer

TIFF Scientific Viewer

Computational-Imaging

|
7 installs
| (0) | Free
ImageJ-style preview for scientific TIFF images (float32/16-bit CT, stacks) with display-range contrast control.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

TIFF Scientific Viewer

Preview scientific TIFF images inside VS Code — including the 32-bit float, 16-bit and signed CT/microscopy images written by tifffile, which VS Code's built-in image preview and the general-purpose TIFF extensions cannot open.

The contrast model is a direct port of ImageJ's: the pixel data is never modified, and a separate display range (min, max) is mapped to the screen. That is the difference between a black rectangle and a readable CT slice.

full range versus ImageJ Auto

The same slice: full data range on the left, Auto on the right.

Why

A CT slice normalised to [-1, 1] has most of its structure packed into a narrow band. Rendered naively across the full data range it looks almost black. ImageJ's Auto finds the band; so does this.

For sample.tif in this repo, the data spans [-1.0000, 0.9805] but Auto picks [-1.0000, -0.1490] — everything above -0.149 is bone and saturates, and the soft tissue that occupies most of the image gets the full 256 levels.

Features

  • Formats: 8/16/32/64-bit integer (signed and unsigned), float16/32/64, RGB and RGBA, palette; classic TIFF and BigTIFF, both byte orders.
  • Compression: none, LZW, Deflate/ZIP, PackBits, with horizontal (2) and floating-point (3) predictors. Strips and tiles, chunky and planar.
  • Contrast, ported from ImageJ:
    • Auto — ContrastAdjuster.autoAdjust, including the pixelCount/10 rule that stops a constant background from swallowing the stretch, and the stateful threshold that tightens on each press.
    • Enhance — ContrastEnhancer.stretchHistogram, saturating 0.35% by default.
    • Reset — the full data range.
    • Exact numeric min/max entry, for comparing two images on one scale.
    • Min/Max/Brightness/Contrast sliders and a draggable histogram.
  • LUTs: Grays, Inverted Grays, Fire, Ice, Spectrum, 3-3-2 RGB, Red/Green/Blue.
  • Stacks: multi-page files get a slice slider and arrow-key navigation. The display range is held across slices by default.
  • Readout: live x, y, value of the raw value under the cursor — the actual float, not the 8-bit screen value.
  • Zoom on ImageJ's ladder, cursor-anchored, nearest-neighbour always.
  • NaN / Inf are excluded from statistics and drawn in red.

Remote work

Built for the "processing runs on a remote box" workflow:

  • extensionKind is workspace, so the extension runs on the remote host where the files are. Nothing large crosses the SSH link except one slice.
  • Pages are decoded lazily and cached with a pixel budget, so a multi-gigabyte stack does not have to fit in memory.
  • Pixel data reaches the webview as base64 rather than a transferred ArrayBuffer, because structured clone of binary is not dependable across every VS Code transport (Remote-SSH, vscode.dev).
  • tifSciviewer.maxDecodedMegabytes (default 512) refuses an oversized page with a clear message rather than exhausting the login node.

Install

npm install
npm run build
npm run package        # produces tif-sciviewer.vsix
code --install-extension tif-sciviewer.vsix

Under Remote-SSH, install it into the remote host from the Extensions view ("Install in SSH: hostname"), or run code --install-extension in the remote terminal.

Then open any .tif/.tiff file. To get back to the raw bytes, use Open With… → Hex Editor.

Keyboard

Key Action
A Auto contrast (press again to tighten)
E Enhance contrast
R Reset to full range
F Fit to window
1 100% zoom
+ / - Zoom in / out
← → ↑ ↓ Previous / next slice

Drag to pan, wheel to zoom at the cursor, double-click to fit.

Settings

Setting Default Meaning
tifSciviewer.autoContrastOnOpen true Apply Auto when an image opens
tifSciviewer.defaultLut Grays LUT for newly opened images
tifSciviewer.recomputeRangePerSlice false Re-run Auto on every slice
tifSciviewer.saturatedPercent 0.35 Saturation used by Enhance
tifSciviewer.maxDecodedMegabytes 512 Per-page decode ceiling

Performance

Measured on a 2021 laptop; see docs/ITERATIONS.md for the profiling.

Open a 120-slice, 120 MB stack 1.9 ms (headers only)
Scrub that stack 3.8 ms per slice, ~5 MB heap
Decode a 2048² float32 page ~5 ms warm
Re-map 2048² on a slider drag ~20 ms per frame

Pages are decoded on demand, so the file never has to fit in memory.

Development

npm run typecheck
npm run build
npm test              # 197 tests

Fixtures are generated by tifffile itself, so the decoder is checked against the library that wrote the files:

python3 -m venv .venv && .venv/bin/pip install numpy tifffile imagecodecs
.venv/bin/python test/make_fixtures.py
.venv/bin/python test/make_contrast_truth.py

test/make_contrast_truth.py contains an independent Python transcription of the ImageJ Java, so the contrast tests are a genuine cross-check of the TypeScript port rather than a restatement of it.

To eyeball the pipeline without launching VS Code:

node tools/render.mjs sample.tif out.png --mode auto --lut Fire

docs/IMAGEJ_ANALYSIS.md holds the source-level analysis this is built from, docs/REQUIREMENTS.md the requirement IDs the tests trace to, docs/ITERATIONS.md the build log and known gaps, and docs/MANUAL_TEST.md the checklist for things the automated suite cannot reach.

Licence

MIT — see LICENSE.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft