PixelPeek
Pixel-level raw image viewer for VS Code. Open YUV and Y4M files directly in the editor, read raw sample values under the cursor, step through frames, and compare two files with a per-pixel diff and PSNR — without leaving your code.

Two consecutive frames of the bundled bounce sequence (A, B) and the channel-coded Diff view at ×4 gain — red = ΔY, green = ΔU, blue = ΔV. Rendered by the extension's own decoder from testdata/.
Features
- Formats: I420, NV12/NV21, YUV422 planar, YUV444, Y grayscale, and Y4M (resolution, fps, subsampling and bit depth read from the header)
- Bit depth: 8/10/12/16-bit, little or big endian; P010/P016 (MSB-aligned semi-planar) and ffmpeg-style
yuv420p10le planar
- Pixel inspector: hover for
(x, y), raw Y/U/V at native scale (0–1023 for 10-bit) and the converted RGB
- Pixel grid + values: at high zoom every pixel gets a grid cell with its Y/U/V printed inside (Δ values in Diff mode)
- A/B compare: load a second file, switch A / B / Diff, ×1–×16 diff gain, per-component PSNR in the status bar — works across bit depths and subsampling (8-bit recon vs 10-bit source is fine)
- Multi-frame, any length: frames stream from disk on demand with prefetch — multi-GB sequences open instantly; ←/→ stepping, Space to play at the file's fps, first/last jump
- Color science: BT.601 / BT.709 / BT.2020, limited or full range, Y / U / V channel isolation
- Export: current view as PNG at native resolution; whole sequence as Y4M (any layout → planar, 10-bit+ written as LE)
- Zero-config open: format from the extension, resolution from the filename (
clip-1920x1080.yuv) or file size, bit depth from names like p010, yuv420p10le, 10bit
- Per-file view settings persist — only what you change, never a guess

10-bit I420 color bars (BT.709), a P010 gradient, and the same gradient's U plane in channel view.
| Layout |
Extensions |
Bit depths |
| I420 (4:2:0 planar) |
.yuv .i420 |
8 · 10/12/16 LSB-aligned, LE/BE |
| NV12 / NV21 (4:2:0 semi-planar) |
.nv12 .nv21 .p010 .p016 |
8 · 10/16 as P010/P016 (MSB-aligned) |
| YUV422 planar |
.yuv422 .yuv422p .i422 |
8 · 10/12/16 |
| YUV444 planar |
.yuv444 .yuv444p |
8 · 10/12/16 |
| Y (grayscale) |
.y .gray |
8 · 10/12/16 |
| YUV4MPEG2 |
.y4m |
C420* C422 C444 Cmono, plus p10 / p12 / p16 variants |
Any file can be reinterpreted from the toolbar — format, size, bit depth and byte order are all live controls (locked for Y4M, where the header is authoritative).
Usage
| Action |
How |
| Open |
Click any file with a supported extension, or Reopen Editor With… → PixelPeek |
| Zoom |
Fit / 100% / − + buttons, or Ctrl/Cmd + wheel |
| Frames |
← → step, Space play/pause, ⏮ ⏭ first/last |
| Inspect |
Hover the image; values appear in the status bar |
| Grid |
Grid toggle — lines from 600% zoom, values from 2800% |
| Compare |
A/B… picks file B, then A / B / Diff and gain; ✕ closes |
| Export |
PNG ↓ saves the current view; Y4M ↓ writes every frame |
Compare details
- Raw B follows A's format, size, bit depth and byte order; a Y4M B uses its own header (resolution must match A).
- Diff is computed at the larger of the two bit depths; chroma is sampled on the luma grid using each side's own subsampling, so I420 vs YUV444 works.
- PSNR is per component over the luma grid — identical to plane-based PSNR when subsampling matches. Lossless shows as
∞.
- If B is shorter, it holds its last frame.
Notes
- Frames are read on demand from disk (the current frame, the next one, and a small LRU cache), so file length is not limited by memory — a 300-frame 8K 10-bit sequence opens like a 1-frame one. Per-frame cost still scales with resolution (~0.4 s to convert one 8192×8192 frame on an M-series Mac).
- Chroma is displayed nearest-neighbor (no upsampling filter) on purpose — you see the samples that are actually in the file.
- Y4M export writes planar 4:2:0/4:2:2/4:4:4/mono with
FRAME markers and the source fps (25 fps for raw input); higher bit depths are written little-endian, LSB-aligned.
Development
npm install
npm run gen-testdata # sample files into testdata/
npm run sanity # decoder / parser / export round-trip checks
# open this folder in VS Code and press F5, then open a file from testdata/
npm run package # build .vsix
testdata/ includes color bars (8-bit I420/422/444 and 10-bit I420), gradients (NV12, NV21, P010, gray), a 12-frame bouncing-box sequence as raw .yuv plus 8-bit and 10-bit .y4m, and a tiny 8×8 quad for pixel-inspector checks.
Roadmap
- Bayer raw + TIFF Bayer (RGGB/BGGR/GRBG/GBRG) with demosaicing
- Drawing tools (boxes/points/lines, absolute or normalized coordinates)
- U/V heatmap rendering
License
MIT
| |