fix(viewer): warn upfront when a NIfTI volume is too large to display (#228)#256
Merged
Merged
Conversation
…#228) High-resolution volumes whose uncompressed voxel data exceeds the ~2 GB browser ArrayBuffer/WebGL-texture limit previously failed with "Array buffer allocation failed" (VS Code) or rendered as garbage with blur/sobel shader errors (online viewer) after a slow load. Detect this from the NIfTI header and show an actionable "Image too large to display" warning before any allocation. - New @niivue/react nifti.ts computes the uncompressed voxel byte length from the NIfTI-1/2 header. For .nii.gz it inflates only the gzip header prefix, so the true uncompressed size is used, not the compressed file size on disk. - buildImageMessageBodies peeks the header via file.slice(), so an oversized local file is never read into memory at all. - loadVolume guards every other host: in-memory buffers (Jupyter, Streamlit, VS Code binary) and URL streams (VS Code local files, fetched header-only and then aborted). - The on-canvas overlay shows an amber "Image too large to display" warning with the size and a downsample/crop hint. Verified with new unit tests (nifti, oversized-guard) and a new e2e test, plus turbo type-check (8/8) and lint (10/10). Closes #228 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
🚀 PWA Preview DeploymentYour PWA preview has been deployed! Preview URL: https://niivue.github.io/niivue-vscode/pr-256/ This preview will be updated automatically when you push new commits to this PR. |
Contributor
Coverage ReportOverall line coverage: 45.2% (+2.4) vs
|
Contributor
🧹 PWA Preview CleanupThe preview deployment for this PR has been removed. |
korbinian90
added a commit
that referenced
this pull request
Jun 20, 2026
Reconcile #256 (warn upfront when a NIfTI volume is too large to display, issue #228) with the @niivue/niivue v1.0 core migration. Resolution: - utility.ts import conflict: the migration switched to the v1 default export (import NiiVue, plus `import type { NVImage }`); #256 added the nifti-guard import (isNiftiName, NIFTI_PEEK_BYTES, niftiTooLargeWarning from './nifti'). Kept the migration's default-export form and folded in #256's nifti import. - #256's header-peek guard (file.slice -> niftiTooLargeWarning, push an ImageMessageBody with loadError) lives in the shared file-reading loop and is unaffected by the migration's loader rewrite, which acts downstream in NiiVueCanvas/events. NiiVueCanvas.tsx, Volume.tsx and utility.test.ts auto-merged. Verified (forced, uncached): turbo type-check 8/8, turbo build 8/8, @niivue/react 179 unit tests pass (16 files, incl. #256's nifti suite). The streamlit python test fails only on a missing local pytest (env, pre-existing). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Opening high-resolution anatomical data (>2 GB uncompressed) failed badly (#228):
Array buffer allocation failed.niivue-error blur shader/sobel shaderconsole errors.Root cause: a single browser
ArrayBuffer/ WebGL texture is capped at ~2 GB, so a volume whose uncompressed voxel data exceeds that cannot be allocated or uploaded. The viewer tried anyway, slowly, then failed or rendered garbage.Fix
Detect the oversized case from the NIfTI header and show an actionable warning before any allocation, instead of loading slowly into a blank canvas or a cryptic error.
.nii.gzis taken into account: the check inflates only the first ~64 KB of the gzip stream to read the header, so it uses the true uncompressed size, not the compressed file size on disk.Where the guard runs (all in
@niivue/react, the shared webview layer every host uses)nifti.ts(new): parses NIfTI-1/2 headers (endian-aware, int64 dims) intoproduct(dim) * bitpix / 8, inflates the gzip header prefix, and returns a warning when voxels exceed 2 GiB. Fail-open: any uncertainty returnsnull, so normal loads proceed and genuine errors still surface.buildImageMessageBodies(browser file picker / drag-drop): peeks the header viafile.slice(), so an oversized local file is never read into memory at all.loadVolume(universal net): guards in-memory buffers (Jupyter, Streamlit, VS Code binary) and URL streams alike. VS Code local files stream by URL with no data buffer, so that path fetches only the header and aborts the rest of the download.Volume.tsx: the oversized case renders an amber "Image too large to display" overlay with the size and a downsample/crop hint.Testing
nifti.test.ts(16 cases: NIfTI-1/2 parsing, endianness, gzip header inflation including a truncated prefix, the size boundary) and new oversized-guard cases inutility.test.ts(including proof the whole file is never read). Full@niivue/reactsuite: 161 passing.ErrorHandling.spec.ts; Images / Meshes / Overlays / 4D-navigation still pass, confirming normal and 4D volumes load and the added header-fetch does not regress the URL path.turbo type-check8/8 andturbo lint10/10.Notes for reviewers
vscode.workspace.fshas no partial read and the extension also targets web (no Nodefs), so a header-only.nii.gzpeek is not possible extension-side. The webview header-fetch covers VS Code local + remote and.nii/.nii.gzuniformly.Closes #228
🤖 Generated with Claude Code