Skip to main content
Glama
image-utils-canvas.ts4.46 kB
/** * Image utilities using canvas for cross-platform compatibility * Falls back to minimal implementation if canvas isn't available */ let canvasModule: any = null; // Try to load canvas module try { canvasModule = require('canvas'); } catch (error) { console.warn('Canvas module not available, using minimal image implementation'); } /** * 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(); return Buffer.from(screenshot, 'base64'); } /** * Generate an image with text */ export async function generateImage( width: number = 1280, height: number = 720, text?: string ): Promise<Buffer> { if (canvasModule) { try { const { createCanvas } = canvasModule; const canvas = createCanvas(width, height); const ctx = canvas.getContext('2d'); // Fill background ctx.fillStyle = '#f0f0f0'; ctx.fillRect(0, 0, width, height); // Add text if provided if (text) { ctx.fillStyle = '#333333'; ctx.font = '24px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(text, width / 2, height / 2); } // Return PNG buffer return canvas.toBuffer('image/png'); } catch (error) { console.warn('Canvas rendering failed:', error); } } // Fallback: return a minimal 1x1 transparent PNG return Buffer.from( 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==', 'base64' ); } /** * Crop an image to specified area * Note: Without image processing library, returns original */ export async function cropImage( imageBuffer: Buffer, area: { x: number; y: number; w: number; h: number } ): Promise<Buffer> { if (canvasModule) { try { const { createCanvas, loadImage } = canvasModule; const img = await loadImage(imageBuffer); const canvas = createCanvas(area.w, area.h); const ctx = canvas.getContext('2d'); ctx.drawImage(img, area.x, area.y, area.w, area.h, 0, 0, area.w, area.h); return canvas.toBuffer('image/png'); } catch (error) { console.warn('Canvas cropping failed:', error); } } return imageBuffer; // Return original if can't crop } /** * Get image dimensions */ export async function getImageDimensions(imageBuffer: Buffer): Promise<{ width: number; height: number }> { if (canvasModule) { try { const { loadImage } = canvasModule; const img = await loadImage(imageBuffer); return { width: img.width, height: img.height }; } catch (error) { console.warn('Failed to get image dimensions:', error); } } // Parse PNG header to get dimensions if possible if (imageBuffer.length > 24 && imageBuffer[0] === 0x89 && imageBuffer[1] === 0x50 && imageBuffer[2] === 0x4E && imageBuffer[3] === 0x47) { // PNG detected, extract dimensions from IHDR chunk const width = imageBuffer.readUInt32BE(16); const height = imageBuffer.readUInt32BE(20); return { width, height }; } // 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> { if (canvasModule) { try { const { createCanvas, loadImage } = canvasModule; const img = await loadImage(imageBuffer); const canvas = createCanvas(img.width, img.height); const ctx = canvas.getContext('2d'); // Draw original image ctx.drawImage(img, 0, 0); // Draw black rectangles over redacted areas ctx.fillStyle = '#000000'; for (const area of areas) { ctx.fillRect(area.x, area.y, area.w, area.h); } return canvas.toBuffer('image/png'); } catch (error) { console.warn('Canvas redaction failed:', 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 canvasModule !== null; }

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