### Install terminal-image Source: https://github.com/sindresorhus/terminal-image/blob/main/readme.md Install the package via npm. ```sh npm install terminal-image ``` -------------------------------- ### Configure Image Rendering Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/types.md Examples demonstrating various ways to configure image output using the ImageOptions object. ```javascript import terminalImage from 'terminal-image'; // Full width, half height, maintain aspect ratio const img1 = await terminalImage.file('photo.jpg', { width: '100%', height: '50%' }); // Fixed 40-column width, auto height (maintains aspect) const img2 = await terminalImage.file('photo.jpg', { width: 40 }); // Stretch to exact dimensions (no aspect ratio preservation) const img3 = await terminalImage.file('photo.jpg', { width: 60, height: 30, preserveAspectRatio: false }); // Force ANSI rendering (no graphics protocols) const img4 = await terminalImage.file('photo.jpg', { preferNativeRender: false }); ``` -------------------------------- ### Implement Custom RenderFrame Callbacks Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/types.md Examples of providing custom rendering logic and completion handlers for GIF animations. ```javascript import terminalImage from 'terminal-image'; // Custom frame renderer that accumulates frames to a log file const stop = terminalImage.gifFile('animation.gif', { renderFrame: (frameText) => { // Write each frame to stdout console.log(`[Frame] ${frameText}`); }, renderFrame: { done: () => { console.log('Animation finished'); } } }); // Custom frame renderer that uses alternative display method const stop2 = terminalImage.gifFile('spinner.gif', { renderFrame: (frameText) => { // Clear screen before rendering each frame process.stdout.write('\x1Bc'); process.stdout.write(frameText); } }); // Custom cleanup on animation completion const stop3 = terminalImage.gifFile('loading.gif', { renderFrame: (frameText) => { process.stdout.write(frameText); }, renderFrame: { done: () => { // Restore cursor, reset colors, etc. process.stdout.write('\x1B[?25h'); // Show cursor process.stdout.write('\x1B[0m'); // Reset formatting } } }); ``` -------------------------------- ### Example ANSI Color Mapping Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Demonstrates how chalk is used to map top and bottom pixels to block colors. ```javascript chalk.bgRgb(255, 0, 0).rgb(0, 0, 255)('▄') → Red background with blue half-block ``` -------------------------------- ### Configure GIF Animation Rendering Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/types.md Examples of using GifOptions with terminalImage.gifFile to control frame rates and custom rendering behavior. ```javascript import terminalImage from 'terminal-image'; // Standard animation at 30 FPS const stop1 = terminalImage.gifFile('spin.gif', { maximumFrameRate: 30 }); // High framerate animation const stop2 = terminalImage.gifFile('spin.gif', { maximumFrameRate: 60 }); // Lower framerate (CPU efficient) const stop3 = terminalImage.gifFile('spin.gif', { maximumFrameRate: 12 }); // With custom render function const stop4 = terminalImage.gifFile('spin.gif', { maximumFrameRate: 24, renderFrame: (frame) => { process.stdout.write(frame); } }); // With cleanup callback const stop5 = terminalImage.gifFile('spin.gif', { renderFrame: (frame) => { process.stdout.write(frame); }, renderFrame: { done: () => { console.log('Done!'); } } }); ``` -------------------------------- ### Display animated GIFs with terminalImage.gifFile Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/api-reference.md Examples showing how to play, limit framerate, and stop GIF animations in the terminal. ```javascript import terminalImage from 'terminal-image'; import {setTimeout} from 'node:timers/promises'; // Play a GIF animation const stopAnimation = terminalImage.gifFile('loading.gif', { width: '80%', height: '80%' }); // Stop after animation plays for 10 seconds await setTimeout(10000); stopAnimation(); // Play with limited framerate and cleanup const stop = terminalImage.gifFile('spinner.gif', { maximumFrameRate: 24, renderFrame: { done: () => { process.stdout.write('\n✓ Complete\n'); } } }); // Stop on user input (example with readline) import readline from 'node:readline'; const rl = readline.createInterface({input: process.stdin}); rl.on('line', () => { stop(); rl.close(); }); ``` -------------------------------- ### Control Animation Loop Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/configuration.md Manages the animation state using the isPlaying property to start or stop the loop. ```javascript return { get isPlaying() { return isPlaying; }, set isPlaying(value) { const wasPlaying = isPlaying; isPlaying = value; if (!value) { delayAbortController?.abort(); // Stop delays } else if (!wasPlaying && !loopPromise) { start(); // Restart if stopped } } } ``` -------------------------------- ### Stop GIF After Timeout Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Starts an animated GIF and manually stops it after a specified duration using a timer. ```javascript import {setTimeout} from 'node:timers/promises'; const stop = terminalImage.gifFile('spinner.gif'); await setTimeout(5000); stop(); ``` -------------------------------- ### Implement Comprehensive Error Handling Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Wrap image display logic in try-catch blocks to handle file system errors and invalid configuration options. ```javascript import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; async function safeDisplayImage(filePath, options = {}) { try { // Validate file exists await fs.access(filePath); // Display with options const image = await terminalImage.file(filePath, options); console.log(image); return true; } catch (error) { if (error.code === 'ENOENT') { console.error(`File not found: ${filePath}`); } else if (error.code === 'EACCES') { console.error(`Permission denied: ${filePath}`); } else if (error.message.includes('is not a valid dimension value')) { console.error(`Invalid dimension option`); } else { console.error(`Failed to display image: ${error.message}`); } return false; } } // Usage const success = await safeDisplayImage('photo.jpg', {width: '50%'}); if (success) { console.log('Image displayed successfully'); } ``` -------------------------------- ### Display images from buffer Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/api-reference.md Demonstrates various ways to render images from a buffer, including scaling options and forcing specific rendering modes. ```javascript import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; // Display an image from a buffer const imageData = await fs.readFile('photo.jpg'); console.log(await terminalImage.buffer(imageData)); // Display at 50% of terminal size console.log(await terminalImage.buffer(imageData, {width: '50%', height: '50%'})); // Display with fixed column width console.log(await terminalImage.buffer(imageData, {width: 40})); // Display without aspect ratio preservation console.log(await terminalImage.buffer(imageData, {width: 60, height: 30, preserveAspectRatio: false})); // Force ANSI rendering (no native protocols) console.log(await terminalImage.buffer(imageData, {preferNativeRender: false})); ``` -------------------------------- ### file(filePath, options?) Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Displays a static image from a local file path. ```APIDOC ## file(filePath, options?) ### Description Displays a static image from a local file path. ### Parameters - **filePath** (string) - Required - The path to the image file. - **options** (Object) - Optional - Configuration options for rendering (width, height, preserveAspectRatio, preferNativeRender). ### Returns - **Promise** - A promise that resolves with the rendered image string. ``` -------------------------------- ### Create Standalone CLI Image Viewer in JavaScript Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Build a CLI command that accepts a file path argument to display an image. Includes basic error handling for missing files or invalid paths. ```javascript #!/usr/bin/env node import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; import path from 'node:path'; async function main() { const imagePath = process.argv[2]; if (!imagePath) { console.error('Usage: show-image '); process.exit(1); } try { const image = await terminalImage.file(imagePath, {width: '90%'}); console.log(image); } catch (error) { console.error('Failed to display image:', error.message); process.exit(1); } } main(); ``` -------------------------------- ### Load Image for ANSI Rendering Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Initializes a Jimp image instance from a buffer. ```javascript const image = await Jimp.fromBuffer(Buffer.from(buffer)); ``` -------------------------------- ### gifFile(filePath, options?) Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Plays a GIF animation from a local file path. ```APIDOC ## gifFile(filePath, options?) ### Description Plays a GIF animation from a local file path. ### Parameters - **filePath** (string) - Required - The path to the GIF file. - **options** (Object) - Optional - Configuration options (width, height, preserveAspectRatio, preferNativeRender, maximumFrameRate, renderFrame). ### Returns - **() => void** - A function to stop the animation. ``` -------------------------------- ### Project Directory Structure Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Visual representation of the project file layout. ```text terminal-image/ ├── index.js # Main module (static & GIF rendering) ├── gif.js # GIF animation playback ├── index.d.ts # TypeScript type definitions ├── package.json # Project metadata └── readme.md # User-facing README ``` -------------------------------- ### Display Directory Images Sequentially in JavaScript Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Iterate through a directory to display images one by one with a configurable delay. ```javascript import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; import path from 'node:path'; import {setTimeout} from 'node:timers/promises'; async function displayAllImages(directory, delayMs = 1000) { const files = await fs.readdir(directory); const images = files.filter(f => /\.(jpg|jpeg|png)$/i.test(f)); for (const file of images) { try { const fullPath = path.join(directory, file); process.stdout.write('\x1Bc'); // Clear screen console.log(`Displaying: ${file}`); const image = await terminalImage.file(fullPath, {width: '90%'}); console.log(image); await setTimeout(delayMs); } catch (error) { console.error(`Skipped ${file}: ${error.message}`); } } } displayAllImages('./images'); ``` -------------------------------- ### Implement Interactive Image Menu in JavaScript Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Create an interactive browser for a directory of images using readline. Allows navigation between images with keyboard input. ```javascript import terminalImage from 'terminal-image'; import readline from 'node:readline'; import path from 'node:path'; import fs from 'node:fs/promises'; async function browseImages(directory) { const files = await fs.readdir(directory); const imageFiles = files.filter(f => /\.(jpg|jpeg|png)$/i.test(f)); let currentIndex = 0; async function displayCurrent() { const file = imageFiles[currentIndex]; const fullPath = path.join(directory, file); process.stdout.write('\x1Bc'); // Clear screen console.log(`Image ${currentIndex + 1}/${imageFiles.length}: ${file}`); console.log(await terminalImage.file(fullPath, {width: '80%'})); } const rl = readline.createInterface({input: process.stdin, output: process.stdout}); async function showMenu() { await displayCurrent(); rl.question('\n[N]ext [P]revious [Q]uit: ', async (answer) => { if (answer.toLowerCase() === 'n') { currentIndex = (currentIndex + 1) % imageFiles.length; await showMenu(); } else if (answer.toLowerCase() === 'p') { currentIndex = (currentIndex - 1 + imageFiles.length) % imageFiles.length; await showMenu(); } else if (answer.toLowerCase() === 'q') { rl.close(); } else { await showMenu(); } }); } await showMenu(); } browseImages('./images'); ``` -------------------------------- ### Enable Native Rendering Configuration Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Use this configuration object to prioritize native terminal protocols over ANSI block rendering. ```javascript {preferNativeRender: true} ``` -------------------------------- ### Protocol Selection Algorithm Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Logic used to determine the rendering method based on terminal type and image properties. ```pseudocode Input: terminal capabilities, image data, user preferences Output: rendered image if preferNativeRender = false: → Use ANSI block characters only if terminal type = iTerm2: → Use iTerm2 protocol else if Kitty capable AND not GIF frame: → Try Kitty protocol On success: done On failure: fall back to ANSI else: → Try term-img library (handles iTerm2) → Fall back to ANSI ``` -------------------------------- ### Display Documentation Hierarchy Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/00-START-HERE.md Visual representation of the project's documentation file structure. ```text START-HERE (this file) ↓ README.md ├─ Quick Start ├─ API Overview ├─ Terminal Support ├─ Common Patterns └─ Documentation Index ↓ api-reference.md (4 methods, complete signatures) ↓ Configuration & Options ├─ configuration.md (options, defaults, algorithms) ├─ types.md (type definitions) └─ errors.md (error handling) ↓ Implementation Details ├─ terminal-protocols.md (Kitty, iTerm2, ANSI) └─ implementation-guide.md (architecture, algorithms) ↓ usage-patterns.md (15+ examples) ``` -------------------------------- ### Display an Image File Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Renders an image file at full terminal size with automatic protocol detection. ```javascript import terminalImage from 'terminal-image'; console.log(await terminalImage.file('photo.jpg')); ``` -------------------------------- ### Process Images Concurrently in JavaScript Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Use Promise.all to process multiple images in parallel for improved efficiency. ```javascript import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; import path from 'node:path'; async function getImageThumbnails(directory) { const files = await fs.readdir(directory); const images = files.filter(f => /\.(jpg|jpeg|png)$/i.test(f)); // Process concurrently const results = await Promise.all( images.map(async (file) => { try { const fullPath = path.join(directory, file); const image = await terminalImage.file(fullPath, {width: '20%', height: '10%'}); return { file, success: true, image }; } catch (error) { return { file, success: false, error: error.message }; } }) ); return results; } const thumbnails = await getImageThumbnails('./gallery'); ``` -------------------------------- ### Display images and GIFs from files Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Use file-based methods to render static images or animated GIFs directly to the terminal. ```javascript import terminalImage from 'terminal-image'; // Display a static image console.log(await terminalImage.file('photo.jpg')); // Display an animated GIF terminalImage.gifFile('animation.gif'); ``` -------------------------------- ### buffer(imageBuffer, options?) Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Displays a static image from a Uint8Array buffer. ```APIDOC ## buffer(imageBuffer, options?) ### Description Displays a static image from a Uint8Array buffer. ### Parameters - **imageBuffer** (Uint8Array) - Required - The image data to render. - **options** (Object) - Optional - Configuration options for rendering (width, height, preserveAspectRatio, preferNativeRender). ### Returns - **Promise** - A promise that resolves with the rendered image string. ``` -------------------------------- ### Handle GIF size errors Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/errors.md Demonstrates how to catch the error thrown when a GIF is smaller than the 2x2 pixel minimum requirement. ```javascript import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; // Create a 1x1 pixel GIF (hypothetically) const tinyGifData = /* 1x1 GIF data */; // Throws: "The image is too small to be rendered." try { const stop = terminalImage.gifBuffer(tinyGifData); } catch (error) { console.error('GIF is too small:', error.message); } // Valid size - 2x2 minimum const minimalGifData = /* 2x2 GIF data */; const stop = terminalImage.gifBuffer(minimalGifData); // OK ``` ```javascript try { const stopAnimation = terminalImage.gifFile('animation.gif'); } catch (error) { if (error.message === 'The image is too small to be rendered.') { console.error('GIF dimensions are too small (must be at least 2x2)'); } else { throw error; } } ``` -------------------------------- ### ImageOptions Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/types.md Configuration object for static image rendering used by terminalImage.buffer() and terminalImage.file(). ```APIDOC ## ImageOptions ### Description Configuration object for static image rendering (common to both `buffer()` and `file()`). ### Properties - **width** (string | number) - Optional - Display width. String with '%' suffix for percentage (1-100), or number for terminal columns. Default: '100%'. - **height** (string | number) - Optional - Display height. String with '%' suffix for percentage (1-100), or number for terminal rows. Default: '100%'. - **preserveAspectRatio** (boolean) - Optional - When true, image maintains original aspect ratio when scaled. When false, image is stretched to exact dimensions. Default: true. - **preferNativeRender** (boolean) - Optional - When true, uses native terminal graphics protocols (Kitty, iTerm2) if available. When false, forces ANSI block character rendering. Default: true. ``` -------------------------------- ### Implement GIF Frame Rate Limiting Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/implementation-guide.md Logic for calculating frame intervals and determining render eligibility based on the maximumFrameRate option. ```text minInterval = 1000 / maximumFrameRate (milliseconds per frame) For each frame: 1. Get GIF frame delay in seconds 2. Convert to milliseconds and apply 10ms minimum 3. Calculate elapsed time since last render 4. Determine if frame should render: shouldRender = (minInterval === 0) OR (firstFrame) OR (elapsedSinceRender + frameDuration >= minInterval) 5. If rendering: - Wait until minInterval since last render - Render frame - Record current time as lastRenderTime 6. Wait for actual frame duration 7. Update elapsed counters (modulo minInterval for overflow) 8. Continue to next frame ``` -------------------------------- ### Percentage-Based Sizing Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Scales images relative to the terminal window size, which is recommended for responsive layouts. ```javascript import terminalImage from 'terminal-image'; // Half width and height console.log(await terminalImage.file('photo.jpg', {width: '50%', height: '50%'})); // Three-quarter width console.log(await terminalImage.file('photo.jpg', {width: '75%'})); // Various common ratios console.log(await terminalImage.file('photo.jpg', {width: '80%', height: '60%'})); ``` -------------------------------- ### Kitty Rendering Error Handling Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Falls back to ANSI rendering if the Kitty protocol fails. ```javascript try { return await renderKitty(buffer, {width, height, preserveAspectRatio}); } catch { return render(buffer, {height, width, preserveAspectRatio}); } ``` -------------------------------- ### Display an image in the terminal Source: https://github.com/sindresorhus/terminal-image/blob/main/readme.md Render a local image file to the terminal output. ```js import terminalImage from 'terminal-image'; console.log(await terminalImage.file('unicorn.jpg')); ``` -------------------------------- ### gifBuffer(imageBuffer, options?) Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Plays a GIF animation from a Uint8Array buffer. ```APIDOC ## gifBuffer(imageBuffer, options?) ### Description Plays a GIF animation from a Uint8Array buffer. ### Parameters - **imageBuffer** (Uint8Array) - Required - The GIF data to render. - **options** (Object) - Optional - Configuration options (width, height, preserveAspectRatio, preferNativeRender, maximumFrameRate, renderFrame). ### Returns - **() => void** - A function to stop the animation. ``` -------------------------------- ### terminalImage.gifFile(filePath, options?) Source: https://github.com/sindresorhus/terminal-image/blob/main/readme.md Renders an animated GIF from a file path to the terminal. ```APIDOC ## terminalImage.gifFile(filePath, options?) ### Description Displays an animated GIF from a file path. Returns a function that can be called to stop the animation. ### Parameters - **filePath** (string) - Required - The path to the GIF file. - **options** (object) - Optional - Configuration including maximumFrameRate, renderFrame, and renderFrame.done. ``` -------------------------------- ### Display images from buffers Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Render images by passing raw buffer data, useful when reading files manually or receiving data from network streams. ```javascript import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; const imageData = await fs.readFile('photo.jpg'); console.log(await terminalImage.buffer(imageData)); ``` -------------------------------- ### terminalImage.buffer(imageBuffer, options?) Source: https://github.com/sindresorhus/terminal-image/blob/main/readme.md Renders an image from a buffer to the terminal. ```APIDOC ## terminalImage.buffer(imageBuffer, options?) ### Description Displays an image from a buffer in the terminal. Returns a Promise that resolves to a string containing the ANSI escape codes. ### Parameters - **imageBuffer** (Buffer) - Required - The image data to render. - **options** (object) - Optional - Configuration for rendering (width, height, preserveAspectRatio, preferNativeRender). ``` -------------------------------- ### Handle file system errors Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/errors.md Shows how to catch and identify common Node.js file system errors like ENOENT or EACCES when loading images or GIFs. ```javascript import terminalImage from 'terminal-image'; // File not found - promise rejection terminalImage.file('nonexistent.jpg') .catch(error => { if (error.code === 'ENOENT') { console.error('Image file not found'); } else if (error.code === 'EACCES') { console.error('Permission denied reading image file'); } }); // GIF file not found - synchronous throw try { const stop = terminalImage.gifFile('/invalid/path/animation.gif'); } catch (error) { if (error.code === 'ENOENT') { console.error('GIF file not found'); } } ``` -------------------------------- ### Display Image at 50% Size Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Renders a local image file scaled to 50% of its original dimensions. ```javascript console.log(await terminalImage.file('photo.jpg', {width: '50%', height: '50%'})); ``` -------------------------------- ### terminalImage.file(filePath, options?) Source: https://github.com/sindresorhus/terminal-image/blob/main/readme.md Renders an image from a file path to the terminal. ```APIDOC ## terminalImage.file(filePath, options?) ### Description Displays an image from a file path in the terminal. Returns a Promise that resolves to a string containing the ANSI escape codes. ### Parameters - **filePath** (string) - Required - The path to the image file. - **options** (object) - Optional - Configuration for rendering (width, height, preserveAspectRatio, preferNativeRender). ``` -------------------------------- ### Chunking Data for Kitty Protocol Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Splits base64 data into 4KB chunks to comply with terminal buffer limits. ```javascript const chunks = []; for (let index = 0; index < base64Data.length; index += 4096) { chunks.push(base64Data.slice(index, index + 4096)); } ``` -------------------------------- ### Display images in terminal Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Render images from a file path or a buffer. Requires an ESM environment. ```javascript import terminalImage from 'terminal-image'; // Display an image console.log(await terminalImage.file('photo.jpg')); // Or from a buffer const buffer = /* image data */; console.log(await terminalImage.buffer(buffer)); ``` -------------------------------- ### Display Animated Loading Spinner in JavaScript Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Use an animated GIF as a progress indicator during asynchronous operations. Ensure the cursor is restored in the renderFrame done callback. ```javascript import terminalImage from 'terminal-image'; import {setTimeout} from 'node:timers/promises'; async function performTaskWithSpinner(task) { const stopSpinner = terminalImage.gifFile('spinner.gif', { width: '20%', renderFrame: { done: () => { process.stdout.write('\x1B[?25h'); // Show cursor process.stdout.write('\n✓ Done!\n'); } } }); try { const result = await task(); return result; } finally { stopSpinner(); } } // Usage const data = await performTaskWithSpinner(async () => { // Simulate async work await new Promise(r => setTimeout(r, 3000)); return {status: 'success'}; }); ``` -------------------------------- ### Play Animated GIF with Cleanup Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Plays an animated GIF and executes a callback function upon completion. ```javascript const stop = terminalImage.gifFile('animation.gif', { renderFrame: { done: () => console.log('✓ Complete!') } }); ``` -------------------------------- ### Handle Image and GIF Processing Errors Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/errors.md Demonstrates catching errors for both static image buffer processing and asynchronous GIF animation rendering. ```javascript import terminalImage from 'terminal-image'; // Invalid image data const corruptedData = Buffer.from([0xFF, 0xD8, 0x00, 0x01]); // Invalid JPEG try { const result = await terminalImage.buffer(corruptedData); } catch (error) { console.error('Failed to process image:', error.message); } // GIF rendering error during animation terminalImage.gifBuffer(corruptedGifData) .then(stopAnimation => { // Might error asynchronously when rendering frames }) .catch(error => { console.error('GIF animation error:', error.message); }); ``` -------------------------------- ### Calculate Image Dimensions Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/implementation-guide.md Logic for resolving input dimensions against terminal constraints and aspect ratio requirements. ```text Input: {width: userWidth, height: userHeight} terminal: {columns, rows} preserveAspectRatio: boolean image: {width: imgW, height: imgH} 1. Convert percentage strings to pixels: width_px = parseInt(width.slice(0, -1)) / 100 * columns height_px = parseInt(height.slice(0, -1)) / 100 * rows 2. Handle single dimension specified: if both: use as-is (may scale if aspect ratio preserved) if width only: height = imageHeight * (width / imageWidth) if height only: width = imageWidth * (height / imageHeight) if neither: width = columns, height = rows * 2 3. If preserveAspectRatio: Apply scale() function to fit within bounds 4. Constrain to terminal: if width > terminal_columns: Rescale both to fit within columns ``` -------------------------------- ### terminalImage.gifBuffer(imageBuffer, options?) Source: https://github.com/sindresorhus/terminal-image/blob/main/readme.md Renders an animated GIF from a buffer to the terminal. ```APIDOC ## terminalImage.gifBuffer(imageBuffer, options?) ### Description Displays an animated GIF from a buffer. Returns a function that can be called to stop the animation. ### Parameters - **imageBuffer** (Buffer) - Required - The GIF data. - **options** (object) - Optional - Configuration including maximumFrameRate, renderFrame, and renderFrame.done. ``` -------------------------------- ### Render static images from file paths Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/api-reference.md Use terminalImage.file() to display PNG or JPEG images. The method accepts optional dimensions and aspect ratio settings. ```typescript file( filePath: string, options?: Readonly<{ width?: string | number; height?: string | number; preserveAspectRatio?: boolean; preferNativeRender?: boolean; }> ): Promise ``` ```javascript import terminalImage from 'terminal-image'; // Display a JPEG image console.log(await terminalImage.file('unicorn.jpg')); // Display a PNG with custom dimensions console.log(await terminalImage.file('photo.png', {width: '75%', height: '75%'})); // Display with exact terminal cell dimensions console.log(await terminalImage.file('image.jpg', {width: 50, height: 25})); // Mix percentage and cell dimensions (preserves aspect ratio by default) console.log(await terminalImage.file('image.jpg', {width: '50%'})); ``` -------------------------------- ### Display remote images with retry logic Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Implements a robust fetching pattern with configurable retries and request timeouts. ```javascript import terminalImage from 'terminal-image'; import got from 'got'; async function displayRemoteImageWithRetry(url, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await got(url, {timeout: {request: 5000}}); console.log(await terminalImage.buffer(response.body)); return; } catch (error) { if (attempt === maxRetries) throw error; console.error(`Attempt ${attempt} failed, retrying...`); await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); } } } displayRemoteImageWithRetry('https://example.com/image.jpg'); ``` -------------------------------- ### terminalImage.file() Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/api-reference.md Displays an image file (PNG or JPEG) in the terminal. ```APIDOC ## terminalImage.file(filePath, options) ### Description Displays images in the terminal from a file path. Reads the file and returns ANSI escape codes for the rendered image. ### Parameters - **filePath** (string) - Required - Absolute or relative path to the image file (PNG or JPEG). - **options** (object) - Optional - Configuration object. - **width** (string | number) - Optional - Image display width (default: '100%'). - **height** (string | number) - Optional - Image display height (default: '100%'). - **preserveAspectRatio** (boolean) - Optional - Maintain aspect ratio (default: true). - **preferNativeRender** (boolean) - Optional - Use native terminal protocols (default: true). ### Returns - **Promise** - Resolves to ANSI escape codes for the rendered image. ``` -------------------------------- ### Display Sequential Images in JavaScript Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Render a sequence of static images as a slideshow. Uses ANSI escape codes to clear the screen between frames. ```javascript import terminalImage from 'terminal-image'; import {setTimeout} from 'node:timers/promises'; async function displayProgressSequence(imageFiles, delayMs = 500) { for (const file of imageFiles) { process.stdout.write('\x1Bc'); // Clear screen console.log(await terminalImage.file(file, {width: '80%'})); await setTimeout(delayMs); } } displayProgressSequence(['step1.png', 'step2.png', 'step3.png']); ``` -------------------------------- ### Display a remote image Source: https://github.com/sindresorhus/terminal-image/blob/main/readme.md Fetch an image buffer from a URL and render it using terminalImage.buffer. ```js import terminalImage from 'terminal-image'; import got from 'got'; const body = await got('https://sindresorhus.com/unicorn').buffer(); console.log(await terminalImage.buffer(body)); ``` -------------------------------- ### Play an animated GIF Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/00-START-HERE.md Renders an animated GIF file in the terminal. ```javascript import terminalImage from 'terminal-image'; terminalImage.gifFile('animation.gif'); ``` -------------------------------- ### Default GIF Renderer Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/configuration.md Configures the frame rendering function to use log-update for in-place frame overwriting. ```javascript renderFrame: logUpdate ``` -------------------------------- ### Invoke iTerm2 Protocol in terminal-image Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Delegates image rendering to the term-img library, falling back to ANSI rendering if unsupported. ```javascript return termImg(buffer, { width, height, fallback: () => render(buffer, {height, width, preserveAspectRatio}), }); ``` -------------------------------- ### Handle terminal-image errors Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/README.md Use a try-catch block to handle common errors like missing files or invalid dimensions. ```javascript try { await terminalImage.file('missing.jpg'); } catch (error) { if (error.code === 'ENOENT') { console.error('File not found'); } else if (error.message.includes('is not a valid dimension value')) { console.error('Invalid width/height format'); } else { console.error('Image processing failed'); } } ``` -------------------------------- ### Convert Image to PNG Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Checks for PNG magic bytes and converts non-PNG formats using Jimp. ```javascript const isPng = buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && buffer[3] === 0x47; if (!isPng) { // Convert to PNG if needed const image = await Jimp.fromBuffer(Buffer.from(buffer)); imageBuffer = await image.getBuffer('image/png'); } ``` -------------------------------- ### Fixed Column/Row Sizing Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Sets image dimensions based on specific terminal cell counts. ```javascript import terminalImage from 'terminal-image'; // Display 40 columns wide (height auto-calculated) console.log(await terminalImage.file('photo.jpg', {width: 40})); // Display 25 rows tall (width auto-calculated) console.log(await terminalImage.file('photo.jpg', {height: 25})); // Fixed dimensions (height will be scaled proportionally) console.log(await terminalImage.file('photo.jpg', {width: 60, height: 40})); ``` -------------------------------- ### Kitty Protocol Control Data Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/configuration.md Defines the control parameters used when transmitting image data in 4KB chunks via the Kitty protocol. ```text f=100 Format: PNG (always converted to PNG) a=T Action: transmit and display q=2 Quiet: suppress terminal responses c=N Columns: specified column count (if provided and > 0) r=N Rows: specified row count (if provided and > 0) m=M More chunks: 1 if more follow, 0 for last chunk ``` -------------------------------- ### Render GIF Frame Pipeline Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md The sequence of operations for processing and displaying individual GIF frames. ```text Decode GIF frame 1 ↓ Render frame to PNG ↓ Convert to ANSI blocks ↓ Display with log-update (overwrite previous) ↓ Wait for frame duration ↓ Repeat for next frame ``` -------------------------------- ### Handle Transparency in ANSI Rendering Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Conditional logic to handle alpha channels by resetting colors for transparent pixels. ```javascript if (a === 0) { // Transparent: use reset color, only show bottom pixel color chalk.reset.rgb(r2, g2, b2)(PIXEL) } else { // Opaque: use both colors chalk.bgRgb(r, g, b).rgb(r2, g2, b2)(PIXEL) } ``` -------------------------------- ### Return Rendered ANSI Lines Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Joins the processed lines into a single string for terminal output. ```javascript return lines.join('\n'); ``` -------------------------------- ### Downscale Large Images in JavaScript Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Resize images before rendering to reduce memory usage by specifying width and height percentages. ```javascript import terminalImage from 'terminal-image'; import Jimp from 'jimp'; import fs from 'node:fs/promises'; async function displayLargeImageEfficiently(filePath) { // Pre-process: limit to 80% of terminal const result = await terminalImage.file(filePath, { width: '80%', height: '80%' }); console.log(result); } displayLargeImageEfficiently('huge-image.jpg'); ``` -------------------------------- ### Detect Terminal Graphics Support Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Use this pattern to check for terminal graphics support and provide a fallback mechanism for incompatible environments. ```javascript import terminalImage from 'terminal-image'; import supportsTerminalGraphics from 'supports-terminal-graphics'; async function displayImageWithFallback(filePath) { const hasGraphicsSupport = supportsTerminalGraphics.stdout.kitty || process.env.TERM_PROGRAM === 'iTerm.app'; if (hasGraphicsSupport) { console.log(await terminalImage.file(filePath, {width: '80%'})); } else { console.log('│ Terminal does not support graphics │'); console.log(`│ Display image with: cat ${filePath} │`); } } displayImageWithFallback('photo.jpg'); ``` -------------------------------- ### Define ImageOptions Type Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/types.md TypeScript type definition for configuring image rendering options. ```typescript type ImageOptions = { width?: string | number; height?: string | number; preserveAspectRatio?: boolean; preferNativeRender?: boolean; } ``` -------------------------------- ### GifOptions Type Definition Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/types.md Configuration object for GIF animation rendering used by gifBuffer() and gifFile(). ```APIDOC ## GifOptions ### Description Configuration object for GIF animation rendering (common to both `gifBuffer()` and `gifFile()`). ### Properties - **width** (string | number) - Optional - Frame display width. String with '%' suffix for percentage or number for columns. Default: '100%'. - **height** (string | number) - Optional - Frame display height. String with '%' suffix for percentage or number for rows. Default: '100%'. - **maximumFrameRate** (number) - Optional - Maximum framerate (FPS) for animation playback. Ignored in iTerm2. Set to 0 for unlimited. Default: 30. - **renderFrame** (RenderFrame) - Optional - Custom frame rendering function. Default uses log-update for smooth in-place animation. ``` -------------------------------- ### Define GifOptions Type Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/types.md TypeScript definition for the configuration object used in GIF rendering methods. ```typescript type GifOptions = { width?: string | number; height?: string | number; maximumFrameRate?: number; renderFrame?: RenderFrame; } ``` -------------------------------- ### Custom GIF frame rendering Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Overrides the default renderer to apply custom formatting or layout to each frame. ```javascript import terminalImage from 'terminal-image'; const stopAnimation = terminalImage.gifFile('animation.gif', { renderFrame: (frameText) => { // Custom rendering - e.g., with border process.stdout.write('\x1Bc'); // Clear screen console.log('┌─────────────────┐'); console.log('│ Animation Frame │'); console.log('└─────────────────┘'); console.log(frameText); } }); ``` -------------------------------- ### Render animated GIFs from buffers Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/api-reference.md Use terminalImage.gifBuffer() to play animated GIFs. It returns a stop function to terminate the animation. ```typescript gifBuffer( imageBuffer: Readonly, options?: Readonly<{ width?: string | number; height?: string | number; maximumFrameRate?: number; renderFrame?: RenderFrame; }> ): () => void ``` ```javascript import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; import {setTimeout} from 'node:timers/promises'; // Play a GIF animation for 5 seconds const gifData = await fs.readFile('animation.gif'); const stopAnimation = terminalImage.gifBuffer(gifData); await setTimeout(5000); stopAnimation(); // Play with custom frame rendering const stop = terminalImage.gifBuffer(gifData, { width: '50%', height: '50%', maximumFrameRate: 15, renderFrame: (frameText) => { // Custom rendering logic process.stdout.write('\x1Bc'); // Clear screen console.log(frameText); }, renderFrame: { done: () => { console.log('Animation complete!'); } } }); // Stop after 3 seconds await setTimeout(3000); stop(); // High framerate animation const quickStop = terminalImage.gifBuffer(gifData, { maximumFrameRate: 60 // 60 FPS }); ``` -------------------------------- ### Kitty Protocol Transmission Format Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Base64-encoded PNG data transmission format for the Kitty graphics protocol. ```text ESC _G {control data} ; {chunk data} ESC \ ``` ```text ESC _G f=100,a=T,q=2,c=40,r=20,m=0;{4KB of base64} ESC \ ``` ```text ESC _G f=100,a=T,q=2,c=40,r=20,m=1;{4KB of base64 chunk 1} ESC \ ESC _G q=2,m=1;{4KB of base64 chunk 2} ESC \ ESC _G q=2,m=0;{4KB of base64 chunk 3} ESC \ ``` -------------------------------- ### Handle Dimension Value Errors Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/errors.md Demonstrates triggering and catching dimension value errors when providing invalid width or height options. ```javascript import terminalImage from 'terminal-image'; import fs from 'node:fs/promises'; const imageData = await fs.readFile('photo.jpg'); // Throws: "0 is not a valid dimension value" try { await terminalImage.buffer(imageData, {width: 0}); } catch (error) { console.error('Invalid width:', error.message); } // Throws: "101 is not a valid dimension value" try { await terminalImage.buffer(imageData, {height: '101%'}); } catch (error) { console.error('Invalid height:', error.message); } // Throws: "50 is not a valid dimension value" try { await terminalImage.buffer(imageData, {width: '50'}); // String without % } catch (error) { console.error('Invalid width format:', error.message); } // Valid formats - these work await terminalImage.buffer(imageData, {width: '50%'}); // OK await terminalImage.buffer(imageData, {height: 30}); // OK await terminalImage.buffer(imageData, {width: '100%', height: 50}); // OK ``` -------------------------------- ### Optimize GIF Frame Rate in JavaScript Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Lower the maximum frame rate to reduce CPU usage in resource-constrained environments. ```javascript import terminalImage from 'terminal-image'; // CPU-efficient: 12 FPS const stop = terminalImage.gifFile('animation.gif', { maximumFrameRate: 12, // Lower framerate = less CPU width: '50%' }); ``` -------------------------------- ### Detect Terminal Graphics Capabilities Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/implementation-guide.md Uses supports-terminal-graphics to identify available protocols, with specific checks for Kitty and iTerm2. ```javascript import supportsTerminalGraphics from 'supports-terminal-graphics'; // Check stdout capabilities if (supportsTerminalGraphics.stdout.kitty) { // Kitty Graphics Protocol available } // Also checks for iTerm2 via environment: const isITerm2 = process.env.TERM_PROGRAM === 'iTerm.app'; ``` -------------------------------- ### Scale images in the terminal Source: https://github.com/sindresorhus/terminal-image/blob/main/readme.md Adjust image dimensions using percentages or specific column/row counts. ```js import terminalImage from 'terminal-image'; console.log(await terminalImage.file('unicorn.jpg', {width: '50%', height: '50%'})); ``` ```js import terminalImage from 'terminal-image'; console.log(await terminalImage.file('unicorn.jpg', {width: 50})); ``` -------------------------------- ### Detect iTerm2 Environment Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Checks the TERM_PROGRAM environment variable to identify iTerm2 sessions. ```javascript const isITerm2 = process.env.TERM_PROGRAM === 'iTerm.app'; ``` -------------------------------- ### Constrain Kitty Image Dimensions Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Calculates dimensions to preserve aspect ratio within terminal cell constraints. ```javascript function constrainKittyDimensions(buffer, columns, rows) { // Calculate image aspect ratio imageAspectRatio = imageWidth / imageHeight // Terminal cells are approximately 2:1 (height:width) cellAspectRatio = 0.5 terminalAspectRatio = (columns * cellAspectRatio) / rows // Constrain by whichever dimension actually limits the image if (imageAspectRatio > terminalAspectRatio) { // Image wider than terminal space - constrain by width return [columns, undefined] } else { // Image taller - constrain by height return [undefined, rows] } } ``` -------------------------------- ### Calculate ANSI Rendering Dimensions Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Determines output dimensions based on terminal constraints and user options. ```javascript const {width, height} = calculateWidthHeight( bitmap, inputWidth, inputHeight, preserveAspectRatio ); ``` -------------------------------- ### Enforce Minimum Frame Duration Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/configuration.md Ensures GIF frames meet a minimum duration threshold of 10ms. ```javascript const MINIMUM_FRAME_DURATION = 10; // milliseconds function effectiveFrameDuration(frameMs) { if (frameMs === 0) { return MINIMUM_FRAME_DURATION; } return frameMs; } ``` -------------------------------- ### Define Protocol Fallback Chain Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md The logic flow for selecting the appropriate terminal graphics protocol. ```text Check capabilities ↓ Kitty available? No → Check iTerm2 Yes and not iTerm2 → Try Kitty iTerm2 → Use iTerm2 (preferred over Kitty in iTerm) ↓ Try selected protocol ↓ Fails or unsupported? → Fall back to ANSI blocks ``` -------------------------------- ### Play GIF animation until completion Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/usage-patterns.md Plays a GIF file automatically until the animation sequence finishes. ```javascript import terminalImage from 'terminal-image'; const stopAnimation = terminalImage.gifFile('animation.gif'); // Animation plays in background until completion ``` -------------------------------- ### Iterate Pixels for ANSI Rendering Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/terminal-protocols.md Processes image pixels in pairs to generate colored half-block characters. ```javascript for (let y = 0; y < bitmap.height - 1; y += 2) { let line = ''; for (let x = 0; x < bitmap.width; x++) { // Get top and bottom pixel const {r, g, b, a} = intToRGBA(image.getPixelColor(x, y)); const {r: r2, g: g2, b: b2} = intToRGBA(image.getPixelColor(x, y + 1)); // Create colored half-block line += a === 0 ? chalk.reset.rgb(r2, g2, b2)(PIXEL) : chalk.bgRgb(r, g, b).rgb(r2, g2, b2)(PIXEL); } lines.push(line); } ``` -------------------------------- ### Constrain Kitty Protocol Dimensions Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/configuration.md Determines whether to constrain by width or height when rendering in the Kitty protocol to maintain aspect ratio. ```javascript function constrainKittyDimensions(buffer, columns, rows) { const imageAspectRatio = dimensions.width / dimensions.height; const cellAspectRatio = 0.5; // Terminal cells are ~2:1 const terminalAspectRatio = (columns * cellAspectRatio) / rows; // Constrain by width if image is wider than terminal space, else by height return imageAspectRatio > terminalAspectRatio ? [columns, undefined] : [undefined, rows]; } ``` -------------------------------- ### Handle Errors in GIF Animation Loop Source: https://github.com/sindresorhus/terminal-image/blob/main/_autodocs/implementation-guide.md Ensures the animation state is reset and resources are cleaned up when an error occurs during the main loop. ```javascript try { await loop(); // Main animation loop } catch (error) { isPlaying = false; // Stop animation throw error; // Rethrow } finally { loopPromise = undefined; // Cleanup } ```