写真保存形式をjpgからwebpに切り替えた
これまで、写真の保存形式としては主に`jpg`(JPEG)を使っていました。扱いやすく、ほとんどの環境で問題なく開くことができるため、特に疑問も持たずに長年使い続けていたのです。
写真保存形式をjpgからwebpに切り替えた#
はじめに#
これまで、写真の保存形式としては主にjpg(JPEG)を使っていました。扱いやすく、ほとんどの環境で問題なく開くことができるため、特に疑問も持たずに長年使い続けていたのです。
ところが最近、「webp」という画像形式を見かける機会が増えてきました。Googleが開発した形式で、主にWebの高速表示を目的としているそうです。少し気になったので、自分の環境でも試してみることにしました。
webp形式のメリット#
調べてみたところ、webpにはいくつかの魅力的な特長があることがわかりました。
- ファイルサイズが小さい:同じ画質で保存した場合でも、jpgより圧縮率が高く、容量がかなり抑えられます。
- 画質も良好:圧縮による劣化が目立ちにくく、自然な見た目を保てます。
- 透過対応:pngと同様に背景を透明にできるため、用途の幅が広がります。
- アニメーション対応:gifの代替としても利用可能です。
対応状況も年々改善されており、主要なブラウザやモダンなOSではほとんど問題なく再生・表示が可能になってきています。
Macでのwebp対応状況#
私が特に驚いたのは、macOSがwebp形式をいつの間にか標準でサポートしていたという点です。
Finderでのサムネイル表示やQuick Look(スペースキーによるプレビュー)も対応しており、Preview.appでも問題なく開けました。普段使っている画像ビューアと変わらない使い心地で、非常にスムーズでした。
jpgからwebpへの変換自動化#
brewに入っているので、以下のコマンドでOKです。
brew install webpcwebp -q 80 input.jpg -o output.webp一つ一つやるのは大変なので既存のjpgファイルを一括でwebpに変換してみようと思い、自分で変換スクリプトを作成します。 Claude Codeでささっと。AIが作ると絵文字が多くなるのはなんでなんでしょうね。
#!/bin/bash
# JPG/PNG/JPEGファイルをWebPに再帰的に変換するスクリプト# 使用方法: ./image-to-webp-converter.sh /path/to/directory [quality]
# 引数チェックif [ $# -lt 1 ]; then echo "使用方法: $(basename "$0") <ディレクトリパス> [品質(0-100、デフォルト:70)]" echo "例: $(basename "$0") '/home/user/pictures with spaces' 85" echo "例: $(basename "$0") /home/user/pictures 85" exit 1fi
TARGET_DIR="$1"QUALITY="${2:-70}"
# ディレクトリの存在チェックif [ ! -d "$TARGET_DIR" ]; then echo "エラー: ディレクトリ '$TARGET_DIR' が存在しません" exit 1fi
# cwebpコマンドの存在チェックif ! command -v cwebp &> /dev/null; then echo "エラー: cwebpコマンドが見つかりません" echo "WebPツールをインストールしてください" exit 1fi
# 品質の範囲チェックif ! [[ "$QUALITY" =~ ^[0-9]+$ ]] || [ "$QUALITY" -lt 0 ] || [ "$QUALITY" -gt 100 ]; then echo "エラー: 品質は0-100の数値で指定してください" exit 1fi
# ディレクトリ全体のサイズを計算する関数get_directory_size() { local dir="$1" if command -v du >/dev/null 2>&1; then # macOSとLinux両対応 local size_kb=$(du -sk "$dir" 2>/dev/null | cut -f1) if [ -n "$size_kb" ] && [ "$size_kb" -gt 0 ]; then echo $((size_kb * 1024)) # KBをBに変換 else echo "0" fi else echo "0" fi}
# ファイルサイズを人間が読みやすい形式に変換する関数human_readable_size() { local size=$1 if [ "$size" -ge 1073741824 ]; then echo "$(echo "scale=2; $size / 1073741824" | bc -l) GB" elif [ "$size" -ge 1048576 ]; then echo "$(echo "scale=2; $size / 1048576" | bc -l) MB" elif [ "$size" -ge 1024 ]; then echo "$(echo "scale=2; $size / 1024" | bc -l) KB" else echo "${size} B" fi}
# 圧縮率を計算する関数calculate_compression_ratio() { local original=$1 local compressed=$2 if [ "$original" -gt 0 ]; then echo "$(echo "scale=1; (($original - $compressed) * 100) / $original" | bc -l)" else echo "0" fi}
echo "=== 画像 to WebP 変換スクリプト ==="echo "対象ディレクトリ: $TARGET_DIR"echo "品質設定: $QUALITY"echo "対応形式: JPG, JPEG, PNG"echo "==============================="
# 指定されたディレクトリに移動して処理を実行cd "$TARGET_DIR" || { echo "エラー: ディレクトリ '$TARGET_DIR' に移動できません" exit 1}
# 変換前のディレクトリサイズを取得echo ""echo "📁 変換前のディレクトリサイズを計算中..."initial_dir_size=$(get_directory_size ".")echo "変換前ディレクトリサイズ: $(human_readable_size $initial_dir_size)"echo ""
# 一時ファイルでカウンターとサイズを管理temp_dir=$(mktemp -d)trap "rm -rf '$temp_dir'" EXIT # スクリプト終了時に一時ディレクトリを削除
converted_count_file="$temp_dir/converted_count"failed_count_file="$temp_dir/failed_count"total_original_size_file="$temp_dir/total_original_size"total_converted_size_file="$temp_dir/total_converted_size"
echo "0" > "$converted_count_file"echo "0" > "$failed_count_file"echo "0" > "$total_original_size_file"echo "0" > "$total_converted_size_file"
# findコマンドで再帰的に検索・変換(JPG、JPEG、PNGに対応)while IFS= read -r -d '' file; do # 出力ファイル名を生成(拡張子をwebpに変更) output="${file%.*}.webp"
# 元ファイルのサイズを取得 if [ -f "$file" ]; then original_size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null || echo "0") else original_size=0 fi
# ファイル形式を判定してcwebpのオプションを調整 file_ext=$(echo "${file##*.}" | tr '[:upper:]' '[:lower:]')
# PNGの場合は可逆圧縮オプションも提供 if [ "$file_ext" = "png" ]; then # PNGの場合、透明度がある可能性があるのでアルファチャンネルを保持 cwebp_options="-q $QUALITY -alpha_cleanup" # 可逆圧縮を試してみて、サイズが小さくなるかチェック temp_lossless="${output}.temp_lossless" cwebp -lossless "$file" -o "$temp_lossless" 2>/dev/null
if [ -f "$temp_lossless" ]; then lossless_size=$(stat -f%z "$temp_lossless" 2>/dev/null || stat -c%s "$temp_lossless" 2>/dev/null || echo "0") else lossless_size=999999999 # 失敗した場合は非常に大きい値 fi else cwebp_options="-q $QUALITY" lossless_size=999999999 fi
echo "変換中: $file ($(human_readable_size $original_size))"
# WebPに変換 if cwebp $cwebp_options "$file" -o "$output" 2>/dev/null; then # 変換後ファイルのサイズを取得 if [ -f "$output" ]; then converted_size=$(stat -f%z "$output" 2>/dev/null || stat -c%s "$output" 2>/dev/null || echo "0") else converted_size=0 fi
# PNGの場合、可逆圧縮の方が小さければそちらを使用 if [ "$file_ext" = "png" ] && [ "$lossless_size" -lt "$converted_size" ] && [ -f "$temp_lossless" ]; then mv "$temp_lossless" "$output" converted_size=$lossless_size compression_type="可逆圧縮" else compression_type="品質$QUALITY" [ -f "$temp_lossless" ] && rm "$temp_lossless" fi
# 圧縮率を計算 compression_ratio=$(calculate_compression_ratio $original_size $converted_size)
# 変換成功時は元ファイルを削除 if rm "$file"; then echo "✓ 変換完了: $file -> $output ($compression_type)" echo " サイズ: $(human_readable_size $original_size) -> $(human_readable_size $converted_size) (${compression_ratio}% 圧縮)"
# カウンターを一時ファイルに記録 converted_count=$(cat "$converted_count_file") total_original_size=$(cat "$total_original_size_file") total_converted_size=$(cat "$total_converted_size_file")
echo $((converted_count + 1)) > "$converted_count_file" echo $((total_original_size + original_size)) > "$total_original_size_file" echo $((total_converted_size + converted_size)) > "$total_converted_size_file" else echo "✗ 元ファイルの削除に失敗: $file" # 削除に失敗した場合は変換ファイルも削除 [ -f "$output" ] && rm "$output" [ -f "$temp_lossless" ] && rm "$temp_lossless"
failed_count=$(cat "$failed_count_file") echo $((failed_count + 1)) > "$failed_count_file" fi else echo "✗ 変換失敗: $file" # 失敗時は不完全なWebPファイルがあれば削除 [ -f "$output" ] && rm "$output" [ -f "$temp_lossless" ] && rm "$temp_lossless"
failed_count=$(cat "$failed_count_file") echo $((failed_count + 1)) > "$failed_count_file" fi
echo "" # 空行で区切りdone < <(find . -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -print0)
# 一時ファイルから最終結果を読み取りconverted_count=$(cat "$converted_count_file")failed_count=$(cat "$failed_count_file")total_original_size=$(cat "$total_original_size_file")total_converted_size=$(cat "$total_converted_size_file")
echo "==============================="echo "変換完了: ${converted_count}ファイル"echo "変換失敗: ${failed_count}ファイル"
# 変換後のディレクトリサイズを取得echo ""echo "📁 変換後のディレクトリサイズを計算中..."final_dir_size=$(get_directory_size ".")
echo ""echo "=== 最終結果 ==="echo "変換前ディレクトリサイズ: $(human_readable_size $initial_dir_size)"echo "変換後ディレクトリサイズ: $(human_readable_size $final_dir_size)"
if [ $converted_count -gt 0 ]; then echo "" echo "=== 詳細なサイズ比較・圧縮効果 ===" echo "【変換対象ファイルのみ】" echo "変換前総サイズ: $(human_readable_size $total_original_size)" echo "変換後総サイズ: $(human_readable_size $total_converted_size)"
if [ $total_original_size -gt 0 ]; then saved_size=$((total_original_size - total_converted_size)) total_compression_ratio=$(calculate_compression_ratio $total_original_size $total_converted_size)
# ディレクトリ全体での節約サイズ if [ $initial_dir_size -gt 0 ] && [ $final_dir_size -gt 0 ]; then dir_saved_size=$((initial_dir_size - final_dir_size)) dir_compression_ratio=$(calculate_compression_ratio $initial_dir_size $final_dir_size) else dir_saved_size=0 dir_compression_ratio="0" fi
echo "" echo "🎉 圧縮効果 🎉" echo "【変換ファイルのみ】" echo " 節約されたサイズ: $(human_readable_size $saved_size)" echo " 圧縮率: ${total_compression_ratio}%"
echo "【ディレクトリ全体】" echo " ディレクトリ容量削減: $(human_readable_size $dir_saved_size)" echo " ディレクトリ圧縮率: ${dir_compression_ratio}%" echo " 🎯 合計ストレージ節約効果: $(human_readable_size $dir_saved_size)"
# パーセンテージでの節約効果も表示 if [ $total_original_size -gt 0 ]; then savings_percentage=$(echo "scale=1; ($saved_size * 100) / $total_original_size" | bc -l) echo " 変換ファイル削減率: ${savings_percentage}%" fi
if [ $initial_dir_size -gt 0 ] && [ $dir_saved_size -gt 0 ]; then dir_savings_percentage=$(echo "scale=1; ($dir_saved_size * 100) / $initial_dir_size" | bc -l) echo " ディレクトリ全体削減率: ${dir_savings_percentage}%" fi fifiecho "=============================="使い方
chmod u+x jpg2webp.sh./jpg2webp ./images圧縮率や画質の検証#
実際に、100枚ほどのjpg画像をwebp形式に変換して比較してみたところ:
- 平均で40〜60%ほどのファイルサイズ削減が見られました。
- 肉眼で見た限り、ほとんど画質の違いは感じませんでした。
- 特に風景写真や物撮り画像などは、webpとの相性がとても良い印象です。
という感じで圧縮効果がかなりあります。古い端末だと見えないかもしれないので、まだ完全に置き換えるのは難しそうですが、、、
画像圧縮ツールの一つであるjpeg mini proとの併用も検討しています。たとえば、まずjpgをjpeg mini proで圧縮してからwebpに変換すると、さらに無駄のないファイルサイズが実現できそうです。
まとめ#
今回、jpgからwebpへの移行を実際に行ってみて、非常に満足しています。
- 表示速度が向上し、Webページのパフォーマンスにも好影響
- ストレージ容量の節約にもつながる
- 自動化スクリプトの作成によって画像管理の効率化も実現
まだすべての用途に適しているとは言い切れませんが、**「画像を軽量化したい」「でも画質は保ちたい」**と考えている方には、webpはとてもおすすめの形式だと思います。