image-processing について
一般的な画像加工を `img-process` コマンドラインツールで行い、独自の処理には Pillow を使うスキルです。開発者やデザイナーによる画像素材の準備、最適化、一括処理に役立ちます。
主な機能
- 01画像のリサイズ、変換、トリミング
- 02サムネイルと OG カードの生成
- 03素材の最適化と一括処理
- 04カスタム Pillow スクリプトの生成
- 05画像形式と保存方法のガイド
活用シーン
- 01ロゴやアイコンの余白を整理
- 02圧縮したウェブ用メイン画像を準備
- 03ソーシャル向けプレビューカードを作成
- 04画像フォルダーを一括変換またはリサイズ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill image-processingインストール後、Claude Code で/image-processingを入力して読み込まれたか確認します。
詳細
画像処理
一般的な操作には、bin/に同梱されているimg-processを使用します。複雑なワークフローやカスタムワークフローには、ユーザーの環境に合わせたPillowスクリプトを生成します。
クイックリファレンス — img-process CLI
img-process resize hero.png --width 1920
img-process convert logo.png --format webp
img-process trim logo-raw.jpg -o logo-clean.png --padding 10
img-process thumbnail photo.jpg --size 200
img-process optimise hero.jpg --quality 85 --max-width 1920
img-process og-card -o og.png --title "My App" --subtitle "Built for speed"
img-process batch ./images --action convert --format webp -o ./optimised
img-processを使用する場合:操作が標準的なもの(サイズ変更、変換、余白のトリミング、サムネイル作成、最適化、OGカード作成、一括処理)の場合です。スクリプトを毎回生成する必要がなく、より高速です。
カスタムスクリプトを生成する場合:img-processでは対応できないロジックが必要な操作(複数画像の合成、透かし、複雑なテキストレイアウト、条件付き処理)の場合です。
前提条件
img-processとカスタムスクリプトのどちらにもPillowが必要です。
pip install Pillow
Pillowを利用できない場合は、次の代替手段を使用してください。
| 代替手段 | プラットフォーム | インストール | 最適な用途 |
|---|---|---|---|
sips | macOS(標準搭載) | 不要 | サイズ変更、変換(トリミング/OGカード作成には非対応) |
sharp | Node.js | npm install sharp | 全機能、高パフォーマンス |
ffmpeg | クロスプラットフォーム | brew install ffmpeg | サイズ変更、変換 |
出力形式ガイド
| 用途 | 形式 | 理由 |
|---|---|---|
| 写真、ヒーロー画像 | WebP | 最高の圧縮率、幅広いブラウザー対応 |
| ロゴ、アイコン(透過が必要) | PNG | ロスレス、アルファチャンネル対応 |
| 古いブラウザー向けのフォールバック | JPG | 汎用的に対応 |
| サムネイル | WebPまたはJPG | ファイルサイズの小ささを優先 |
| OGカード | PNG | ソーシャルプラットフォームではPNGが最適 |
基本パターン
形式別の品質設定で保存する
形式によって必要な保存パラメーターは異なります。RGBAからJPGへの合成は必ず処理してください。JPGは透過に対応していないため、先に白い背景へ合成します。
from PIL import Image
import os
def save_image(img, output_path, quality=None):
os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
kwargs = {}
ext = output_path.lower().rsplit(".", 1)[-1]
if ext == "webp":
kwargs = {"quality": quality or 85, "method": 6}
elif ext in ("jpg", "jpeg"):
kwargs = {"quality": quality or 90, "optimize": True}
# RGBA → RGB: composite onto white background
if img.mode == "RGBA":
bg = Image.new("RGB", img.size, (255, 255, 255))
bg.paste(img, mask=img.split()[3])
img = bg
elif ext == "png":
kwargs = {"optimize": True}
img.save(output_path, **kwargs)
アスペクト比を維持してサイズを変更する
幅または高さの一方だけが指定された場合は、アスペクト比からもう一方を計算します。高品質に縮小するにはImage.LANCZOSを使用します。
def resize_image(img, width=None, height=None):
if width and height:
return img.resize((width, height), Image.LANCZOS)
elif width:
ratio = width / img.width
return img.resize((width, int(img.height * ratio)), Image.LANCZOS)
elif height:
ratio = height / img.height
return img.resize((int(img.width * ratio), height), Image.LANCZOS)
return img
余白をトリミングする(自動クロップ)
ロゴやアイコンの周囲にある余白を削除します。まずRGBAに変換し、次にgetbbox()を使用してコンテンツの境界を取得します。
img = Image.open(input_path)
if img.mode != "RGBA":
img = img.convert("RGBA")
bbox = img.getbbox() # Bounding box of non-zero pixels
if bbox:
img = img.crop(bbox)
サムネイル
アスペクト比を維持しながら、最大寸法内に収めます。
img.thumbnail((size, size), Image.LANCZOS)
Web向けに最適化する
サイズ変更と圧縮を一度に行います。最高の圧縮率を得るにはWebPに変換します。一般的な設定は、幅1920、品質85です。
クロスプラットフォームでフォントを検出する
システムのフォントパスはOSによって異なります。複数のパスを試し、見つからない場合はPillowのデフォルトにフォールバックします。Linuxでは、fc-listでフォントを動的に検出できます。
from PIL import ImageFont
def get_font(size):
font_paths = [
# macOS
"/System/Library/Fonts/Helvetica.ttc",
"/System/Library/Fonts/SFNSText.ttf",
# Linux
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
# Windows
"C:/Windows/Fonts/arial.ttf",
]
for path in font_paths:
if os.path.exists(path):
try:
return ImageFont.truetype(path, size)
except Exception:
continue
return ImageFont.load_default()
OGカードを生成する(1200x630)
背景画像または単色の背景にテキストを合成します。テキストを読みやすくするため、半透明のオーバーレイを適用します。テキストは水平方向の中央に配置します。
from PIL import Image, ImageDraw, ImageFont
width, height = 1200, 630
# Background: image or solid colour
if background_path:
img = Image.open(background_path).resize((width, height), Image.LANCZOS)
else:
img = Image.new("RGB", (width, height), bg_color or "#1a1a2e")
# Semi-transparent overlay for text readability
overlay = Image.new("RGBA", (width, height), (0, 0, 0, 128))
img = img.convert("RGBA")
img = Image.alpha_composite(img, overlay)
draw = ImageDraw.Draw(img)
font_title = get_font(48)
font_sub = get_font(24)
# Centre title
if title:
bbox = draw.textbbox((0, 0), title, font=font_title)
tw = bbox[2] - bbox[0]
draw.text(((width - tw) // 2, height // 2 - 60), title, fill="white", font=font_title)
img = img.convert("RGB")
一般的なワークフロー
ロゴを整える(白背景のクライアント提供JPG)
img-process trim logo-raw.jpg -o logo-trimmed.png --padding 10
img-process thumbnail logo-trimmed.png --size 512 -o favicon-512.png
本番環境向けにヒーロー画像を準備する
img-process optimise hero.jpg --max-width 1920 --quality 85
# Outputs hero.webp — resized and compressed
一括処理する
img-process batch ./raw-images --action convert --format webp --quality 85 -o ./optimised
img-process batch ./photos --action resize --width 800 -o ./thumbnails
Gemini Image Genとのパイプライン
gemini-image-genスキルで画像を生成し、その後に処理します。
# After generating with Gemini (raw PNG output):
img-process optimise generated-image.png --max-width 1920 --quality 85
# Or batch process all generated images:
img-process batch ./generated --action optimise -o ./production