πΌοΈ Display and animate images, GIFs, and photo sequences directly in your terminal with ANSI color support π₯οΈ

Pixelpop is a sophisticated terminal utility library that brings visual content to command-line applications. With intelligent terminal detection and multiple rendering strategies, it ensures your images look great across different terminal environments.
- πΌοΈ Multi-format Support - Display JPEG, PNG, GIF, and more
- π¬ GIF Animation - Smooth animated GIF playback with frame rate control
- π― Smart Terminal Detection - Automatically adapts to your terminal's capabilities
- π Flexible Sizing - Percentage-based dimensions with aspect ratio preservation
- π Universal Compatibility - Works in iTerm2, Kitty, WezTerm, and standard terminals
- β‘ High Performance - Optimized rendering with intelligent fallbacks
- π§ TypeScript Ready - Full type definitions included
# Using npm
npm install @pinkpixel/pixelpop
# Using yarn
yarn add @pinkpixel/pixelpop
# Using pnpm
pnpm add @pinkpixel/pixelpop
Note: @pinkpixel/pixelpop
is ESM-only ("type": "module"
). Use ESM in your project, or use dynamic import()
from CommonJS if needed.
import pixelPop from "@pinkpixel/pixelpop";
// Display a static image
const output = await pixelPop.file("./my-image.jpg", {
width: "50%",
});
console.log(output);
// Play an animated GIF
const stop = await pixelPop.gifFile("./my-animation.gif", {
width: "80%",
maximumFrameRate: 24,
});
// Stop the animation after 5 seconds
setTimeout(stop, 5000);
Display an image from a file path.
await pixelPop.file("./image.jpg", {
width: "60%",
height: 20,
preserveAspectRatio: true,
});
Display an image from a buffer.
const imageBuffer = fs.readFileSync("./image.jpg");
await pixelPop.buffer(imageBuffer, { width: "50%" });
Play an animated GIF from a file path. Returns a function to stop the animation.
const stop = await pixelPop.gifFile("./animation.gif", {
width: "75%",
maximumFrameRate: 30,
});
Play an animated GIF from a buffer. Returns a function to stop the animation.
const gifBuffer = fs.readFileSync("./animation.gif");
const stop = await pixelPop.gifBuffer(gifBuffer, {
maximumFrameRate: 15,
});
interface RenderOptions {
width?: DimensionValue; // number or percentage string like '50%'
height?: DimensionValue; // number or percentage string like '50%'
preserveAspectRatio?: boolean; // default: true
}
interface GifOptions extends RenderOptions {
maximumFrameRate?: number; // default: 30
renderFrame?: RenderFrame; // custom frame renderer
}
type DimensionValue = number | `${number}%`;
import pixelPop from "@pinkpixel/pixelpop";
// Adapt to terminal size
await pixelPop.file("./hero-image.jpg", {
width: "100%",
preserveAspectRatio: true,
});
import pixelPop from "@pinkpixel/pixelpop";
const stop = await pixelPop.gifFile("./loading.gif", {
width: "25%",
maximumFrameRate: 20,
});
// Stop after process completes
await someAsyncOperation();
stop();
import pixelPop from "@pinkpixel/pixelpop";
import logUpdate from "log-update";
const customRenderer = (frame: string) => {
logUpdate(`\n㪠Animation Frame:\n${frame}`);
};
customRenderer.done = () => {
logUpdate.done();
console.log("Animation complete!");
};
await pixelPop.gifFile("./demo.gif", {
renderFrame: customRenderer,
maximumFrameRate: 24,
});
import pixelPop from "@pinkpixel/pixelpop";
import { promises as fs } from "fs";
const imageBuffer = await fs.readFile("./screenshot.png");
const output = await pixelPop.buffer(imageBuffer, {
width: 80,
height: "50%",
});
console.log(output);
Pixelpop uses a sophisticated multi-strategy rendering approach:
Automatically detects your terminal's capabilities by checking environment variables:
TERM_PROGRAM
(iTerm2, WezTerm, etc.)TERM
(xterm-kitty, etc.)KITTY_WINDOW_ID
andKONSOLE_VERSION
Uses term-img
for terminals with built-in image protocols.
Direct image rendering using Kitty's graphics protocol for superior quality.
Block character rendering with RGB colors using Chalk - works everywhere!
- FFmpeg-based frame extraction to temporary files
- Controlled animation loop with configurable frame rates
- Automatic cleanup of temporary resources
Terminal | Strategy | Quality |
---|---|---|
iTerm2 | Native | βββββ |
Kitty | Kitty Protocol | βββββ |
WezTerm | Kitty Protocol | βββββ |
Warp | ANSI Fallback | ββββ |
Konsole | Kitty Protocol | ββββ |
Terminal.app | ANSI Fallback | βββ |
Windows Terminal | ANSI Fallback | βββ |
Standard xterm | ANSI Fallback | βββ |
- Node.js >= 20
- npm, yarn, or pnpm
git clone https://github.com/pinkpixel-dev/pixelpop.git
cd pixelpop
npm install
npm run build # Compile TypeScript
npm run clean # Clean dist directory
npm run prepare # Full build (runs automatically on install)
npm run lint # Run ESLint
npm run lint:fix # Fix ESLint issues
npm run typecheck # TypeScript validation
Examples in examples/
are TypeScript. Run them with a TS runner like tsx
or ts-node
, or copy snippets into your own app:
npm run build
# Using tsx (recommended)
npx tsx examples/example.ts # Static image demo
npx tsx examples/example_gif.ts # Animated GIF demo
# Or using ts-node (if installed)
node --loader ts-node/esm examples/example.ts
node --loader ts-node/esm examples/example_gif.ts
Pixelpop includes comprehensive documentation with detailed guides, examples, and API references. Visit the /docs
directory for complete documentation:
- π Getting Started Guide - Installation, basic usage, and core concepts
- π― API Reference - Complete method documentation, types, and interfaces
- π¬ GIF Animation Guide - Advanced animation techniques and performance optimization
- π¨ Terminal Compatibility - Terminal-specific optimizations and troubleshooting
- π‘ Examples & Recipes - Real-world usage patterns and integration examples
// Static images
await pixelPop.file(filePath, options?) // Display image from file
await pixelPop.buffer(buffer, options?) // Display image from buffer
// Animated GIFs
const stop = await pixelPop.gifFile(filePath, options?) // Play GIF from file
const stop = await pixelPop.gifBuffer(buffer, options?) // Play GIF from buffer
// All methods support:
// - width/height: number | '50%' (percentage or pixels)
// - preserveAspectRatio: boolean (default: true)
// - maximumFrameRate: number (GIFs only, default: 30)
// - renderFrame: custom renderer function (GIFs only)
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Make your changes and add tests
- Run the test suite:
npm test
- Commit your changes:
git commit -m 'Add amazing feature'
- Push to the branch:
git push origin feature/amazing-feature
- Open a Pull Request
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Website: https://pinkpixel.dev Email: admin@pinkpixel.dev
Made with β€οΈ by Pink Pixel
β Star this repo if you find it useful!