UTIF.js

A dependency-light JavaScript TIFF decoder that also reads RAW camera formats like DNG, CR2, NEF, and ARW.

Library
npm
v3.1.0
498stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
40/100Fair
Development Activity12
Maintenance0
Community68
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
44/100Fair
Architecture55
Code Quality30
Innovation55
Learning Curve35

UTIF.js is a small, pure-JavaScript TIFF and EXIF decoder that also handles camera RAW formats such as DNG, CR2, NEF, and ARW. It began as the core TIFF-reading engine inside the Photopea online image editor, where it needed to parse whatever oddball TIFF variant a user dragged in without relying on native codecs or a server round-trip.

The library ships with a single dependency (pako, for DEFLATE-compressed strips) and supports an unusually wide range of TIFF compression schemes — Fax Group 3/4 (CCITT), old and new JPEG-in-TIFF, LZW, PackBits, Thunderscan, and several RAW-specific codecs (ARW, Panasonic, LogLuv32, VC5) — plus a convenience UTIF.replaceIMG() helper that swaps <img src="foo.tif"> tags for a rendered PNG data URI with no extra wiring.

What You Get

  • A dependency-light TIFF/EXIF decoder (UTIF.decode) that reads image file directory tags without decompressing pixel data.
  • Full pixel decompression via UTIF.decodeImage() across a wide set of TIFF compression schemes.
  • An UTIF.toRGBA8() conversion step that turns decoded TIFF data into browser-ready 8-bit RGBA pixels.
  • A one-line UTIF.replaceIMG() helper for displaying TIFF/RAW images directly in <img> tags.
  • A basic uncompressed TIFF encoder (UTIF.encodeImage/UTIF.encode) for writing IFD metadata back out.

Common Use Cases

  • Rendering user-uploaded TIFF or camera RAW files (DNG, CR2, NEF) in a browser-based image editor without a server round trip.
  • Extracting EXIF/IFD metadata (dimensions, camera tags) from TIFF files client-side.
  • Displaying legacy TIFF scans or faxes (CCITT Group 3/4 compressed) directly in web pages via replaceIMG().
  • Converting decoded TIFF pixel data to RGBA for canvas-based image processing pipelines.

Under The Hood

Architecture The entire library is a single IIFE (UTIF.js) that attaches everything to one flat UTIF namespace, with a typeof module check to support both CommonJS require() and a plain browser global. Internally it’s organized as dozens of self-contained decoder/encoder functions keyed off the TIFF compression tag (t259) — _decodeG3, _decodeG4, _decodeLZW, _decodeOldJPEG, _decodeNewJPEG, _decodeVC5, _decodeARW, _decodePanasonic, _decodeLogLuv32, _decodeNikon, and more — plus a separately vendored embedded JPEG decoder exposed as UTIF.JpegDecoder. There are no classes or DI; every function communicates through passed-in typed arrays and a shared IFD object keyed by TIFF tag number strings ("t256", "t273", etc.), so any change to that flat tag-dictionary shape would ripple through every decode/encode path at once.

Tech Stack Pure vanilla JavaScript with no TypeScript, no bundler, and no build step — package.json’s main field points directly at the raw source file. The only runtime dependency is pako (^1.0.5), used solely for DEFLATE compression when encoding TIFF strips. It ships as an npm package (utif) but is equally consumable via a plain <script> tag, reflecting its original use as a vendored decoder inside the Photopea editor rather than a modern tooled library.

Code Quality No test directory, test framework, or CI configuration exists in the repository. Error handling is largely implicit — most decoders assume well-formed TIFF input and will throw generic JavaScript errors (e.g. out-of-bounds array access) on malformed files, though the embedded JPEG decoder is a notable exception with dedicated JpegError, DNLMarkerError, and EOIMarkerError types. Naming throughout the core decoders favors terse, often single/double-letter identifiers even in the checked-in source, and there is no TypeScript or JSDoc type coverage. In short: no tests found, minimal error typing outside the JPEG path.

API Design The public surface is intentionally tiny: UTIF.decode(), UTIF.decodeImage(), and UTIF.toRGBA8() take a caller from a raw TIFF ArrayBuffer to RGBA pixels in three calls, and UTIF.replaceIMG() collapses that into a single zero-config call for HTML <img> tags — genuinely low boilerplate for the common case. That said, documentation stops at those four entry points in the README; the large internal surface of codec-specific _decode* functions is entirely undocumented, and there are no TypeScript type definitions, JSDoc annotations, or a changelog to guide consumers past the happy path.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search