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

@huh-david/bmp-js

v0.8.2

Published

A pure TypeScript BMP encoder and decoder for Node.js

Downloads

1,401

Readme

@huh-david/bmp-js

npm version Documentation

A pure TypeScript BMP encoder/decoder for Node.js.

Maintenance

This fork is actively maintained and tracks unresolved upstream shaozilee/bmp-js issues and PRs.

  • Repository: https://github.com/Huh-David/bmp-js
  • Releases: https://github.com/Huh-David/bmp-js/releases
  • Documentation: https://huh-david.github.io/bmp-js/

Features

  • Decoding for BMP bit depths: 1, 4, 8, 15, 16, 24, 32
  • Decoding support for RLE-4 and RLE-8 compressed BMPs
  • Robust DIB handling for CORE/INFO/V4/V5 headers
  • Encoding output bit depths: 1, 4, 8, 16, 24, 32
  • Dual package output: ESM + CommonJS
  • First-class TypeScript types

Install

pnpm add @huh-david/bmp-js

Migration

Migrating from legacy bmp-js/bmp-ts is straightforward:

pnpm remove bmp-js bmp-ts
pnpm add @huh-david/bmp-js

Usage

ESM

import { decode, encode } from "@huh-david/bmp-js";
import { readFileSync, writeFileSync } from "node:fs";

const input = readFileSync("./image.bmp");
const decoded = decode(input);

const encoded = encode({
  data: decoded.data,
  width: decoded.width,
  height: decoded.height,
});

writeFileSync("./roundtrip.bmp", encoded.data);

Encode options

import { encode } from "@huh-david/bmp-js";

const encoded = encode(
  {
    data: rgbaLikeBytes,
    width: 320,
    height: 200,
  },
  {
    orientation: "bottom-up", // default: "top-down"
    bitPP: 32, // supported: 1, 4, 8, 16, 24, 32
    // palette is required for 4/8-bit and optional for 1-bit
    // palette: [{ red: 0, green: 0, blue: 0, quad: 0 }, ...],
  },
);

CommonJS

const bmp = require("@huh-david/bmp-js");
const fs = require("node:fs");

const decoded = bmp.decode(fs.readFileSync("./image.bmp"));
const encoded = bmp.encode(decoded);

fs.writeFileSync("./roundtrip.bmp", encoded.data);

Decode options

import { decode } from "@huh-david/bmp-js";

const decoded = decode(inputBytes, {
  toRGBA: true, // return RGBA instead of default ABGR
});

Output format helpers (non-breaking)

import { decodeRgb, decodeRgba } from "@huh-david/bmp-js";

const rgba = decodeRgba(inputBytes); // DecodedBmp with RGBA data
const rgb = decodeRgb(inputBytes); // { data, width, height, channels: 3, format: "rgb" }

Data layout

Decoded pixel data is a byte buffer in ABGR order by default. If toRGBA: true is provided to decode, output is returned in RGBA. decodeRgba and decodeRgb are explicit opt-in helpers for RGBA/RGB consumers.

  • A: alpha
  • B: blue
  • G: green
  • R: red

Input/output binary types use Uint8Array (Node Buffer is fully compatible because it extends Uint8Array).

Sharp adapter (optional subexport)

The package ships an optional Sharp adapter at @huh-david/bmp-js/sharp. Core usage does not require sharp.

Install Sharp only when using the adapter:

pnpm add sharp

BMP -> Sharp -> PNG

import sharp from "sharp";
import { sharpFromBmp } from "@huh-david/bmp-js/sharp";

const png = await sharpFromBmp(bmpBytes, sharp).resize(800).png().toBuffer();

Sharp raw -> BMP

import sharp from "sharp";
import { encodeFromSharp } from "@huh-david/bmp-js/sharp";

const { data, info } = await sharp(input).ensureAlpha().raw().toBuffer({ resolveWithObject: true });

const bmp = encodeFromSharp({ data, info }, { bitDepth: 32 });

Adapter behavior:

  • decodeForSharp and sharpFromBmp require BMP input and throw on non-BMP bytes.
  • Sharp-bound decode output is normalized to RGBA + { raw: { width, height, channels: 4 } }.
  • encodeFromSharp supports channels 3 and 4 only; other values throw.
  • Default encode depth is data-preserving: RGB -> 24-bit, RGBA -> 32-bit.
  • Inputs are Uint8Array-first and accept Buffer/ArrayBuffer/typed-array views.
  • sharpFromBmp supports both forms:
    • sharpFromBmp(input, sharp?)
    • sharpFromBmp({ input, sharp })
  • encodeFromSharp supports:
    • encodeFromSharp({ data, info }, options?)
    • encodeFromSharp({ data, width, height, channels }, options?)
    • encodeFromSharp(data, info, options?)
  • toSharpInput is kept as a compatibility alias for decodeForSharp.

Development

pnpm install
pnpm fixtures:generate
pnpm check

Useful scripts:

  • pnpm build
  • pnpm test
  • pnpm test:browser
  • pnpm test:watch
  • pnpm lint
  • pnpm format
  • pnpm typecheck

License

MIT