create_palette_png
Generate PNG images of color palettes with customizable layouts, styles, and resolutions for design workflows.
Instructions
Generate high-quality PNG images of color palettes with professional layout and styling options
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| palette | Yes | Array of colors in any supported format | |
| layout | No | Layout arrangement of color swatches | horizontal |
| resolution | No | Image resolution in DPI | |
| dimensions | No | Custom dimensions [width, height] in pixels | |
| style | No | Visual style of color swatches | flat |
| labels | No | Show color values as labels | |
| label_style | No | Style of color labels | minimal |
| background | No | Background color or transparency | white |
| background_color | No | Custom background color (required if background is "custom") | |
| margin | No | Margin around the palette in pixels |
Implementation Reference
- src/tools/create-palette-png.ts:323-458 (handler)The core handler function that executes the tool logic: validates input using Joi schema, checks color validity, generates SVG palette visualization, creates dual light/dark PNGs using dualBackgroundPNGGenerator, saves files via enhancedFileOutputManager, and returns structured FileBasedToolResponse.async function createPalettePng( params: unknown ): Promise<FileBasedToolResponse | ErrorResponse> { const startTime = Date.now(); try { // Initialize file output manager await enhancedFileOutputManager.initialize(); // Validate parameters const { error, value } = palettePngSchema.validate(params); if (error) { return createErrorResponse( 'create_palette_png', 'INVALID_PARAMETERS', `Invalid parameters: ${error.details.map(d => d.message).join(', ')}`, startTime, { details: error.details, suggestions: [ 'Check the parameter format', 'Ensure all required fields are provided', ], } ); } const validatedParams = value as PalettePngParams; // Validate colors const invalidColors: string[] = []; validatedParams.palette.forEach((colorStr, index) => { try { const color = colord(colorStr); if (!color.isValid()) { invalidColors.push(`${colorStr} at index ${index}`); } } catch { invalidColors.push(`${colorStr} at index ${index}`); } }); if (invalidColors.length > 0) { return createErrorResponse( 'create_palette_png', 'INVALID_COLOR_FORMAT', `Invalid colors found: ${invalidColors.join(', ')}`, startTime, { details: { invalidColors }, suggestions: [ 'Use valid color formats like #FF0000, rgb(255,0,0), or hsl(0,100%,50%)', ], } ); } // Generate dual background PNGs const pngResult = await generatePalettePng(validatedParams); // Save files using enhanced file output manager const visualizationResult = await enhancedFileOutputManager.saveDualPNGVisualization( pngResult.lightBuffer, pngResult.darkBuffer, { toolName: 'create_palette_png', description: `Color palette with ${validatedParams.palette.length} colors`, customName: `palette-${validatedParams.layout}`, dimensions: pngResult.dimensions, resolution: validatedParams.resolution || 150, colorSpace: 'sRGB', parameters: validatedParams as unknown as Record<string, unknown>, } ); const data: PalettePngData = { palette: validatedParams.palette, layout: validatedParams.layout || 'horizontal', dimensions: pngResult.dimensions, resolution: validatedParams.resolution || 150, light_file_size: pngResult.lightBuffer.length, dark_file_size: pngResult.darkBuffer.length, total_file_size: pngResult.lightBuffer.length + pngResult.darkBuffer.length, color_count: validatedParams.palette.length, }; const executionTime = Date.now() - startTime; return createFileBasedSuccessResponse( 'create_palette_png', data, executionTime, visualizationResult, { colorSpaceUsed: 'sRGB', accessibilityNotes: [ 'Light background variant optimized for light themes', 'Dark background variant optimized for dark themes', ], recommendations: [ 'Use high resolution (300+ DPI) for print applications', 'Light variant works best on light backgrounds', 'Dark variant works best on dark backgrounds', 'Grid layout works best for large palettes', ], } ); } catch (error) { logger.error('Error generating palette PNG', { error: error as Error }); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; const errorCode = errorMessage.includes('memory limits') || errorMessage.includes('exceeds') ? 'MEMORY_LIMIT_ERROR' : 'PNG_GENERATION_ERROR'; return createErrorResponse( 'create_palette_png', errorCode, errorMessage, startTime, { details: { error: errorMessage, }, suggestions: [ 'Check image dimensions and color formats', 'Ensure sufficient memory is available', 'Try reducing image dimensions or resolution', ], } ); } }
- Joi validation schema for tool input parameters including palette array, layout, resolution, dimensions, style options, labels, background settings, and margins.const palettePngSchema = Joi.object({ palette: Joi.array() .items(Joi.string().required()) .min(1) .max(100) .required() .messages({ 'array.min': 'Palette must contain at least 1 color', 'array.max': 'Palette cannot contain more than 100 colors', }), layout: Joi.string() .valid('horizontal', 'vertical', 'grid', 'circular') .default('horizontal'), resolution: Joi.number().valid(72, 150, 300, 600).default(150), dimensions: Joi.array() .items(Joi.number().integer().min(100).max(20000)) .length(2) .optional(), style: Joi.string() .valid('flat', 'gradient', 'material', 'glossy', 'fabric', 'paper') .default('flat'), labels: Joi.boolean().default(true), label_style: Joi.string() .valid('minimal', 'detailed', 'branded') .default('minimal'), background: Joi.string() .valid('transparent', 'white', 'black', 'custom') .default('white'), background_color: Joi.string().when('background', { is: 'custom', then: Joi.required(), otherwise: Joi.optional(), }), margin: Joi.number().integer().min(0).max(100).default(20), });
- src/tools/index.ts:80-125 (registration)Import of createPalettePngTool and registration in the central ToolRegistry singleton instance.import { createPalettePngTool } from './create-palette-png'; import { createGradientPngTool } from './create-gradient-png'; import { createColorComparisonPngTool } from './create-color-comparison-png'; // Import and register theme generation tools import { generateThemeTool } from './generate-theme'; import { generateSemanticColorsTool } from './generate-semantic-colors'; // Import color utility tools import { mixColorsTool } from './mix-colors'; import { generateColorVariationsTool } from './generate-color-variations'; import { sortColorsTool } from './sort-colors'; import { analyzeColorCollectionTool } from './analyze-color-collection'; // Import export format tools import { exportCssTool } from './export-css'; import { exportScssTool } from './export-scss'; import { exportTailwindTool } from './export-tailwind'; import { exportJsonTool } from './export-json'; // Register conversion tools toolRegistry.registerTool(convertColorTool); // Register analysis tools toolRegistry.registerTool(analyzeColorTool); toolRegistry.registerTool(checkContrastTool); // Register accessibility tools toolRegistry.registerTool(simulateColorblindnessTool); toolRegistry.registerTool(optimizeForAccessibilityTool); // Register palette generation tools toolRegistry.registerTool(generateHarmonyPaletteTool); // Register gradient generation tools toolRegistry.registerTool(generateLinearGradientTool); toolRegistry.registerTool(generateRadialGradientTool); // Register visualization tools toolRegistry.registerTool(createPaletteHtmlTool); toolRegistry.registerTool(createColorWheelHtmlTool); toolRegistry.registerTool(createGradientHtmlTool); toolRegistry.registerTool(createThemePreviewHtmlTool); // Register PNG generation tools toolRegistry.registerTool(createPalettePngTool);
- src/validation/schemas.ts:214-237 (schema)Exported Joi schema for create_palette_png tool parameters, providing global validation reference.export const createPalettePngSchema = Joi.object({ palette: colorArraySchema.required(), layout: Joi.string() .valid('horizontal', 'vertical', 'grid', 'circular') .default('horizontal'), resolution: Joi.number().valid(72, 150, 300, 600).default(150), dimensions: dimensionSchema.optional(), style: Joi.string() .valid('flat', 'gradient', 'material', 'glossy', 'fabric', 'paper') .default('flat'), labels: Joi.boolean().default(true), label_style: Joi.string() .valid('minimal', 'detailed', 'branded') .default('minimal'), background: Joi.string() .valid('transparent', 'white', 'black', 'custom') .default('white'), background_color: colorSchema.when('background', { is: 'custom', then: Joi.required(), otherwise: Joi.optional(), }), margin: Joi.number().min(0).max(100).default(20), }).required();
- Helper function that orchestrates PNG generation: dimension calculation, SVG creation, dual-background PNG rendering, and quality validation.async function generatePalettePng(params: PalettePngParams): Promise<{ lightBuffer: Buffer; darkBuffer: Buffer; dimensions: [number, number]; }> { const { palette, layout = 'horizontal', dimensions, style = 'flat', labels = true, label_style = 'minimal', margin = 20, } = params; // Calculate dimensions const [width, height] = calculateDimensions( palette.length, layout, dimensions ); // Create base SVG content (without background) const svgContent = createPaletteSvg( palette, layout, [width, height], style, labels, label_style, 'transparent', // Always use transparent for base SVG undefined, margin ); // Generate dual background PNGs const result = await dualBackgroundPNGGenerator.generateDualPNG( svgContent, [width, height], { lightBackground: '#ffffff', darkBackground: '#1a1a1a', intelligentTextColor: true, quality: 'standard', } ); // Validate visual quality const qualityCheck = await dualBackgroundPNGGenerator.validateVisualQuality( result.lightBuffer, result.darkBuffer, [width, height] ); if (!qualityCheck.valid) { logger.warn('PNG quality validation issues detected', { issues: qualityCheck.issues, }); } return { lightBuffer: result.lightBuffer, darkBuffer: result.darkBuffer, dimensions: [width, height], }; }