Skip to content

neplextech/bgone

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bgone

Node.js library to remove solid background colors from images without AI/ML based on bgone by Benface.

Features

  • Automatic background detection - Detects solid background colors by sampling image edges
  • Color unmixing - Separates foreground from background using advanced alpha blending algorithms
  • Foreground color deduction - Automatically deduce unknown foreground colors using "auto"
  • Strict and non-strict modes - Choose between exact color matching or flexible unmixing
  • Parallel processing - Utilizes all CPU cores for maximum performance
  • Cross-platform - Works on Windows, macOS, Linux, and more

Example Result

Input Output
Input Output

Example image from Unsplash

Installation

npm install @neplex/bgone
# or
yarn add @neplex/bgone
# or
pnpm add @neplex/bgone
# or
bun add @neplex/bgone
# or
deno add npm:@neplex/bgone

Quick Start

import { readFileSync, writeFileSync } from 'fs';
import { processImage, processImageSync, detectBackgroundColor } from '@neplex/bgone';

const input = readFileSync('input.png');

// Async processing (recommended for large images)
const output = await processImage({
  input,
  strictMode: false,
  trim: false,
});
writeFileSync('output.png', output);

// Sync processing
const outputSync = processImageSync({
  input,
  strictMode: false,
  trim: false,
});

CLI Usage

You can use bgone directly from the command line:

# Using npx (no installation required)
npx @neplex/bgone input.png

CLI Options

Usage: npx @neplex/bgone [options] <input> [output]

Remove solid background colors from images

Arguments:
  input                  Input image file
  output                 Output image file (defaults to input-bgone.png)

Options:
  -V, --version          output the version number
  -b, --bg <color>       Background color to remove (hex, e.g. #ffffff or fff)
  -f, --fg <colors...>   Foreground colors (hex or "auto" for deduction)
  -s, --strict           Strict mode - only use specified foreground colors
  -t, --threshold <value> Color closeness threshold (0.0-1.0)
  --trim                 Trim output to content bounding box
  --detect               Only detect and print background color, do not process
  -h, --help             display help for command

CLI Examples

# Fully automatic - detects background and removes it
npx @neplex/bgone input.png

# Specify output path
npx @neplex/bgone input.png output.png

# With explicit background color
npx @neplex/bgone input.png --bg=#ffffff
npx @neplex/bgone input.png -b fff

# With foreground color for optimized opacity
npx @neplex/bgone input.png --fg=#ff0000

# Multiple foreground colors
npx @neplex/bgone input.png --fg ff0000 00ff00 0000ff

# Foreground color deduction
npx @neplex/bgone input.png --fg auto
npx @neplex/bgone input.png --fg auto auto --bg ffffff

# Mix known and unknown colors
npx @neplex/bgone input.png --fg ff0000 auto

# Strict mode with foreground colors
npx @neplex/bgone input.png --strict --fg=#ff0000
npx @neplex/bgone input.png -s --fg auto

# With threshold and trim
npx @neplex/bgone input.png -f f00 0f0 00f -b fff -t 0.1 --trim

# Only detect background color
npx @neplex/bgone input.png --detect

API Reference

Types

interface RgbColor {
  r: number; // 0-255
  g: number; // 0-255
  b: number; // 0-255
}

interface RgbaColor {
  r: number; // 0-255
  g: number; // 0-255
  b: number; // 0-255
  a: number; // 0-255
}

interface NormalizedRgbColor {
  r: number; // 0.0-1.0
  g: number; // 0.0-1.0
  b: number; // 0.0-1.0
}

interface ProcessImageOptions {
  /** The input image buffer (PNG, JPEG, etc.) */
  input: Buffer;
  /** Foreground colors as hex strings. Use "auto" to deduce unknown colors. */
  foregroundColors?: string[];
  /** Background color as hex string. Auto-detected if not specified. */
  backgroundColor?: string;
  /** Restricts unmixing to only the specified foreground colors. */
  strictMode: boolean;
  /** Threshold for color closeness (0.0-1.0, default: 0.05) */
  threshold?: number;
  /** Trim output to bounding box of non-transparent pixels. */
  trim: boolean;
}

interface UnmixResult {
  /** Weight for each foreground color */
  weights: number[];
  /** Overall alpha value (0.0-1.0) */
  alpha: number;
}

Image Processing

processImage(options: ProcessImageOptions): Promise<Buffer>

Process an image asynchronously to remove its background. Returns a Promise that resolves to the processed image buffer (PNG format).

// Fully automatic - detects background and removes it
const output = await processImage({
  input: imageBuffer,
  strictMode: false,
  trim: false,
});

// With explicit background color
const output = await processImage({
  input: imageBuffer,
  backgroundColor: '#ffffff',
  strictMode: false,
  trim: true,
});

// With foreground colors for optimized opacity
const output = await processImage({
  input: imageBuffer,
  foregroundColors: ['#ff0000', '#00ff00'],
  backgroundColor: '#ffffff',
  strictMode: false,
  trim: false,
});

// Foreground color deduction using "auto"
const output = await processImage({
  input: imageBuffer,
  foregroundColors: ['auto'],
  backgroundColor: '#ffffff',
  strictMode: false,
  trim: false,
});

// Mix known and unknown colors
const output = await processImage({
  input: imageBuffer,
  foregroundColors: ['#ff0000', 'auto'],
  strictMode: true,
  trim: false,
});

// Strict mode - restricts to exact foreground colors
const output = await processImage({
  input: imageBuffer,
  foregroundColors: ['#ff0000'],
  backgroundColor: '#ffffff',
  strictMode: true,
  trim: false,
});

processImageSync(options: ProcessImageOptions): Buffer

Synchronous version of processImage. Use for smaller images or when async is not needed.

const output = processImageSync({
  input: imageBuffer,
  strictMode: false,
  trim: false,
});

Background Detection

detectBackgroundColor(input: Buffer): RgbColor

Detect the background color of an image by sampling its edges and corners.

const bgColor = detectBackgroundColor(imageBuffer);
console.log(`Background: rgb(${bgColor.r}, ${bgColor.g}, ${bgColor.b})`);

Image Utilities

trimImage(input: Buffer): Buffer

Trim an image to the bounding box of non-transparent pixels.

const trimmed = trimImage(imageBuffer);

Color Utilities

parseColor(hex: string): RgbColor

Parse a hex color string into an RGB color. Supports formats: "#ff0000", "ff0000", "#f00", "f00".

const red = parseColor('#ff0000');
// { r: 255, g: 0, b: 0 }

const green = parseColor('0f0');
// { r: 0, g: 255, b: 0 }

colorToNormalized(color: RgbColor): NormalizedRgbColor

Convert an RGB color (0-255) to a normalized RGB color (0.0-1.0).

const normalized = colorToNormalized({ r: 255, g: 128, b: 0 });
// { r: 1.0, g: 0.502, b: 0.0 }

normalizedToColor(color: NormalizedRgbColor): RgbColor

Convert a normalized RGB color (0.0-1.0) to an RGB color (0-255).

const rgb = normalizedToColor({ r: 1.0, g: 0.5, b: 0.0 });
// { r: 255, g: 128, b: 0 }

Color Unmixing

unmixColor(observed: RgbColor, foregroundColors: RgbColor[], background: RgbColor): UnmixResult

Unmix an observed color into foreground color components. Given an observed color and known foreground/background colors, determines how much of each foreground color contributed to the observed color.

const result = unmixColor(
  { r: 128, g: 0, b: 0 }, // observed color
  [{ r: 255, g: 0, b: 0 }], // foreground colors
  { r: 0, g: 0, b: 0 }, // background
);
console.log(result.weights); // [0.502...]
console.log(result.alpha); // 0.502...

computeUnmixResultColor(weights: number[], alpha: number, foregroundColors: RgbColor[]): RgbaColor

Compute the final RGBA color from an unmix result.

const rgba = computeUnmixResultColor([0.5, 0.5], 1.0, [
  { r: 255, g: 0, b: 0 },
  { r: 0, g: 255, b: 0 },
]);
// { r: 128, g: 128, b: 0, a: 255 }

compositeOverBackground(pixel: RgbaColor, background: RgbColor): RgbColor

Composite an RGBA pixel over an RGB background color. If the pixel is translucent (alpha < 255), pre-composes it over the background to produce an opaque equivalent.

const result = compositeOverBackground({ r: 255, g: 0, b: 0, a: 128 }, { r: 0, g: 0, b: 0 });
// { r: 128, g: 0, b: 0 }

Constants

getDefaultThreshold(): number

Get the default threshold for color closeness (0.05 = 5% of max RGB distance).

const threshold = getDefaultThreshold();
// 0.05

Processing Modes

Non-Strict Mode (default)

In non-strict mode, the algorithm finds the optimal foreground color and alpha that produces the observed color when alpha-blended with the background. This mode:

  • Works without specifying foreground colors
  • Allows any color to be used as foreground
  • Optimizes for minimum alpha (maximum transparency)
  • Always produces perfect reconstruction of the original image

Non-Strict Mode with Foreground Colors

When foreground colors are specified in non-strict mode:

  • Pixels close to specified foreground colors use the optimized unmixing algorithm
  • Pixels NOT close to any foreground color can use ANY color (preserves glows, gradients, etc.)
  • Uses the threshold option to determine "closeness"

Strict Mode

Strict mode restricts unmixing to only the specified foreground colors:

  • Requires at least one foreground color (can be "auto" for deduction)
  • Output pixels can only be a mix of the specified foreground colors
  • Best for images with known, limited color palettes

Foreground Color Deduction

Use "auto" in the foregroundColors array to automatically deduce unknown colors:

// Deduce one unknown color
const output = await processImage({
  input,
  foregroundColors: ['auto'],
  strictMode: true,
  trim: false,
});

// Mix known and unknown colors
const output = await processImage({
  input,
  foregroundColors: ['#ff0000', 'auto', 'auto'],
  strictMode: true,
  trim: false,
});

Performance

The library uses Rayon for parallel processing, utilizing all available CPU cores. For best performance:

  • Use processImage (async) for large images to avoid blocking the event loop
  • Use processImageSync for small images or batch processing
  • Consider using worker threads for processing multiple images

License

MIT

Credits

Based on bgone by Benface.

About

Node.js library to remove solid background colors from images without AI/ML

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors