Scientific raster format

Read ENVI rasters in JavaScript

ENVI stores a small text .hdr file beside a binary raster. PureJsImage opens ENVI Standard hyperspectral data and ENVI Classification class maps while preserving native numeric samples and declared metadata.

Import

import { openEnvi, renderSpectralBand } from 'purejsimage/scientific'

Minimal Node.js example

import { FileSource } from 'purejsimage'
import { openEnvi, renderSpectralBand } from 'purejsimage/scientific'

const dataset = await openEnvi({
  header: await FileSource.open('scene.hdr'),
  data: await FileSource.open('scene.img'),
  maxInputBytes: 2_000_000_000,
})
const display = await renderSpectralBand(dataset, {
  wavelength: 1648.7,
  range: { mode: 'percentile', low: 1, high: 99 },
  palette: 'viridis',
})
for await (const pixels of display.image.pixels) console.log(pixels.width, pixels.height)

Minimal browser example

import { openEnvi } from 'purejsimage/scientific'

const headerInput = document.querySelector<HTMLInputElement>('#header')
const binaryInput = document.querySelector<HTMLInputElement>('#binary')
const header = headerInput?.files?.[0]
const data = binaryInput?.files?.[0]
if (!header || !data) throw new Error('Choose an ENVI header and binary file')
const dataset = await openEnvi({
  header,
  data,
  maxInputBytes: data.size,
})
for await (const block of dataset.readPlane({
  z: 0, c: 172, t: 0, x: 0, y: 0, width: 512, height: 512,
})) console.log(block.data)

Supported features

FeatureSupport
ENVI StandardRead
ENVI ClassificationRead class names and exact RGB lookup colors; bounded categorical preview
InterleaveBSQ, BIL, BIP
Samplesuint8, int16, int32, float32, float64, uint16, uint32
Byte orderLittle-endian and big-endian
Spectral metadataBand names, wavelength centers, units, FWHM, default bands

Dataset mapping

ENVI samples map to X, lines map to Y, and bands map to C in MultidimensionalRasterDataset. Z and T are 1. Channel metadata retains each actual wavelength center. PureJsImage does not manufacture wavelengths between declared channels.

Bounded reads

The header is read eagerly because it is small. The binary source stays lazy. A browser File uses BlobSource and Blob.slice(). BSQ and BIL selections read the requested rows and bands. BIP reads the required interleaved row ranges. Opening a large file does not call File.arrayBuffer().

Display rendering

renderSpectralBand() selects the nearest actual wavelength channel. renderScientificPlane() selects a channel index directly. Display transfers run after the selected quantitative range is normalized: linear uses the normalized value; sqrt uses its square root; log uses log1p(999x) / log(1000); asinh uses asinh(10x) / asinh(10). Use measureScientificPlane() once and reuse its explicit range when only palette or transfer changes.

Classification maps

renderEnviClassification() uses the header's class lookup colors directly and nearest-neighbor sampling so categories are never blended. Callers must provide maximum output dimensions. The renderer reads one selected source row at a time, which allows the explorer to preview the 37,679 × 39,594 USGS Afghanistan mineral map without creating its roughly 6 GB full-resolution RGBA equivalent.

Unsupported features

Complex samples, 64-bit integer samples, other special ENVI file types, malformed headers, and mismatched binary lengths reject. ENVI writing and spectral-coordinate interpolation are not implemented.

Official specification

ENVI image files · ENVI header files

Scientific Raster Explorer · GSF guide · FITS guide · API · OME-TIFF