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

@takalawang/jpeg-decoder

v1.1.5

Published

A complete JPEG decoder implementation in TypeScript

Readme

@takalawang/jpeg-decoder

A complete JPEG decoder implementation in TypeScript with support for both baseline and progressive JPEG formats. Convert JPEG images to PNG, BMP, PPM, or raw RGBA data.

Installation

Local Installation

npm install @takalawang/jpeg-decoder

Or with pnpm:

pnpm add @takalawang/jpeg-decoder

Global Installation

For command-line usage, you can install globally:

npm install -g @takalawang/jpeg-decoder

Or with pnpm:

pnpm add -g @takalawang/jpeg-decoder

This will make the jpeg-decode command available system-wide.

Usage

Programmatic API

import { JPEGDecoder } from '@takalawang/jpeg-decoder';
import { readFileSync } from 'fs';

// Read JPEG file
const data = readFileSync('image.jpg');

// Create decoder instance
const decoder = new JPEGDecoder(new Uint8Array(data));

// Decode image
const result = decoder.decode();

console.log(`Width: ${result.width}`);
console.log(`Height: ${result.height}`);
console.log(`Data: RGBA format, ${result.data.length} bytes`);

// Access pixel data (RGBA format)
const pixel = {
  r: result.data[0],
  g: result.data[1],
  b: result.data[2],
  a: result.data[3],
};

Simple API

import { decodeJPEG, decodeAndConvert } from '@takalawang/jpeg-decoder';
import { readFileSync, writeFileSync } from 'fs';

// Decode to raw RGBA
const data = readFileSync('image.jpg');
const decoded = decodeJPEG(new Uint8Array(data));

// Decode and convert to PNG
const pngData = await decodeAndConvert(new Uint8Array(data), 'png');
writeFileSync('output.png', pngData);

// Decode and convert to BMP
const bmpData = await decodeAndConvert(new Uint8Array(data), 'bmp');
writeFileSync('output.bmp', bmpData);

// Decode and convert to PPM
const ppmData = await decodeAndConvert(new Uint8Array(data), 'ppm');
writeFileSync('output.ppm', ppmData);

CLI Usage

After installation, you can use the jpeg-decode command:

# Decode JPEG and save as PNG (auto-detected from .png extension)
jpeg-decode decode input.jpg -o output.png

# Decode JPEG and save as BMP (auto-detected from .bmp extension)
jpeg-decode decode input.jpg -o output.bmp

# Convert to specific format (overrides auto-detection)
jpeg-decode decode input.jpg -o output.raw --format raw
jpeg-decode decode input.jpg -o output.ppm --format ppm

# Display image information only
jpeg-decode decode input.jpg -i

# Get detailed info about JPEG
jpeg-decode info input.jpg

# Works with both baseline and progressive JPEGs
jpeg-decode decode progressive.jpg -o output.png

API Reference

JPEGDecoder

Main decoder class for JPEG images.

Constructor

new JPEGDecoder(data: Uint8Array)
  • data: JPEG file data as Uint8Array

Methods

decode(): DecodedImage

Decodes the JPEG image and returns the decoded data.

Returns:

interface DecodedImage {
  width: number; // Image width in pixels
  height: number; // Image height in pixels
  data: Uint8Array; // RGBA pixel data (4 bytes per pixel)
}

decodeJPEG()

Convenience function for quick decoding.

function decodeJPEG(data: Uint8Array): DecodedImage;

decodeAndConvert()

Decode JPEG and convert to specific format.

async function decodeAndConvert(
  jpegData: Uint8Array,
  format: 'png' | 'bmp' | 'ppm' | 'raw'
): Promise<Buffer>;

getEncoder()

Get encoder for specific format.

import { getEncoder } from '@takalawang/jpeg-decoder';

const encoder = getEncoder('png');
const pngBuffer = await encoder.encode(rgbaData, width, height);

Output Formats

  • PNG: Portable Network Graphics with zlib compression
  • BMP: Windows Bitmap (32-bit RGBA)
  • PPM: Portable Pixmap (P6 binary format, RGB only)
  • RAW: Uncompressed RGBA data

Supported JPEG Features

✅ Supported

  • Baseline DCT (SOF0) - Sequential JPEG
  • Extended sequential DCT (SOF1) - Extended sequential JPEG
  • Progressive DCT (SOF2) - Progressive JPEG with spectral selection and successive approximation
  • Huffman coding - Standard entropy coding
  • YCbCr color space - Standard JPEG color space
  • CMYK color space - Adobe CMYK format (4-component)
  • YCCK color space - YCbCr with K channel (Adobe format)
  • Grayscale images - Single component images
  • Multiple quantization tables - Up to 4 quantization tables
  • Multiple Huffman tables - Separate DC/AC tables per component
  • Chroma subsampling - 4:4:4, 4:2:2, 4:2:0 formats

❌ Not Supported

  • Lossless JPEG (SOF3) - Predictive lossless encoding
  • Hierarchical JPEG (SOF5-SOF7) - Multi-resolution pyramid encoding
  • Arithmetic coding - Alternative entropy coding (rarely used due to patents)

How It Works

Progressive JPEG Decoding

Progressive JPEGs decode in multiple scans, gradually refining image quality:

  1. Spectral Selection: DC coefficients first, then AC coefficients in bands
  2. Successive Approximation: High-order bits first, then refinement bits
  3. Coefficient Accumulation: Multiple scans build up the final DCT coefficients

Output Format

The decoder outputs raw pixel data in RGBA format:

  • 4 bytes per pixel (Red, Green, Blue, Alpha)
  • Alpha channel is always 255 (fully opaque)
  • Row-major order (left to right, top to bottom)

Technical Details

Decoding Pipeline

Baseline JPEG (SOF0)

  1. Marker Parsing: Identifies and processes JPEG markers (SOI, SOF, DHT, DQT, SOS, etc.)
  2. Huffman Decoding: Decodes compressed coefficients using Huffman tables
  3. Dequantization: Applies quantization tables to coefficients
  4. IDCT: Inverse Discrete Cosine Transform using efficient AAN algorithm
  5. Color Conversion: YCbCr to RGB conversion with inline optimization
  6. Rendering: Direct component-to-image rendering (no intermediate upsampling buffers)

Progressive JPEG (SOF2)

  1. Parse Progressive Scans: Reads multiple SOS markers with scan parameters
  2. Spectral Selection: Processes DC (0) or AC (1-63) coefficient ranges
  3. Successive Approximation: Accumulates bits across refinement scans
  4. Coefficient Assembly: Builds complete DCT blocks from multiple passes (including efficient EOB run handling)
  5. IDCT & Color Space: Same as baseline after coefficient reconstruction

Color Space Conversion

The decoder automatically detects and handles multiple color spaces:

  • YCbCr → RGB: Standard JPEG color space using ITU-R BT.601 conversion
  • CMYK → RGB: Adobe CMYK format (inverted values) with proper K channel handling
  • YCCK → RGB: YCbCr with separate K channel, converted via CMY intermediate
  • Grayscale: Single component copied to R, G, B channels

Color space detection uses the Adobe APP14 marker when present, or infers from component count.

Image Format Encoders

  • PNG: Creates IHDR, IDAT (zlib-compressed), IEND chunks with CRC32 validation
  • BMP: Windows DIB format with bottom-up row ordering and BITMAPINFOHEADER
  • PPM: Simple NetPBM binary format (P6 magic number)
  • RAW: Direct RGBA buffer output

Performance

The decoder is optimized for speed and memory efficiency:

  • AAN Algorithm: Uses the Arai, Agui, and Nakajima algorithm for IDCT, reducing multiplications per block from ~1024 (naive) to < 100.
  • Memory Optimization: Eliminates intermediate upsampling buffers, reducing memory usage during rendering.
  • Inline Scaling: Calculates pixel coordinates on-the-fly for faster processing.

Decode time for 512×512 images: ~30-50ms on modern hardware.

Development

Setup

# Install dependencies
pnpm install

# Build project
pnpm build

# Run tests
pnpm test

# Run tests with coverage
pnpm test:coverage

# Lint code
pnpm lint

# Format code
pnpm format

Project Structure

src/
├── index.ts          # Main exports
├── cli.ts            # CLI interface
├── decoder.ts        # Main decoder class
├── types.ts          # TypeScript interfaces
├── bit-reader.ts     # Bit-level reading utilities
├── huffman.ts        # Huffman decoding
├── aan.ts            # IDCT implementation (AAN algorithm)
├── encoders.ts       # Image format encoders
└── __tests__/        # Test files

Testing

The project includes comprehensive tests using Vitest:

# Run all tests
pnpm test

# Run tests with coverage
pnpm test:coverage

# Test with specific file
jpeg-decode decode lena.jpg -i

License

MIT License - see LICENSE file for details.