Skip to main content
Glama

convert_image

Convert images between formats like PNG, JPG, WebP, GIF, BMP, TIFF, SVG, and ICO. Resize images while maintaining aspect ratio and adjust compression quality for supported formats.

Instructions

将图片转换为指定格式

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
input_pathNo源图片文件路径(与input_data二选一)
input_dataNo图片数据(Buffer或base64字符串,与input_path二选一)
input_filenameNo原始文件名,用于确定格式(使用input_data时建议提供)
output_formatYes目标格式(png/jpg/jpeg/gif/bmp/tiff/webp/svg/ico等)
qualityNo压缩质量(1-100,仅适用于有损格式)
widthNo目标宽度(像素)
heightNo目标高度(像素)
maintain_aspect_ratioNo保持宽高比
output_pathNo输出文件路径(可选,默认自动生成)

Implementation Reference

  • src/index.ts:60-110 (registration)
    Registration of the 'convert_image' tool in the ListTools handler, defining name, description, and input schema.
    {
      name: 'convert_image',
      description: '将图片转换为指定格式',
      inputSchema: {
        type: 'object',
        properties: {
          input_path: {
            type: 'string',
            description: '源图片文件路径(与input_data二选一)'
          },
          input_data: {
            type: 'string',
            description: '图片数据(Buffer或base64字符串,与input_path二选一)'
          },
          input_filename: {
            type: 'string',
            description: '原始文件名,用于确定格式(使用input_data时建议提供)'
          },
          output_format: {
            type: 'string',
            description: '目标格式(png/jpg/jpeg/gif/bmp/tiff/webp/svg/ico等)'
          },
          quality: {
            type: 'number',
            minimum: 1,
            maximum: 100,
            description: '压缩质量(1-100,仅适用于有损格式)'
          },
          width: {
            type: 'number',
            minimum: 1,
            description: '目标宽度(像素)'
          },
          height: {
            type: 'number',
            minimum: 1,
            description: '目标高度(像素)'
          },
          maintain_aspect_ratio: {
            type: 'boolean',
            default: true,
            description: '保持宽高比'
          },
          output_path: {
            type: 'string',
            description: '输出文件路径(可选,默认自动生成)'
          }
        },
        required: ['output_format']
      }
    },
  • Zod schema for validating arguments to the convert_image tool.
    const ConvertImageArgsSchema = z.object({
      input_path: z.string().optional().describe('源图片文件路径'),
      input_data: z.string().optional().describe('图片数据(Buffer或base64字符串)'),
      input_filename: z.string().optional().describe('原始文件名,用于确定格式'),
      output_format: z.string().describe('目标格式(png/jpg/jpeg/gif/bmp/tiff/webp/svg/ico等)'),
      quality: z.number().min(1).max(100).optional().describe('压缩质量(1-100,仅适用于有损格式)'),
      width: z.number().positive().optional().describe('目标宽度(像素)'),
      height: z.number().positive().optional().describe('目标高度(像素)'),
      maintain_aspect_ratio: z.boolean().default(true).describe('保持宽高比'),
      output_path: z.string().optional().describe('输出文件路径(可选,默认自动生成)')
    });
  • MCP CallTool request handler case that validates args and delegates to ImageConverter.convertImage.
    case 'convert_image': {
      const validatedArgs = ConvertImageArgsSchema.parse(args);
      const result = await this.converter.convertImage(validatedArgs);
      return {
        content: [
          {
            type: 'text',
            text: `图片转换成功!\n输出文件:${result.output_path}\n文件大小:${result.file_size} bytes\n图片尺寸:${result.dimensions.width}x${result.dimensions.height}\n格式:${result.format}`
          }
        ]
      };
    }
  • Primary handler function implementing the image conversion logic, supporting various input/output formats with resizing and quality options.
    async convertImage(options: ConvertImageOptions): Promise<ConvertResult> {
      const { input_path, input_data, input_filename, output_format, quality, width, height, maintain_aspect_ratio = true, output_path } = options;
    
      let inputBuffer: Buffer;
      let inputFormat: string;
    
      // 处理不同的输入方式
      if (input_data) {
        // 处理上传的文件数据
        if (typeof input_data === 'string') {
          // 处理base64数据
          const base64Data = input_data.includes(',') ? input_data.split(',')[1] : input_data;
          inputBuffer = Buffer.from(base64Data, 'base64');
        } else {
          // 处理Buffer数据
          inputBuffer = input_data;
        }
        
        // 从文件名获取格式
        if (input_filename) {
          inputFormat = this.getFileFormat(input_filename);
        } else {
          // 尝试从Buffer检测格式
          inputFormat = await this.detectFormatFromBuffer(inputBuffer);
        }
      } else if (input_path) {
        // 处理文件路径
        try {
          await fs.access(input_path);
          inputBuffer = await fs.readFile(input_path);
          inputFormat = this.getFileFormat(input_path);
        } catch {
          throw new Error(`输入文件不存在: ${input_path}`);
        }
      } else {
        throw new Error('必须提供input_path或input_data参数');
      }
    
      // 验证输出格式
      const normalizedFormat = output_format.toLowerCase().replace('.', '');
      if (!this.supportedOutputFormats.includes(normalizedFormat)) {
        throw new Error(`不支持的输出格式: ${output_format}`);
      }
    
      // 生成输出路径
      const finalOutputPath = output_path || this.generateOutputPath(
        input_path || input_filename || `uploaded_image.${inputFormat}`, 
        normalizedFormat
      );
    
      // 确保输出目录存在
      const outputDir = path.dirname(finalOutputPath);
      await fs.mkdir(outputDir, { recursive: true });
      
      // 验证输入格式是否支持
      if (!this.supportedInputFormats.includes(inputFormat)) {
        throw new Error(`不支持的输入格式: ${inputFormat}`);
      }
    
      // 对于特殊格式的处理说明
      if (inputFormat === 'heic' || inputFormat === 'heif') {
        try {
          // Sharp 0.32+ 支持HEIC,但需要libvips支持
          await sharp(inputBuffer).metadata();
        } catch {
          throw new Error(`HEIC/HEIF格式需要系统支持libvips,请先转换为JPG或PNG格式`);
        }
      } else if (inputFormat === 'psd') {
        throw new Error(`PSD格式暂不支持,请使用Photoshop导出为JPG或PNG格式`);
      }
    
      try {
        let sharpInstance = sharp(inputBuffer);
    
        // 调整尺寸
        if (width || height) {
          const resizeOptions: sharp.ResizeOptions = {
            fit: maintain_aspect_ratio ? 'inside' : 'fill',
            withoutEnlargement: false
          };
    
          if (width && height) {
            sharpInstance = sharpInstance.resize(width, height, resizeOptions);
          } else if (width) {
            sharpInstance = sharpInstance.resize(width, undefined, resizeOptions);
          } else if (height) {
            sharpInstance = sharpInstance.resize(undefined, height, resizeOptions);
          }
        }
    
        // 根据格式设置输出选项
        switch (normalizedFormat) {
          case 'jpg':
          case 'jpeg':
            sharpInstance = sharpInstance.jpeg({ quality: quality || 90 });
            break;
          case 'png':
            sharpInstance = sharpInstance.png({ quality: quality || 90 });
            break;
          case 'webp':
            sharpInstance = sharpInstance.webp({ quality: quality || 90 });
            break;
          case 'gif':
            // Sharp不直接支持GIF输出,使用Jimp
            return await this.convertWithJimp(inputBuffer, finalOutputPath, normalizedFormat, { width, height, quality });
          case 'bmp':
            // 使用Jimp处理BMP
            return await this.convertWithJimp(inputBuffer, finalOutputPath, normalizedFormat, { width, height, quality });
          case 'tiff':
            sharpInstance = sharpInstance.tiff({ quality: quality || 90 });
            break;
          case 'avif':
            sharpInstance = sharpInstance.avif({ quality: quality || 90 });
            break;
          case 'ico':
            // ICO格式需要特殊处理
            return await this.convertToIco(inputBuffer, finalOutputPath, { width: width || 32, height: height || 32 });
          case 'svg':
            // SVG格式转换
            return await this.convertToSvg(inputBuffer, finalOutputPath, { width, height });
          default:
            throw new Error(`暂不支持转换为格式: ${normalizedFormat}`);
        }
    
        // 执行转换
        await sharpInstance.toFile(finalOutputPath);
    
        // 获取结果信息
        const stats = await fs.stat(finalOutputPath);
        const metadata = await sharp(finalOutputPath).metadata();
    
        return {
          output_path: finalOutputPath,
          file_size: stats.size,
          dimensions: {
            width: metadata.width || 0,
            height: metadata.height || 0
          },
          format: normalizedFormat
        };
    
      } catch (error) {
        throw new Error(`图片转换失败: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
  • TypeScript interface defining the options for the convertImage function.
    export interface ConvertImageOptions {
      input_path?: string;
      input_data?: Buffer | string; // 支持Buffer数据或base64字符串
      input_filename?: string; // 原始文件名,用于确定格式
      output_format: string;
      quality?: number;
      width?: number;
      height?: number;
      maintain_aspect_ratio?: boolean;
      output_path?: string;
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure but offers minimal information. It states the conversion action but doesn't mention whether this is a read-only operation, what permissions might be needed, whether original files are modified, what happens with invalid inputs, or what the output looks like. For a tool with 9 parameters and no annotations, this is a significant gap in behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with just one sentence ('将图片转换为指定格式'), which efficiently states the core purpose without any wasted words. It's appropriately sized for a tool where parameter details are fully covered in the schema, making every word earn its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (9 parameters, format conversion with quality/resizing options) and absence of both annotations and output schema, the description is insufficiently complete. It doesn't explain what the tool returns (converted image data? file path? success status?), doesn't mention error conditions, and provides no behavioral context for a potentially destructive operation. The 100% schema coverage helps but doesn't compensate for missing output and behavioral information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 9 parameters thoroughly. The description adds no additional parameter semantics beyond what's in the schema - it doesn't explain parameter interactions, default behaviors, or practical usage examples. With complete schema coverage, the baseline score of 3 is appropriate as the description doesn't compensate but doesn't need to.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose as converting images to specified formats ('将图片转换为指定格式'), which is a specific verb+resource combination. It distinguishes from siblings like batch_convert_images (batch processing), get_image_info (metadata retrieval), and list_supported_formats (format listing) by focusing on single image conversion. However, it doesn't explicitly mention the single-image scope versus batch processing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. There's no mention of when to choose convert_image over batch_convert_images for multiple images, or when to use get_image_info for metadata instead. The only implied usage is for format conversion, but no explicit context or exclusion criteria are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/pickstar-2002/image-mcp'

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