npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@photivra/engine

v2.24.0

Published

Scientific TypeScript engine for camera optics, exposure, focus, motion, sensor sampling, diffraction, and digital imaging calculations.

Readme

Photivra

Photivra is an open TypeScript engine for the science and mathematics of photography and digital imaging.

Pronunciation (IPA): /foʊˈtɪvɹə/

Photivra gives you a reusable, tested API for:

  • camera geometry and optics;
  • focus and depth of field;
  • exposure;
  • subject and camera motion;
  • sensor sampling;
  • diffraction;
  • cropping and framing;
  • stabilization approximations;
  • signal and noise.

Every calculation uses explicit units, documented assumptions, validation and provenance (a record of how the result was produced). Approximations are clearly labelled. Results are reproducible, and their limits are written down.

The source is licensed under Apache-2.0.

Related foundations

  • Digital optics foundations document the standalone stray-light irradiance, composed digital geometry and generic lens-correction APIs. They keep the optical/sensor capture model in charge, and make sampling and noise costs explicit. Production composition is separate.
  • The standalone SimulatedCapture contract stores format-neutral linear floating-point master data plus public metadata.
  • The standalone SDR rendering foundation keeps three steps apart: rendering after capture, output encoding, and adaptation to an external display. (SDR = standard dynamic range.) The processed output contract connects capture, WB and correction, with explicit input domains and bounded support.
  • The standalone Print planner works out printer-file geometry from native pixels only. It uses the physical image size, an independent viewing distance and explicit sampling conventions. It does not assess captured detail or print quality.

Quick start

Install the published ESM package below. The 2.24.0 release record and changelog describe the current release:

npm install @photivra/[email protected]

Simulate a photograph of a test chart with a generic camera, then read the developed sRGB pixels:

import { simulateCapture } from "@photivra/engine";

const capture = await simulateCapture({
  camera: "professional",
  lens: { fNumber: 8 },
  exposure: { mode: "manual", iso: 100, shutterSeconds: 1 / 125 },
  scene: { preset: "slanted-edge" },
  output: { width: 16, height: 16 }
});

console.log(capture.image.samples.length, capture.exposure.settings);
console.log(capture.assumptions.map((a) => `${a.id}: ${a.explanation}`));

simulateCapture() runs the full physical pipeline through the engine's existing contracts: scene radiance, lens, spectral sensor, noise, RAW readout, RAW development and optional JPEG. It lists every default and modelling choice it made in assumptions.

The Quick Start covers the inputs, the chart presets (slanted edge, Siemens star, step wedge, grey ramp, checkerboard, point grid, caller patches and, from 2.14, Photivra's own color patches), illuminants, white balance and limits.

The individual calculations are still available as small functions. For example, the horizontal field of view for a 36 mm sensor dimension and a 50 mm focal length:

import { calculateFieldOfView } from "@photivra/engine";

const horizontal = calculateFieldOfView({
  focalLengthMm: 50,
  sensorDimensionMm: 36
});

console.log(horizontal.value.degrees);
console.log(horizontal.provenance);

Start with the Developer Guide. Then use the Usage Guide and the API reference, which is generated from the package exports.

Repository main may describe newer, unreleased work. For the stable contract, use the docs bundled in the published package, or the exact v2.24.0 tag.

Documentation

Getting help

Use GitHub Issues for reproducible bugs, documentation problems and feature discussions. For security vulnerabilities, follow SECURITY.md.

What is implemented

The root package exports models in four areas. Each model is either deterministic or explicitly labelled as an approximation.

A few abbreviations used below: FOV (field of view), PSF (point-spread function: how a lens spreads one point of light), MTF (modulation transfer function), CA (chromatic aberration), AA (anti-aliasing filter), CFA (colour filter array, such as a Bayer mosaic), QE / EQE (quantum efficiency / external quantum efficiency), A/W (amperes per watt, a detector's responsivity), ADC (analog-to-digital converter), AE / AF / WB (auto-exposure / autofocus / white balance).

Optics and geometry

Exposure and motion

Color controls

  • White-balance control and Auto WB. Generic presets owned by the profile, manual gains, independent CCT (correlated colour temperature) plus tint, custom measurement, deterministic AWB priorities and AWB lock. Scene illumination and the RAW-like capture are never changed.

  • Image processing. All of these are cancellable approximations:

    • built-in bilinear Bayer demosaic kernels with mirrored borders, and AHD demosaic;
    • noise-optimal linear merge of a RAW HDR (high dynamic range) bracket;
    • conversion of merged radiance to linear BT.2020 (PQ and HLG are not part of 2.0; see THIRD_PARTY.md);
    • Reinhard and Durand–Dorsey tone mapping;
    • Mertens exposure fusion;
    • focus stacking;
    • panorama from known rotations;
    • bilateral and non-local-means denoise;
    • unsharp mask;
    • clearly synthetic film grain.
  • Colorimetry:

    • a labelled analytic approximation of the CIE 1931 colour-matching functions (CMFs), or CMF tables you supply;
    • spectral integration;
    • Planckian, illuminant A and CIE daylight illuminants;
    • CCT and Duv;
    • Bradford and CAT16 chromatic adaptation;
    • Kelvin + tint WB gains;
    • CIELAB and ΔE76/94/2000;
    • camera-matrix fitting;
    • Display P3 and Rec.2020 matrices;
    • sRGB, BT.709 and BT.1886 transfer functions;
    • hue-preserving gamut mapping.

    CIE and ColorChecker tables are not bundled.

Sensor and output

Data, validation, and composition

The package has no runtime npm dependencies.

Sensor/capture integration status

The sensor and capture foundations are deliberately additive: they add new APIs without changing existing ones.

The root engine exposes standalone APIs for:

  • physical sensor imaging area and native raster metrics;
  • independent X and Y geometric sampling pitch;
  • active-capture rectangles and physical camera orientation;
  • native ↔ oriented transforms for points, vectors and rectangles;
  • FOV for off-center and asymmetric active capture;
  • diagonal-based 35 mm-equivalent focal length;
  • evidence-backed sensor architecture metadata;
  • evidence-backed colour-sampling topology profiles: monochrome, any periodic mosaic, and structural-only layered colour declarations;
  • evidence-backed bindings between the native effective raster and the colour-site grid, plus capture-mode resolution of structural sources with an explicit grouped-mode phase and channel-site counts;
  • evidence-backed sensor optical-stack profiles: ordered physical components, microlens presence, and a separately declared effective anti-aliasing spatial response;
  • evidence-backed registration of sensor site centers, plus geometric sampling-aperture profiles (unresolved or resolved footprint) and the derived geometric sensitive-area fraction;
  • evidence-backed sensor spectral-response profiles, plus deterministic bounded spectral-quadrature plans that keep the wavelength measure separate from applying the response and from integrating the source spectrum;
  • evidence-backed capture-mode profiles: single, fixed or variable multi-frame acquisition; native, grouped or declared per-frame sampling; optional sensor-shift offsets; reconstruction stages; and a separate processed-image raster;
  • capture-specific native readout scan timing, with explicit provenance and no inference from output resolution;
  • capture exposure-window timing with independent opening and closing boundary schedules;
  • capture-local rotation trajectories for a stationary ray, driven by exposure windows (sensor readout deliberately excluded);
  • instantaneous inverse capture-scan rotation mapping at a caller-selected phase within the local exposure, still independent of sensor data-readout timing;
  • radiometry prerequisite/readiness assessment.

These contracts are not all composed into simulatePocCamera() yet.

  • POC API 0.20 composes staged capture geometry through final output and viewing: orientation, active-capture rectangles, output crop/raster, active/output FOV, 35 mm-equivalent focal length of the active capture, viewing-based CoC (circle of confusion) against the final retained physical area, orientation-aware subject framing, and explicit output pixel scaling.
  • Still not composed into the legacy POC: sensor-architecture metadata, colour-sampling topology profiles, native-effective-raster/colour-site bindings, sensor optical-stack profiles, sensor sampling-aperture profiles, capture-mode profiles, sensor readout scan timing, capture exposure-window timing, and radiometry-readiness profiles.
  • The separate production plan 0.7.0 runs its bounded, declared environment → sensor → RAW → output route.
  • Readout timing stays in invariant native sensor coordinates. Physical orientation is an explicit later transform.

The POC reports X/Y sampling diagnostics, but still uses one representative horizontal pitch internally for several pixel-domain calculations. It therefore rejects geometry whose X and Y pitch differ by more than 1%, instead of silently producing a directional error.

Likewise, radiometry readiness does not turn on photon/noise output in the POC. Integrating these foundations is separate future work, and should happen explicitly, not by silently changing what existing requests mean.

Sample use case

A developer wants to model how a change in camera settings affects an image.

The application gives Photivra camera and scene parameters — sensor dimensions, focal length, aperture, shutter speed, focus distance, subject distance and motion. It gets back structured scientific results describing effects such as:

  • field of view;
  • projected subject size;
  • depth of field and defocus;
  • diffraction;
  • subject-motion blur;
  • camera-shake blur;
  • pixel sampling;
  • crop and framing;
  • exposure relationships;
  • basic signal and noise behaviour.

Each result carries explicit units and model provenance. Approximations are clearly identified, not presented as exact physical measurements.

import {
  calculateFieldOfView,
  calculateDepthOfField,
  calculateProjectedMotionBlur
} from "@photivra/engine";

const fieldOfView = calculateFieldOfView({
  focalLengthMm: 200,
  sensorDimensionMm: 36,
  focusDistanceM: 22
});

const depthOfField = calculateDepthOfField({
  focalLengthMm: 200,
  aperture: 5.6,
  focusDistanceM: 22,
  circleOfConfusionMm: 0.03
});

const motion = calculateProjectedMotionBlur({
  focalLengthMm: 200,
  shutterSeconds: 1 / 1000,
  positionM: { x: 0, y: 1, z: 22 },
  velocityMps: { x: 10, y: 0, z: 0 },
  focusDistanceM: 22,
  pixelPitchMicrometers: 6
});

console.log(fieldOfView.value);
console.log(depthOfField.value);
console.log(motion.value);

The application can then use those results, while the photography calculations themselves stay in one central, tested, reproducible place.

Status

  • Repository package version: 2.24.0 (release candidate prepared November 12, 2026; publication is separate)
  • Engine API contract: 2.24.0
  • Versioned generic tier reference assets: GENERIC_TIER_PRESETS.md.
  • Sensor profiles from published specifications (#554, unnamed): SENSOR_PROFILES.md.
  • Composed POC simulation API contract: 1.0.0
  • Stability: 1.0 root-package compatibility policy; bounded scientific models and independent POC contract

From 1.0.1, the package version and ENGINE_API_VERSION are equal. New captures/plans record 2.24.0; existing archives keep their original creator identities. Schema, model and POC contract versions stay independent.

A breaking change to the root contracts now needs a new package major version. Additive and corrective changes follow compatibility and migration. A 1.0 package is not a claim of calibrated physical accuracy.

Creating a GitHub release/tag and publishing @photivra/engine are separate release actions. The publish workflow, triggered by the tag, checks that the vX.Y.Z tag matches the package version before publishing.

Image-formation integration boundary

The root engine exports getImageFormationContract(). It is a descriptive public contract covering: which scientific domain owns what, coordinate spaces, stage dependencies and couplings, the time basis, renderer warp/compositing rules, and the reserved order of sensor stages.

The contract does not claim that every listed stage is implemented. Reserved stages are future work, and simulatePocCamera() is unchanged at API 0.20. See Image-Formation Contract.

Important scientific limits

Photivra deliberately avoids claiming more than its current models support.

  • Focus-aware projection is ideal paraxial thin-lens geometry by default. A separate focus-breathing approximation, with a declared scale, can change projection and framing for one focus state. Photivra does not infer a breathing curve or claim calibration for any named lens.

  • Generic radial distortion is a field mapping parameterized by the caller, with an explicit physical normalization radius and an operating range in which it can be inverted. Decentering/tangential distortion and named-lens calibration are not modelled yet.

  • Generic illumination vignetting is only a field-dependent attenuation, linear in scene light and per channel. It does not model pupil clipping, cat's-eye bokeh, PSF changes or calibrated lens radiometry.

  • Generic lateral CA is an independent radial field mapping for abstract RGB renderer channels. It is not a spectral lens model, a sensor-CFA calibration, a longitudinal-CA model or a named-lens profile.

  • The legacy projected-motion primitive follows one representative point. Separate extended-object and depth-direction temporal projection supports declared rigid reference geometry and constant linear motion. Visibility, deformation and radiance accumulation remain the caller's responsibility.

  • The legacy stabilization-equivalent camera-shake API is still one global yaw/pitch image-plane vector. Separately:

    • a low-level rotation-only mapping models yaw/pitch/roll image motion that depends on field position;
    • depth-aware translation/parallax quadrature is available;
    • generic stabilization models with response, latency and limits are available.

    Neither models calibrated commercial IBIS/OIS (in-body / optical image stabilization). The bounded production environment route uses only its declared constant-axis rotation.

  • Native sensor readout timing uses a caller-declared, uniform, linear, single-axis spatial phase approximation. Capture data-readout duration and rolling spatial skew are separate evidence-backed facts. The model does not treat one effective raster row or column as one physical hardware readout line, and does not yet model non-uniform or segmented readout or rolling-shutter image distortion.

  • Readout/exposure linkage can assert only a normalized native spatial-phase/order relationship to an electronic exposure boundary. It does not establish absolute readout-versus-exposure timing. Equal directions or equal timing spans are never treated as proof of synchronization.

  • Capture exposure-window timing models opening and closing boundaries independently, as simultaneous or uniform-linear native scans. It checks that the local duration is positive across the whole active rectangle. It does not itself model curtain acceleration, segmented or nonlinear electronic timing, shutter shock, EFCS-specific (electronic first-curtain shutter) pupil/bokeh behaviour, or automatically equate exposure boundaries with sensor readout. The separate manual-flash foundation registers a pulse against this timing without redefining the exposure-window contract (#12).

  • Capture rotation trajectories evaluate a stationary reference ray at local exposure start and end under pure, constant camera rotation. The chord between the endpoints is not an integrated blur kernel, and the API is not an inverse destination-to-source rolling-shutter warp. Separate instantaneous inverse mapping and midpoint temporal quadrature provide those geometric pieces. Executed environment capture integrates declared radiance at its supported local shutter nodes.

  • Capture rotation temporal quadrature supplies deterministic midpoint geometry samples across each local exposure. It does not sample scene radiance, output an averaged coordinate or blur radius, model shutter-transmission ramps, or claim a geometry-only error bound. Radiance integration happens later and separately.

  • Instantaneous capture-rotation inverse mapping gives destination-to-reference geometry at an explicit phase within each local exposure window. Pure rotation is inverted analytically, not iteratively. The result is still not a finite-exposure image or a blur model. Reference rays may legitimately fall outside the active source frame and are not clamped.

  • The Airy diagnostic stays a separately named size diagnostic for an ideal circular pupil.

    • calculateIdealPolygonDiffractionPsf() adds a continuous, unit-energy density for ideal on-axis regular-polygon pupils, with explicit equal-area physical scaling. Blade geometry alone does not give a physical PSF.
    • The real-lens framework owns explicitly profiled, combined primary-optics PSFs and complex-pupil/wavefront propagation.
    • Do not stack polygon diffraction on top of a kernel that already includes diffraction.
  • Capture-mode profiles describe acquisition, sampling and reconstruction structure only. Grouped sampling does not imply charge-domain binning unless that is separately evidenced. Processed-image resolution does not change FOV or the physical sensor identity, and does not establish the physical photosite count. Pixel-shift offsets are in units of the native effective sampling pitch and do not claim a photodiode pitch.

  • Colour-sampling topology is independent from NativeImageRaster. Periodic mosaic phase is anchored to absolute native sensor sampling-site indices, not to crop-local coordinates. Channel IDs are labels, not spectral response curves. Layered colour uses a separate unresolved spatial reference and stays structural-only until per-layer sampling density and registration are explicit. Sparse, non-periodic exceptions such as PDAF (phase-detection autofocus), masked or defective sites are not represented by schema 0.1.0.

  • Native-effective-raster / colour-site binding needs its own evidence and is tied to one exact native raster. Matching dimensions alone never prove a 1:1 CFA correspondence. Grouped capture modes also need an evidenced full-frame top-left grouping phase. The bridge reports only compact pre-reconstruction source rectangles and channel-site counts — no sum/average weights, spectral response, downstream reconstructed-pixel dependency or photodiode count. Pixel-shift offsets do not change CFA channel assignment, because the sensor and CFA move together.

  • Sensor optical-stack schema 0.1.0 separates physical component presence from the effective anti-aliasing response. An omitted AA response means unknown. An explicit absent means there is no intentional AA spatial-splitting term in this contract; it does not mean an identity whole-stack PSF or zero aliasing risk. Point-splitting kernels are normalized spatial redistribution only. They exclude throughput, spectral transmission, field/wavelength/polarization dependence, cover-glass refraction and microlens behaviour.

  • Sensor sampling-aperture schema 0.1.0 keeps the physical registration of colour sites separate from both NativeImageRaster and radiometry. Site pitch and origin must be explicitly evidenced; aperture geometry is not inferred from pitch or fill fraction. The first resolved aperture is a uniform, axis-aligned geometric sensitive rectangle inside one lattice cell. Its derived sensitive-area fraction is a geometry diagnostic only — not QE, effective collection area, microlens behaviour, charge diffusion/crosstalk, spectral response or optical throughput.

  • Sensor spatial quadrature inverse-samples the pre-AA optical field through the declared AA split and geometric aperture. The destination CFA channel stays authoritative for all nodes; pre-AA source coordinates never reassign CFA colour. Source support that falls off the imaging area is exposed, not clamped or dropped. Normalized weights stay unchanged, and square-micrometre measures stay geometric — they are not radiometric collection area.

  • Sensor spectral-response schema 0.1.0 treats channel IDs as labels until explicit wavelength-dependent data is supplied.

    • Direct effective EQE, direct A/W responsivity, and explicitly separable filter × detector-QE are different representations.
    • Response curves need reusable-data or Photivra-owned provenance.
    • They never extrapolate outside their wavelength range, and never convert between air and vacuum wavelength coordinates implicitly.
    • They do not model field-angle, temperature or polarization dependence, and do not integrate over wavelength, photons or electrons.
  • Signal/noise primitives need photon or electron quantities supplied by the caller. The radiometry-readiness API can assess declared prerequisites, but it does not derive photons or turn on photon/noise output in the composed POC.

  • The composed POC still uses one representative pixel-pitch path internally, so it rejects sensor geometry whose X/Y sample pitch differs by more than 1%. The lower-level geometry APIs already keep X and Y pitch independent.

  • No named commercial camera or lens performance is claimed.

See Physics Foundation, Motion and Signal Foundation, and Camera Shake and Stabilization for details.

Principles

  • Implement established photography, optics, sensor, motion and imaging mathematics independently.
  • Do not copy code, datasets, calibration tables, model weights or protected technical expression unless the reuse rights are explicit and compatible with Apache-2.0 distribution.
  • Treat publicly viewable material as reference material only. Being public is not permission to copy. Independent implementation does not, by itself, resolve third-party patent rights.
  • Keep calculations deterministic and testable wherever the model itself is deterministic.
  • Prefer explicit units, versioned schemas, consistent public APIs and reproducible results.
  • Label results by provenance: calculated, calibrated, estimated or approximation.
  • Report uncertainty or accuracy metadata only when it can be defended. Never invent an aggregate confidence or error bars.
  • Keep the repository focused on reusable scientific/business logic, validation, schemas, tests, documentation and contributor tooling.

Runtime surfaces

The package is ESM.

  • From 2.0.0, its export map also has a default condition. CommonJS code on Node 22.12 or later can therefore require("@photivra/engine") through Node's require(esm) support.
  • @photivra/engine/package.json is exported.
  • The published JavaScript source maps embed their TypeScript sources.
  • The declarations type-check with lib: ["es2022"] alone. DOM and @types/node are not required; the package declares the one minimal AbortSignal member it uses.

The root export is the runtime-neutral scientific surface:

import {
  calculateFieldOfView,
  simulatePocCamera
} from "@photivra/engine";

CI checks the root dependency graph, so Node-only modules and the repository-local HTTP POC server cannot become reachable from this browser-facing surface.

The open repository still contains a minimal Node HTTP POC server under src/api, for contributor integration testing. It is deliberately not exported by @photivra/engine and is left out of the published npm package. It has no authentication and is not a production hosting recommendation.

From 2.0.0, the published manifest declares no prepare or other install lifecycle scripts. Install the npm package. A Git checkout must be built explicitly with npm ci && npm run build before use.

Development

Development and Node-only tooling support maintained Node.js 22 (minimum 22.13), maintained 24, and 26 Current. Patched Node 24 is preferred for builds.

CI checks the 22.13 minimum, plus the newest maintained LTS lines and the newest Current release (today: patched 22 and 24 LTS, and 26 Current), under the runtime policy.

The reproducible npm workflow uses the committed lockfile:

npm ci
npm run check
npm run coverage
npm run build
npm run pack:check

Coverage gates are currently:

  • 90% lines;
  • 90% statements;
  • 90% functions;
  • 80% branches.

The deterministic fuzz/property tests use fixed seeds, so failures can be reproduced.

You may use Yarn or pnpm for development. Release and CI dependency resolution is defined by package-lock.json and npm ci.

Validation boundaries

TypeScript types are not validation for untrusted data.

  • Use parseCameraConfiguration(), parseSceneDefinition(), parseSensorArchitectureProfile() and parseRadiometryReadinessProfile() at their external JSON/configuration boundaries.
  • The repository-local Node POC HTTP layer has its own structural request parser, which runs before simulatePocCamera().
  • Scientific range and domain validation stays in the calculation modules.
  • Public CalculationResult<T> envelopes reject non-finite numeric output.

Citation

GitHub can generate citation text from CITATION.cff. Use that metadata when citing Photivra in research, technical documentation or reproducible analyses.

Licensing

Source code in this repository is licensed under Apache-2.0 unless a file clearly states otherwise. See LICENSE, NOTICE, and THIRD_PARTY.md.

This product includes DNG technology under license by Adobe.

The Photivra name, logos and branding are owned by Shackelford Creative, LLC. The Apache license does not grant trademark rights to them, except as allowed by applicable law and the license itself.

Trademarks. ColorChecker, RAL and the other product, company and brand names mentioned are trademarks of their respective owners. They are used only to identify the color sets and products compared against or cited; Photivra is not affiliated with or endorsed by them.

Outside contributions are merged only under the project's contributor licence agreement; see Licensing of contributions.