Skip to main content
Glama
image-utils.ts3.8 kB
/** * Image utilities using jimp for cross-platform compatibility */ const Jimp = require('jimp'); /** * Capture a screenshot from WebDriver and ensure it's in PNG format */ export async function captureScreenshot(driver: any): Promise<Buffer> { const screenshot = await driver.takeScreenshot(); const buffer = Buffer.from(screenshot, 'base64'); try { // Use Jimp to ensure PNG format const image = await Jimp.read(buffer); return await image.getBufferAsync(Jimp.MIME_PNG); } catch (error) { // If Jimp fails, return the buffer as-is (WebDriver screenshots are usually PNG) console.warn('Jimp processing failed, returning raw screenshot:', error); return buffer; } } /** * Generate an image with text using Jimp */ export async function generateImage( width: number = 1280, height: number = 720, text?: string ): Promise<Buffer> { try { // Create a new image with light gray background const image = new Jimp(width, height, '#f0f0f0'); // Load font and add text if provided if (text) { const font = await Jimp.loadFont(Jimp.FONT_SANS_32_BLACK); // Calculate text position (centered) const textWidth = Jimp.measureText(font, text); const textHeight = Jimp.measureTextHeight(font, text, width); const x = (width - textWidth) / 2; const y = (height - textHeight) / 2; image.print(font, x, y, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER, alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE }, width, height); } return await image.getBufferAsync(Jimp.MIME_PNG); } catch (error) { console.warn('Failed to generate image with Jimp:', error); // Fallback: return a minimal 1x1 transparent PNG return Buffer.from( 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==', 'base64' ); } } /** * Crop an image to specified area */ export async function cropImage( imageBuffer: Buffer, area: { x: number; y: number; w: number; h: number } ): Promise<Buffer> { try { const image = await Jimp.read(imageBuffer); image.crop(area.x, area.y, area.w, area.h); return await image.getBufferAsync(Jimp.MIME_PNG); } catch (error) { console.warn('Failed to crop image:', error); return imageBuffer; // Return original if crop fails } } /** * Get image dimensions */ export async function getImageDimensions(imageBuffer: Buffer): Promise<{ width: number; height: number }> { try { const image = await Jimp.read(imageBuffer); return { width: image.getWidth(), height: image.getHeight() }; } catch (error) { console.warn('Failed to get image dimensions:', error); // Return default dimensions return { width: 1920, height: 1080 }; } } /** * Apply redaction to an image (black boxes) */ export async function applyRedaction( imageBuffer: Buffer, areas: Array<{ x: number; y: number; w: number; h: number }> ): Promise<Buffer> { try { const image = await Jimp.read(imageBuffer); // Draw black rectangles over redacted areas for (const area of areas) { // Create a black rectangle const blackBox = new Jimp(area.w, area.h, '#000000'); image.composite(blackBox, area.x, area.y); } return await image.getBufferAsync(Jimp.MIME_PNG); } catch (error) { console.warn('Failed to apply redaction:', error); return imageBuffer; } } /** * Convert image buffer to base64 string */ export function imageToBase64(buffer: Buffer): string { return buffer.toString('base64'); } /** * Check if image processing is available */ export function isImageProcessingAvailable(): boolean { return true; // Jimp is always available as it's pure JavaScript }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JacobFV/mcp-fullstack'

If you have feedback or need assistance with the MCP directory API, please join our Discord server