Use Cases

Claude Codeで画像処理を自動化する方法

Claude Codeを使ってSharpによる画像リサイズ・変換・最適化を自動化。バッチ処理やWebP変換の実践コード付き。

画像処理の自動化にClaude Codeを活用する

Webアプリでは画像のリサイズ、フォーマット変換、最適化が頻繁に必要です。Claude Codeを使えば、Sharpライブラリを活用した画像処理パイプラインを効率的に構築できます。

基本:画像リサイズと最適化

本記事のコード例は Sharp v0.33+(2025年時点の安定版) を前提にしています。Sharp v0.32以降では、.withMetadata()呼ばない限り EXIFなどのメタデータはデフォルトで出力画像から除去されます。「メタデータ削除用メソッド」は存在しないため、何もしない=削除されると覚えておきましょう。

> Sharpを使って画像のリサイズ・WebP変換・メタデータ削除を行うユーティリティを作って。
import sharp from "sharp";
import path from "path";

interface ProcessOptions {
  width?: number;
  height?: number;
  quality?: number;
  format?: "webp" | "avif" | "jpeg" | "png";
  /** trueの場合、EXIFのorientationのみ保持(回転情報のみ維持) */
  keepOrientation?: boolean;
}

export async function processImage(
  inputPath: string,
  outputDir: string,
  options: ProcessOptions = {}
) {
  const {
    width = 1200,
    height,
    quality = 80,
    format = "webp",
    keepOrientation = false,
  } = options;
  const filename = path.basename(inputPath, path.extname(inputPath));
  const outputPath = path.join(outputDir, `${filename}.${format}`);

  // .rotate() でEXIFのorientationに従って自動回転してから、
  // メタデータを除去した出力を作る(デフォルトでメタデータは破棄される)。
  let pipeline = sharp(inputPath)
    .rotate()
    .resize(width, height, {
      fit: "inside",
      withoutEnlargement: true,
    });

  // 特定のメタデータだけ保持したい場合は .withMetadata() を明示的に呼ぶ
  if (keepOrientation) {
    pipeline = pipeline.withMetadata({ orientation: 1 });
  }

  switch (format) {
    case "webp":
      pipeline = pipeline.webp({ quality });
      break;
    case "avif":
      pipeline = pipeline.avif({ quality });
      break;
    case "jpeg":
      pipeline = pipeline.jpeg({ quality, mozjpeg: true });
      break;
    case "png":
      pipeline = pipeline.png({ compressionLevel: 9 });
      break;
  }

  const info = await pipeline.toFile(outputPath);

  return {
    outputPath,
    width: info.width,
    height: info.height,
    size: info.size,
  };
}

レスポンシブ画像の一括生成

複数サイズの画像を一度に生成して、<picture> 要素やsrcsetに対応させます。

interface ResponsiveSize {
  width: number;
  suffix: string;
}

const RESPONSIVE_SIZES: ResponsiveSize[] = [
  { width: 320, suffix: "sm" },
  { width: 640, suffix: "md" },
  { width: 1024, suffix: "lg" },
  { width: 1920, suffix: "xl" },
];

export async function generateResponsiveImages(
  inputPath: string,
  outputDir: string
) {
  const filename = path.basename(inputPath, path.extname(inputPath));
  const results = [];

  for (const size of RESPONSIVE_SIZES) {
    const outputPath = path.join(outputDir, `${filename}-${size.suffix}.webp`);

    const info = await sharp(inputPath)
      .resize(size.width, null, {
        fit: "inside",
        withoutEnlargement: true,
      })
      .webp({ quality: 80 })
      .toFile(outputPath);

    results.push({
      path: outputPath,
      width: info.width,
      height: info.height,
      size: info.size,
    });
  }

  return results;
}

バッチ処理スクリプト

フォルダ内の画像を一括処理するCLIスクリプトです。

import fs from "fs/promises";
import path from "path";
import { processImage } from "./image-processor";

async function batchProcess(inputDir: string, outputDir: string) {
  await fs.mkdir(outputDir, { recursive: true });

  const files = await fs.readdir(inputDir);
  const imageFiles = files.filter((f) =>
    /\.(jpg|jpeg|png|gif|bmp|tiff)$/i.test(f)
  );

  console.log(`${imageFiles.length}件の画像を処理します...`);

  const results = await Promise.allSettled(
    imageFiles.map(async (file) => {
      const inputPath = path.join(inputDir, file);
      const result = await processImage(inputPath, outputDir, {
        width: 1200,
        quality: 80,
        format: "webp",
      });

      const originalSize = (await fs.stat(inputPath)).size;
      const reduction = ((1 - result.size / originalSize) * 100).toFixed(1);
      console.log(`  ${file} → ${path.basename(result.outputPath)} (${reduction}% 削減)`);
      return result;
    })
  );

  const succeeded = results.filter((r) => r.status === "fulfilled").length;
  const failed = results.filter((r) => r.status === "rejected").length;
  console.log(`完了: 成功 ${succeeded}件, 失敗 ${failed}件`);
}

// 実行
batchProcess("./images/raw", "./images/optimized");

OGP画像の動的生成

ブログ記事のOGP画像を自動生成する機能も作れます。

import sharp from "sharp";

export async function generateOgImage(title: string, outputPath: string) {
  const width = 1200;
  const height = 630;

  const svgText = `
    <svg width="${width}" height="${height}">
      <rect width="100%" height="100%" fill="#1e293b"/>
      <text x="50%" y="45%" text-anchor="middle" fill="white"
        font-size="48" font-family="sans-serif" font-weight="bold">
        ${escapeXml(title.length > 30 ? title.slice(0, 30) + "..." : title)}
      </text>
      <text x="50%" y="65%" text-anchor="middle" fill="#94a3b8"
        font-size="24" font-family="sans-serif">
        ClaudeCodeLab
      </text>
    </svg>
  `;

  await sharp(Buffer.from(svgText))
    .resize(width, height)
    .png()
    .toFile(outputPath);
}

function escapeXml(str: string) {
  return str.replace(/[<>&'"]/g, (c) =>
    ({ "<": "&lt;", ">": "&gt;", "&": "&amp;", "'": "&apos;", '"': "&quot;" })[c] || c
  );
}

画像処理と組み合わせて使えるPDF生成についてはPDF生成機能をご覧ください。Claude Codeの基本的な使い方は入門ガイドを参照してください。

まとめ

Claude Codeを使えば、画像リサイズ、フォーマット変換、レスポンシブ対応、OGP生成まで、画像処理に関する機能を短時間で実装できます。要件を自然言語で伝えるだけで、Sharpの複雑なAPIを適切に使ったコードが得られます。

詳しくはClaude Code公式ドキュメントをご覧ください。

#Claude Code #画像処理 #Sharp #最適化 #自動化
無料プレゼント

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。

Masa

この記事を書いた人

Masa

現役DX室長|Claude Code でゼロから多言語AI技術メディア運営中。実務直結の自動化、AI開発相談・研修受付中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。