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

@irithell-js/image2braille

v1.0.0

Published

Convert images to Braille Unicode art with customizable themes, colors, and multiple output formats (console, TXT, HTML, PNG).

Downloads

38

Readme

image2braille

High-performance image to Braille Unicode art converter with Floyd-Steinberg dithering, 20+ built-in themes, and multiple output formats (console, TXT, HTML, PNG).

Features

  • Multiple Output Formats - Console, TXT, HTML (interactive), PNG
  • 20+ Built-in Themes - Dracula, Nord, Monokai, Solarized, Terminal styles
  • Floyd-Steinberg Dithering - Smooth gradients with error diffusion algorithm
  • Flexible Color System - Use hex codes, RGB values, or color names
  • Quality Presets - Fast, balanced, or best quality processing
  • Smart Resizing - Lanczos3, Mitchell, Cubic kernels with aspect ratio preservation
  • TypeScript - Full type definitions included
  • Dual Format - ESM and CommonJS support
  • Zero Dependencies - Only Sharp for image processing

Installation

npm i @irithell-js/image2braille

Quick Start

Basic Usage (ESM)

import { Image2Braille } from "image2braille";

const converter = new Image2Braille();

// Convert and display in console
await converter.convertAndShow("photo.jpg", { width: 80 });

// Convert and save as PNG
await converter.convertAndSave(
  "photo.jpg",
  "output.png",
  { width: 100 },
  { format: "image", theme: "dracula" },
);

// Get art as string
const art = await converter.convertToString("photo.jpg", { width: 60 });
console.log(art);

Basic Usage (CommonJS)

const { Image2Braille } = require("image2braille");

async function convert() {
  const converter = new Image2Braille();
  await converter.convertAndShow("image.png", { width: 80 });
}

convert();

Using Themes

// Use built-in theme
const converter = new Image2Braille({
  theme: "nord",
  dithering: true,
  quality: "best",
});

// List all available themes
Image2Braille.listThemes();
// Output:
// Available themes:
//   dark                 - Classic black and white
//     bg: #000000  fg: #ffffff
//   terminal             - Matrix-style green phosphor
//     bg: #000000  fg: #00ff00
//   ...

// Get theme names programmatically
const themes = Image2Braille.getThemeNames();
// ['dark', 'light', 'terminal', 'dracula', 'nord', ...]

Configuration

Constructor Options

const converter = new Image2Braille({
  // Conversion settings
  defaultWidth: 80, // Default output width in characters
  defaultHeight: undefined, // Default height (auto if undefined)
  preserveAspectRatio: true, // Maintain image proportions
  threshold: 128, // Black/white threshold (0-255)
  dithering: true, // Enable Floyd-Steinberg dithering
  invert: false, // Invert colors (negative)

  // Output settings
  outputFormat: "console", // Default format: console|txt|html|image
  outputDir: "./output", // Output directory

  // Style settings
  theme: "dark", // Theme name (overrides colors)
  fontSize: 10, // Font size for HTML/PNG output
  fontFamily: "Cascadia Code, Courier New, monospace",
  backgroundColor: "#000000", // Background color (hex, rgb, or name)
  textColor: "#ffffff", // Text color (hex, rgb, or name)
  lineHeight: 1.0, // Line spacing
  padding: 20, // Padding for HTML/PNG

  // Quality settings
  resizeKernel: "lanczos3", // Resize algorithm
  quality: "balanced", // Processing speed: fast|balanced|best

  // Logging
  logger: console, // Optional logger instance
});

Quality Presets

// Ultra-fast (nearest neighbor, no dithering)
const fast = new Image2Braille({
  quality: "fast",
  resizeKernel: "nearest",
  dithering: false,
});

// Balanced (recommended)
const balanced = new Image2Braille({
  quality: "balanced",
  resizeKernel: "lanczos3",
  dithering: true,
});

// Best quality (slowest, highest detail)
const best = new Image2Braille({
  quality: "best",
  resizeKernel: "lanczos3",
  dithering: true,
});

Color Configuration

// Using hex colors
const hex = new Image2Braille({
  backgroundColor: "#282a36",
  textColor: "#f8f8f2",
});

// Using RGB
const rgb = new Image2Braille({
  backgroundColor: "rgb(40, 42, 54)",
  textColor: "rgb(248, 248, 242)",
});

// Using color names
const named = new Image2Braille({
  backgroundColor: "black",
  textColor: "green",
});

// Supported color names:
// black, white, red, green, blue, yellow, cyan, magenta, orange,
// purple, pink, lime, teal, navy, maroon, olive, gray, darkgray,
// lightgray, silver, darkred, darkgreen, darkblue, lightred,
// lightgreen, lightblue, transparent

API Reference

Image2Braille Methods

convert(input: string | Buffer, options?: ConversionOptions): Promise<ConversionResult>

Convert an image to Braille art.

const result = await converter.convert("photo.jpg", {
  width: 100, // Width in characters
  height: 50, // Height in characters (optional)
  threshold: 128, // Black/white threshold (0-255)
  dithering: true, // Enable dithering
  invert: false, // Invert colors
  aspectRatio: true, // Preserve aspect ratio
});

console.log(result.art); // Braille art string
console.log(result.width); // 100 characters
console.log(result.height); // 50 characters
console.log(result.originalWidth); // 1920 pixels
console.log(result.originalHeight); // 1080 pixels
console.log(result.processingTime); // 234 ms

convertAndSave(input, outputPath?, conversionOptions?, saveOptions?): Promise<ConversionResult>

Convert and save to file.

// Save as PNG with theme
await converter.convertAndSave(
  "input.jpg",
  "output.png",
  { width: 80 },
  {
    format: "image",
    theme: "dracula",
    fontSize: 12,
  },
);

// Save as HTML with custom colors
await converter.convertAndSave(
  "input.jpg",
  "output.html",
  { width: 100, dithering: true },
  {
    format: "html",
    backgroundColor: "navy",
    textColor: "cyan",
  },
);

// Save as TXT
await converter.convertAndSave(
  "input.jpg",
  "output.txt",
  { width: 60 },
  { format: "txt" },
);

// Display in console
await converter.convertAndSave(
  "input.jpg",
  undefined,
  { width: 80 },
  { format: "console", showInfo: true },
);

convertToString(input, options?): Promise<string>

Convert and return art as string.

const art = await converter.convertToString("photo.jpg", { width: 60 });
console.log(art);

convertAndShow(input, options?): Promise<ConversionResult>

Convert and display in console with metadata.

await converter.convertAndShow("photo.jpg", { width: 80 });
// Output:
// Original: 1920x1080px
// Braille: 80x33 characters
// Represented pixels: 160x132px
//
// ⣿⣿⣿⣿⣿⣿...

updateConfig(newConfig: Partial<Image2BrailleConfig>): void

Update configuration at runtime.

converter.updateConfig({
  theme: "terminal",
  dithering: false,
  threshold: 150,
});

getConfig(): Image2BrailleConfig

Get current configuration.

const config = converter.getConfig();
console.log(config.theme);
console.log(config.threshold);

static listThemes(): void

List all available themes.

Image2Braille.listThemes();

static getThemeNames(): string[]

Get array of theme names.

const themes = Image2Braille.getThemeNames();
// ['dark', 'light', 'terminal', ...]

Available Themes

| Theme | Description | Background | Foreground | | ----------------- | ---------------------------- | ---------- | ---------- | | dark | Classic black and white | #000000 | #ffffff | | light | White background, black text | #ffffff | #000000 | | terminal | Matrix-style green phosphor | #000000 | #00ff00 | | amber | Retro DOS amber | #1a0f00 | #ffb000 | | green | Classic green terminal | #0a1a0a | #00ff41 | | dracula | Dracula theme | #282a36 | #f8f8f2 | | monokai | Monokai theme | #272822 | #f8f8f2 | | solarized-dark | Solarized dark | #002b36 | #839496 | | solarized-light | Solarized light | #fdf6e3 | #657b83 | | nord | Nord theme | #2e3440 | #d8dee9 | | one-dark | Atom One Dark | #282c34 | #abb2bf | | gruvbox-dark | Gruvbox dark | #282828 | #ebdbb2 | | gruvbox-light | Gruvbox light | #fbf1c7 | #3c3836 | | blue | Cyberpunk blue | #001122 | #00aaff | | purple | Neon purple | #0d001a | #bf40ff | | red | Alert red | #1a0000 | #ff4444 | | cyan | Bright cyan | #001a1a | #00ffff | | paper | Aged paper | #f5f5dc | #2c2c2c | | hacker | Hacker terminal | #0c0c0c | #0f0 |

Advanced Usage

Batch Processing with Multiple Themes

const converter = new Image2Braille({
  outputDir: "./output",
});

const themes = ["dark", "terminal", "dracula", "nord"];

for (const theme of themes) {
  converter.updateConfig({ theme });
  await converter.convertAndSave(
    "photo.jpg",
    `./output/${theme}.png`,
    { width: 80 },
    { format: "image" },
  );
}

Custom Pipeline

import { Image2Braille } from "image2braille";
import { readFileSync } from "fs";

// Load image as buffer
const buffer = readFileSync("photo.jpg");

// Convert with custom settings
const converter = new Image2Braille({
  dithering: false,
  threshold: 150,
});

const result = await converter.convert(buffer, {
  width: 100,
  invert: true,
});

// Process the art string
const lines = result.art.split("\n");
console.log(`Generated ${lines.length} lines`);

Error Handling

try {
  const result = await converter.convert("invalid.jpg");
} catch (error) {
  if (error.message.includes("missing dimensions")) {
    console.error("Invalid image file");
  } else {
    console.error("Conversion failed:", error.message);
  }
}

Performance Monitoring

const start = Date.now();
const result = await converter.convert("large-photo.jpg", { width: 200 });
console.log(`Processing took ${result.processingTime}ms`);
console.log(`Total time: ${Date.now() - start}ms`);

Output Formats

Console

Displays art directly in terminal with metadata.

TXT

Plain text file with Braille characters (UTF-8 encoded).

HTML

Interactive HTML with:

  • All themes as clickable buttons
  • Copy to clipboard
  • Download as TXT
  • Smooth theme transitions
  • Responsive design

PNG

Rendered image with:

  • Anti-aliased text
  • Custom fonts
  • Configurable size and padding
  • High-quality SVG-to-PNG conversion

Performance

Conversion speed depends on image size, quality settings, and dithering:

| Image Size | Width | Quality | Dithering | Time | | ---------- | ----- | -------- | --------- | ------ | | 1920x1080 | 80 | fast | off | ~50ms | | 1920x1080 | 80 | balanced | on | ~90ms | | 1920x1080 | 150 | best | on | ~175ms | | 3840x2160 | 80 | balanced | on | ~140ms | | 3840x2160 | 200 | best | on | ~400ms |

Times measured on local tests

How It Works

  1. Load Image - Uses Sharp to read image file or buffer
  2. Calculate Dimensions - Determines target size preserving aspect ratio
  3. Resize - Resizes to exact pixel dimensions (width×2, height×4)
  4. Convert to Grayscale - Calculates luminance using ITU-R BT.709 formula
  5. Apply Dithering - Floyd-Steinberg error diffusion (optional)
  6. Map to Braille - Converts 2×4 pixel blocks to Braille Unicode (U+2800-U+28FF)
  7. Output - Renders to selected format

Braille Unicode

Each Braille character represents a 2×4 pixel block:

⠁ = pixel at (0,0)
⠂ = pixel at (0,1)
⠄ = pixel at (0,2)
⡀ = pixel at (0,3)
⠈ = pixel at (1,0)
⠐ = pixel at (1,1)
⠠ = pixel at (1,2)
⢀ = pixel at (1,3)

Example: = all 8 pixels filled (U+28FF)

Requirements

  • Node.js >= 18.0.0
  • Sharp (automatically installed)

License

MIT

Changelog

1.0.0 (Latest)

  • Initial release
  • Floyd-Steinberg dithering support
  • 20+ built-in themes
  • Multiple output formats (console, TXT, HTML, PNG)
  • Color name resolution (hex, rgb, names)
  • Quality presets (fast, balanced, best)
  • Multiple resize kernels (nearest, cubic, mitchell, lanczos2, lanczos3)
  • Aspect ratio preservation
  • TypeScript support with full type definitions
  • ESM and CommonJS support