jpskill.com
🎨 デザイン コミュニティ

web-files-image-handling

Webブラウザ上で画像ファイルを扱い、プレビュー表示、サイズ変更、圧縮、向き調整、形式変換などを行い、メモリを効率的に管理することで、快適な画像処理を実現するSkill。

📜 元の英語説明(参考)

Client-side image handling - preview generation, Canvas API resizing, compression, EXIF orientation, format conversion, memory management with object URL cleanup

🇯🇵 日本人クリエイター向け解説

一言でいうと

Webブラウザ上で画像ファイルを扱い、プレビュー表示、サイズ変更、圧縮、向き調整、形式変換などを行い、メモリを効率的に管理することで、快適な画像処理を実現するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o web-files-image-handling.zip https://jpskill.com/download/10278.zip && unzip -o web-files-image-handling.zip && rm web-files-image-handling.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10278.zip -OutFile "$d\web-files-image-handling.zip"; Expand-Archive "$d\web-files-image-handling.zip" -DestinationPath $d -Force; ri "$d\web-files-image-handling.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して web-files-image-handling.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → web-files-image-handling フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

画像処理パターン

クイックガイド: 画像プレビューには URL.createObjectURL() を使用します(最も効率的です)。アップロード前に Canvas API でサイズ変更/圧縮を行います。メモリリークを防ぐため、常に URL.revokeObjectURL() でオブジェクト URL をクリーンアップしてください。モバイル写真の EXIF 方向の処理は、アップロードのために処理する場合のみ行ってください(最新のブラウザは表示のために自動的に回転します)。大幅な縮小を行う場合は、品質を維持するためにステップダウンスケーリングを使用してください。


<critical_requirements>

重要: この Skill を使用する前に

すべてのコードは CLAUDE.md のプロジェクト規約に従う必要があります (kebab-case, 名前付きエクスポート, インポート順, import type, 名前付き定数)

(useEffect のクリーンアップ時または URL を置き換える際に、URL.revokeObjectURL() でオブジェクト URL を必ずクリーンアップする必要があります)

(EXIF 方向を適用する前に、ブラウザのコンテキストを必ず確認してください - 最新のブラウザは自動的に回転するため、手動で処理すると二重回転が発生します)

(画像を 50% 以上縮小する場合は、ステップダウンスケーリングを必ず使用してください - シングルパスでのサイズ変更は品質が低下します)

(キャンバスの寸法をブラウザの最大値(通常は 4096px)に制限する必要があります - より大きなキャンバスはブラウザをクラッシュさせます)

</critical_requirements>


自動検出: 画像プレビュー, URL.createObjectURL, revokeObjectURL, canvas resize, image compression, EXIF orientation, toBlob, toDataURL, FileReader image, image thumbnail, client-side resize, image crop, canvas drawImage, createImageBitmap, image quality

使用場面:

  • アップロード前の画像プレビューの作成
  • 画像のクライアントサイドでのサイズ変更または圧縮
  • モバイル写真からの EXIF 方向の処理
  • 画像形式(JPEG/PNG/WebP)間の変換
  • ユーザーが選択した画像からのサムネイルの生成
  • 画像のトリミングインターフェースの実装

使用しない場面:

  • サーバーサイドの画像処理(クライアントサイドの範囲外)
  • 画像 CDN/最適化サービス(インフラストラクチャの問題)
  • 複雑な画像編集(Fabric.js や Konva などの専用ライブラリを検討してください)

<philosophy>

哲学

クライアントサイドでの画像処理は、即時のプレビューを提供し、サーバーに送信する前にアップロードサイズを削減することで、UX を向上させます。重要なのは、プレビューと処理では最適なアプローチが異なるということです - プレビューには URL.createObjectURL() (高速、メモリ効率が良い)、処理には Canvas API (サイズ変更、圧縮、変換) を使用します。

コア原則:

  1. プレビューにはオブジェクト URL - ファイルの読み取り不要、即時表示、クリーンアップ必須
  2. 処理には Canvas - サイズ変更、圧縮、形式変換
  3. メモリ管理が重要 - リークしたオブジェクト URL は無期限に蓄積されます
  4. EXIF を意識する - 最新のブラウザは表示のために自動的に回転します。手動での処理はアップロード処理のみ
  5. 段階的な品質 - ステップダウンスケーリングは大幅な縮小でも鮮明さを維持します

プレビュー方法の比較:

方法 速度 メモリ ユースケース
URL.createObjectURL() 瞬時 低 (参照) プレビューの表示
FileReader.readAsDataURL() 低速 高 (完全な Base64) データ URL 文字列が必要
Canvas toDataURL() 中速 中程度 処理後

</philosophy>


<patterns>

コアパターン

パターン 1: クリーンアップ付きオブジェクト URL プレビュー

即時の画像プレビューには URL.createObjectURL() を使用します。メモリリークを防ぐために必ずクリーンアップしてください。重要なパターンは、新しい URL を作成する前に以前の URL を破棄し、useEffect のクリーンアップで破棄することです。

// 必須のクリーンアップパターン
useEffect(() => {
  const url = URL.createObjectURL(file);
  setPreviewUrl(url);
  return () => URL.revokeObjectURL(url); // 必ずクリーンアップ
}, [file]);

良い点: ファイルをメモリに読み込まずに即座にプレビューでき、クリーンアップによりメモリリークを防ぎます。

// 悪い例: クリーンアップなし - メモリリーク
const [preview] = useState(() => URL.createObjectURL(file));
// URL が破棄されない - メモリが無期限に蓄積されます!

悪い点: オブジェクト URL が破棄されず、ブラウザが blob 参照を無期限に保持し、ファイルを選択するたびに悪化します。

完全なフックとコンポーネントの実装については、examples/core.md パターン 1-2 を参照してください。


パターン 2: 品質保持付き Canvas リサイズ

Canvas API を使用して画像のサイズを変更します。主な懸念事項: 寸法をブラウザの制限 (安全な最大値は 4096px) にクランプし、imageSmoothingQuality: "high" を有効にし、JPEG の場合は白い背景を塗りつぶします (そうしないと透明度が黒になります)。

const MAX_CANVAS_DIMENSION = 4096;

// ブラウザの制限にクランプし、アスペクト比を維持します
const ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
const width = Math.round(img.width * Math.min(ratio, 1));
const height = Math.round(img.height * Math.min(ratio, 1));

ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = "high";
if (mimeType === "image/jpeg") {
  ctx.fillStyle = "#ffffff";
  ctx.fillRect(0, 0, width, height); // JPEG の場合は白い背景
}
ctx.drawImage(img, 0, 0, width, height);

寸法の検証については examples/core.md パターン 3 を、完全なリサイズパイプラインについては examples/canvas.md を参照してください。


パターン 3: ステップダウンスケーリング

50% を超える縮小の場合は、鮮明さを維持するために複数回に分けてスケーリングします。4000px から 100px へのシングルパスでのサイズ変更では、ぼやけた結果になります。2 つの中間ステップで品質が維持されます。

const STEP_DOWN_THRESHOLD = 0.5;
const reductionRatio = targetWidth / img.width;

if (reductionRatio < STEP_DOWN_THRESHOLD) {
  // マルチパス: 4000 -> 400 -> 100 (2 ステップ)
  const factor = Math.pow(targetWidth / img.width, 1 / steps);
  for (let i = 0; i < steps; i++) {
    /* 各ステップで factor でスケーリング */
  }
} else {
  // 小さな縮小の場合はシングルパスで問題ありません
}

自動戦略選択による完全なステップダウンの実装については、examples/canvas.md パターン 1 を参照してください。


パターン 4: EXIF 方向

最新のブラウザ (2020 年以降) は、CSS image-orientation: from-image を介して表示用に画像を自動的に回転させます

(原文はここで切り詰められています)

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Image Handling Patterns

Quick Guide: Use URL.createObjectURL() for image previews (most efficient). Resize/compress with Canvas API before upload. Always cleanup object URLs with URL.revokeObjectURL() to prevent memory leaks. Handle EXIF orientation for mobile photos only when processing for upload (modern browsers auto-rotate for display). Use step-down scaling for quality preservation on large reductions.


<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST cleanup object URLs with URL.revokeObjectURL() in useEffect cleanup or when replacing URLs)

(You MUST check browser context before applying EXIF orientation - modern browsers auto-rotate, manual handling causes double rotation)

(You MUST use step-down scaling when reducing images by more than 50% - single-pass resize loses quality)

(You MUST limit canvas dimensions to browser maximums (typically 4096px) - larger canvases crash browsers)

</critical_requirements>


Auto-detection: image preview, URL.createObjectURL, revokeObjectURL, canvas resize, image compression, EXIF orientation, toBlob, toDataURL, FileReader image, image thumbnail, client-side resize, image crop, canvas drawImage, createImageBitmap, image quality

When to use:

  • Creating image previews before upload
  • Resizing or compressing images client-side
  • Handling EXIF orientation from mobile photos
  • Converting between image formats (JPEG/PNG/WebP)
  • Generating thumbnails from user-selected images
  • Implementing image cropping interfaces

When NOT to use:

  • Server-side image processing (not client-side scope)
  • Image CDN/optimization services (infrastructure concern)
  • Complex image editing (consider dedicated libraries like Fabric.js or Konva)

<philosophy>

Philosophy

Client-side image handling improves UX by providing instant previews and reducing upload sizes before they hit your server. The key insight is that preview and processing have different optimal approaches - URL.createObjectURL() for previews (fast, memory-efficient), Canvas API for processing (resize, compress, convert).

Core Principles:

  1. Object URLs for preview - No file reading, instant display, must cleanup
  2. Canvas for processing - Resize, compress, convert formats
  3. Memory management is critical - Leaked object URLs accumulate indefinitely
  4. EXIF awareness - Modern browsers auto-rotate for display; manual handling only for upload processing
  5. Progressive quality - Step-down scaling preserves sharpness on large reductions

Preview Method Comparison:

Method Speed Memory Use Case
URL.createObjectURL() Instant Low (reference) Display previews
FileReader.readAsDataURL() Slow High (full Base64) Need data URL string
Canvas toDataURL() Medium Medium After processing

</philosophy>


<patterns>

Core Patterns

Pattern 1: Object URL Preview with Cleanup

Use URL.createObjectURL() for instant image previews. Always cleanup to prevent memory leaks. The critical pattern is revoking the previous URL before creating a new one, and revoking in the useEffect cleanup.

// The essential cleanup pattern
useEffect(() => {
  const url = URL.createObjectURL(file);
  setPreviewUrl(url);
  return () => URL.revokeObjectURL(url); // MUST cleanup
}, [file]);

Why good: Instant preview without reading file into memory, cleanup prevents memory leaks

// BAD: No cleanup - memory leak
const [preview] = useState(() => URL.createObjectURL(file));
// URL never revoked - memory accumulates indefinitely!

Why bad: Object URL never revoked, browser holds blob reference indefinitely, compounds with each file selection

See examples/core.md Pattern 1-2 for complete hook and component implementations.


Pattern 2: Canvas Resize with Quality Preservation

Resize images using Canvas API. Key concerns: clamp dimensions to browser limits (4096px safe max), enable imageSmoothingQuality: "high", fill white background for JPEG (transparency becomes black otherwise).

const MAX_CANVAS_DIMENSION = 4096;

// Clamp to browser limits, maintain aspect ratio
const ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
const width = Math.round(img.width * Math.min(ratio, 1));
const height = Math.round(img.height * Math.min(ratio, 1));

ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = "high";
if (mimeType === "image/jpeg") {
  ctx.fillStyle = "#ffffff";
  ctx.fillRect(0, 0, width, height); // White bg for JPEG
}
ctx.drawImage(img, 0, 0, width, height);

See examples/core.md Pattern 3 for dimension validation, examples/canvas.md for complete resize pipeline.


Pattern 3: Step-Down Scaling

For reductions >50%, scale in multiple passes to preserve sharpness. A 4000px to 100px single-pass resize produces blurry results; two intermediate steps maintain quality.

const STEP_DOWN_THRESHOLD = 0.5;
const reductionRatio = targetWidth / img.width;

if (reductionRatio < STEP_DOWN_THRESHOLD) {
  // Multi-pass: 4000 -> 400 -> 100 (two steps)
  const factor = Math.pow(targetWidth / img.width, 1 / steps);
  for (let i = 0; i < steps; i++) {
    /* scale by factor each step */
  }
} else {
  // Single-pass is fine for small reductions
}

See examples/canvas.md Pattern 1 for complete step-down implementation with automatic strategy selection.


Pattern 4: EXIF Orientation

Modern browsers (2020+) auto-rotate images for display via CSS image-orientation: from-image (default). Manual EXIF handling is only needed when:

  • Processing images for upload (server may strip EXIF and not rotate)
  • Using Node.js canvas (no auto-rotation)
  • Needing to detect orientation programmatically
// For DISPLAY: modern browsers handle it - do nothing
<img src={URL.createObjectURL(file)} /> // Auto-rotated

// For UPLOAD PROCESSING: normalize before sending to server
const orientation = await getExifOrientation(file); // Read from JPEG header
if (orientation !== 1) {
  const normalized = await normalizeOrientation(file);
  await uploadToServer(normalized);
}

// To BYPASS auto-rotation (show raw orientation)
<img src={url} style={{ imageOrientation: 'none' }} />

Gotcha: Applying normalizeOrientation() then displaying via <img> causes double-rotation in modern browsers.

See examples/core.md Pattern 4 for EXIF parsing implementation.


Pattern 5: Format Conversion

Convert between JPEG/PNG/WebP with format-appropriate quality defaults. Key detail: JPEG cannot represent transparency, so fill white background before conversion.

const FORMAT_QUALITY_DEFAULTS: Record<string, number> = {
  "image/jpeg": 0.85,
  "image/webp": 0.82,
  "image/png": 1, // Lossless - quality param ignored
};

WebP is supported in all modern browsers (including Safari 14+). For target file size, use binary search over quality parameter.

See examples/canvas.md Pattern 2 for binary search quality targeting.


Pattern 6: Cropping

Canvas-based cropping using drawImage() with source rectangle parameters. Validate crop region is within image bounds, support resize-during-crop for generating specific output dimensions.

// drawImage(source, sx, sy, sw, sh, dx, dy, dw, dh)
ctx.drawImage(
  img,
  cropX,
  cropY,
  cropWidth,
  cropHeight,
  0,
  0,
  outputWidth,
  outputHeight,
);

See examples/canvas.md Pattern 3 for complete crop implementation with aspect ratio helper.

</patterns>


Detailed Resources:

  • examples/core.md - Preview hooks, components, dimension validation, EXIF parsing
  • examples/preview.md - Drag-and-drop, thumbnails, gallery grid
  • examples/canvas.md - Resize pipeline, target-size compression, cropping, watermarks, filters
  • reference.md - Decision frameworks, constants reference, browser compatibility, anti-patterns

<red_flags>

RED FLAGS

High Priority Issues:

  • Not calling URL.revokeObjectURL() - causes memory leaks that accumulate indefinitely
  • Canvas dimensions exceeding 4096px - crashes browser tab or silently fails
  • Double EXIF rotation - applying manual rotation in browsers that auto-rotate (all modern browsers since 2020)

Medium Priority Issues:

  • Using FileReader.readAsDataURL() for preview - slow and memory-intensive vs object URLs
  • Single-pass resize for large reductions (>50%) - results in blurry/aliased images
  • Creating object URLs inside render functions - creates new URL every render cycle

Gotchas & Edge Cases:

  • Object URLs persist until page unload even without cleanup (but waste memory)
  • Canvas toBlob() is async, toDataURL() is sync - prefer toBlob for performance
  • PNG with transparency converted to JPEG needs white background fill (otherwise black)
  • Very large images may exceed WebGL limits even within canvas dimension limits
  • Node.js canvas does NOT auto-rotate EXIF - still needs manual handling server-side
  • Use image-orientation: none CSS to bypass browser auto-rotation when needed

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

All code must follow project conventions in CLAUDE.md

(You MUST cleanup object URLs with URL.revokeObjectURL() in useEffect cleanup or when replacing URLs)

(You MUST check browser context before applying EXIF orientation - modern browsers auto-rotate, manual handling causes double rotation)

(You MUST use step-down scaling when reducing images by more than 50% - single-pass resize loses quality)

(You MUST limit canvas dimensions to browser maximums (typically 4096px) - larger canvases crash browsers)

Failure to follow these rules will cause memory leaks, browser crashes, and poor image quality.

</critical_reminders>