Skip to main content
Glama
by alucardeht
screenshot.js4.69 kB
import axios from "axios"; import sharp from "sharp"; export async function getScreenshot(ctx, fileKey, pageName, frameName, scale, maxDimension) { const { chunker, figmaClient } = ctx; const file = await figmaClient.getFile(fileKey, 2); const page = figmaClient.findPageByName(file, pageName); if (!page) throw new Error(`Page "${pageName}" not found`); const frame = figmaClient.findFrameByName(page, frameName); if (!frame) throw new Error(`Frame "${frameName}" not found`); const width = (frame.absoluteBoundingBox?.width || 0) * scale; const height = (frame.absoluteBoundingBox?.height || 0) * scale; const imageData = await figmaClient.getImage(fileKey, frame.id, "png", scale); const imageUrl = imageData.images[frame.id]; if (!imageUrl) throw new Error("Failed to generate image"); const response = await axios.get(imageUrl, { responseType: "arraybuffer" }); if (width > maxDimension || height > maxDimension) { const tiles = await segmentImage(response.data, { width, height, maxDimension, }); const navInfo = chunker.wrapResponse( { frame: frame.name, width: Math.round(width), height: Math.round(height), tiles: tiles.length }, { step: `Screenshot segmented into ${tiles.length} tiles`, progress: "Complete", nextStep: "Use get_frame_info for structure details", } ); return { content: [ { type: "text", text: JSON.stringify(navInfo, null, 2) }, ...tiles.map((tile) => ({ type: "image", data: tile.data, mimeType: "image/png", })), ], }; } const navInfo = chunker.wrapResponse( { frame: frame.name, width: Math.round(width), height: Math.round(height) }, { step: "Screenshot captured", progress: "Complete", nextStep: "Use get_frame_info for structure, or extract_assets for icons/images", } ); return { content: [ { type: "text", text: JSON.stringify(navInfo, null, 2) }, { type: "image", data: Buffer.from(response.data).toString("base64"), mimeType: "image/png", }, ], }; } export async function applyTransparency(buffer, regions, imageHeight) { if (!regions || regions.length === 0) return buffer; const image = sharp(buffer); const metadata = await image.metadata(); const { width, height } = metadata; let maskBuffer = Buffer.alloc(width * height, 255); for (const region of regions) { const yStart = Math.max(0, Math.round(region.y_start)); const yEnd = Math.min(height, Math.round(region.y_end)); for (let y = yStart; y < yEnd; y++) { for (let x = 0; x < width; x++) { maskBuffer[y * width + x] = 0; } } } const mask = sharp(maskBuffer, { raw: { width, height, channels: 1 }, }); return image.ensureAlpha().composite([ { input: await mask.toBuffer(), blend: 'dest-out', }, ]).png().toBuffer(); } export async function cropToSection(buffer, sectionBounds, fullHeight) { const image = sharp(buffer); const metadata = await image.metadata(); const yStart = Math.round(sectionBounds.y_start); const yEnd = Math.round(sectionBounds.y_end); const extractHeight = Math.max(1, yEnd - yStart); return image .extract({ left: 0, top: yStart, width: metadata.width, height: extractHeight, }) .png() .toBuffer(); } async function segmentImage(buffer, options) { const { width, height, maxDimension = 4096, transparencyRegions = [], mode = 'tiles', } = options; let processedBuffer = buffer; if (transparencyRegions.length > 0) { processedBuffer = await applyTransparency(buffer, transparencyRegions, height); } const image = sharp(processedBuffer); const metadata = await image.metadata(); const cols = Math.ceil(metadata.width / maxDimension); const rows = Math.ceil(metadata.height / maxDimension); const tileWidth = Math.ceil(metadata.width / cols); const tileHeight = Math.ceil(metadata.height / rows); const tiles = []; for (let row = 0; row < rows; row++) { for (let col = 0; col < cols; col++) { const left = col * tileWidth; const top = row * tileHeight; const extractWidth = Math.min(tileWidth, metadata.width - left); const extractHeight = Math.min(tileHeight, metadata.height - top); const tile = await sharp(processedBuffer) .extract({ left, top, width: extractWidth, height: extractHeight }) .png() .toBuffer(); tiles.push({ row, col, data: tile.toString("base64"), }); } } return tiles; }

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/alucardeht/figma-mcp'

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