フォルダに画像を入れてコマンドを1回実行。
Python(Pillow)でまとめてリサイズし、EXIF(写真の向き)補正、拡大しない設定、品質の調整、WebP出力まで対応します。
Windows/Macでそのまま動き、共有・メール添付・クラウド容量の節約・資料作成・EC出品など幅広い用途で使えます。
まずはこれだけ(最短コース)
\ pipや仮想環境が不安な方はこの1冊 /
1) フォルダを用意
- デスクトップなど好きな場所に
img-workフォルダを作る - その中に
input_imagesフォルダを作り、小さくしたい写真を全部ここに入れる
2) 準備(Pillowという道具を入れる)
Mac:
python3 -m pip install --upgrade pip
python3 -m pip install PillowWindows(PowerShell):
py -3 -m pip install --upgrade pip
py -3 -m pip install Pillow3) 下のスクリプトをメモ帳にコピペして保存
- ファイル名:
resize_simple.py - 保存場所:
img-workフォルダの中(input_imagesと同じ階層)
from pathlib import Path
from PIL import Image, ImageOps
# --- HEICを入れていれば使う(任意) ---
try:
import pillow_heif
pillow_heif.register_heif_opener()
HEIF_ENABLED = True
except ImportError:
HEIF_ENABLED = False
# ----------------------------------------
# ===== 設定(ここだけ変えればOK) =====
INPUT_DIR = Path("./input_images") # 入力フォルダ
OUTPUT_DIR = Path("./resized") # 出力フォルダ
LONG_EDGE = 1600 # 長辺のピクセル数(例: 1600)
OUTPUT_FORMAT = "jpg" # "keep"=そのまま / "jpg" / "webp" / "png"
QUALITY = 85 # 画像のきれいさ(数が大きいほどきれい&重い)
# ======================================
EXTS = {".jpg", ".jpeg", ".png", ".webp", ".tif", ".tiff"}
if HEIF_ENABLED:
EXTS |= {".heic", ".heif"}
def calc_new_size(w, h, long_edge=LONG_EDGE):
scale = long_edge / max(w, h)
scale = min(scale, 1.0) # 小さい画像は拡大しない
return max(1, int(w*scale)), max(1, int(h*scale))
def ensure_rgb_for_jpeg(img: Image.Image) -> Image.Image:
# 透過PNGをJPEGにするときは白背景にしておく
if img.mode in ("RGBA", "LA"):
bg = Image.new("RGB", img.size, (255, 255, 255))
bg.paste(img, mask=img.split()[-1])
return bg
if img.mode in ("P", "CMYK"):
return img.convert("RGB")
return img
def main():
files = [p for p in INPUT_DIR.rglob("*") if p.suffix.lower() in EXTS]
if not files:
print("画像が見つかりません。INPUT_DIRを確認してください。")
return
for src in files:
rel = src.relative_to(INPUT_DIR)
out_ext = src.suffix.lower() if OUTPUT_FORMAT == "keep" else "." + OUTPUT_FORMAT
out = (OUTPUT_DIR / rel).with_suffix(out_ext)
out.parent.mkdir(parents=True, exist_ok=True)
try:
with Image.open(src) as im:
im = ImageOps.exif_transpose(im) # 写真の向きを自動で直す
w, h = im.size
nw, nh = calc_new_size(w, h)
if (nw, nh) != (w, h):
im = im.resize((nw, nh), Image.Resampling.LANCZOS)
exif = im.info.get("exif")
icc = im.info.get("icc_profile")
fmt = (OUTPUT_FORMAT if OUTPUT_FORMAT != "keep" else src.suffix[1:]).upper()
if fmt == "JPG":
fmt = "JPEG"
if fmt in ("TIF", "TIFF"):
fmt = "TIFF"
if fmt in ("HEIC", "HEIF"):
fmt = "HEIF"
save_kwargs = {}
if fmt in ("JPEG", "WEBP"):
save_kwargs["quality"] = QUALITY
if fmt == "JPEG":
im = ensure_rgb_for_jpeg(im)
save_kwargs.update(dict(optimize=True, progressive=True))
if exif: save_kwargs["exif"] = exif
if icc: save_kwargs["icc_profile"] = icc
elif fmt == "PNG":
if icc: save_kwargs["icc_profile"] = icc
save_kwargs["optimize"] = True
elif fmt == "WEBP":
save_kwargs.update(dict(method=6))
if icc: save_kwargs["icc_profile"] = icc
im.save(out, format=fmt, **save_kwargs)
print(f"OK: {rel} -> {out.relative_to(OUTPUT_DIR)} ({w}x{h}→{nw}x{nh})")
except Exception as e:
print(f"ERROR: {src.name} / {e}")
print(f"完了: 出力先 {OUTPUT_DIR.resolve()}")
if __name__ == "__main__":
main()4) 実行する
Mac:
cd /あなたの/img-work の場所
python3 resize_simple.pyWindows(PowerShell):
cd "C:\Users\あなたの名前\Desktop\img-work"
py -3 resize_simple.py終わったら img-work の中に resized フォルダができ、そこに小さくなった写真が入ります。
迷ったら:何も変えずに LONG_EDGE=1600 のまま実行でOK。ウェブ共有や資料作成でちょうど良いサイズ感です。
要点(最初に)
- 目的:指定フォルダ内の画像を、長辺○○pxまたは幅×高さの枠内に一括リサイズ。アスペクト比は維持。
- 対応:JPEG/PNG/WebP/TIFF。EXIF(写真の向きの情報)の回転補正&(可能なら)ICCプロファイル(色の情報)を保持。
- 安全設計:デフォルトは拡大しない(画質劣化を防ぐ)。
- 追加機能:出力フォーマットの強制変換/WebP同時出力/品質指定。
この記事で作るもの
- コピペで使えるPythonスクリプト(
resize_images.py) - Windows/Macのインストール~実行コマンド
- 実務TIPS(WordPress/SWELLでの使いどころ、OGP・サムネの目安、失敗しがちなポイント)
- 目的別レシピ(WebP化、正方形サムネ、目標KBに落とす など)
動作環境と準備
- Python 3.9 以上推奨(3.8でも可)
- 追加ライブラリ:Pillow
1) Pythonの確認
Mac
python3 --versionWindows(PowerShell)
py -3 --version2) プロジェクト用フォルダ&仮想環境(任意)
mkdir img-resizer && cd img-resizer
python3 -m venv .venv # Windowsは: py -3 -m venv .venv
source .venv/bin/activate # Windowsは: .venv\Scripts\activate3) Pillowのインストール
pip install --upgrade pip
pip install Pillow3.5) iPhoneのHEICを扱う(任意)
HEIC/HEIF(iPhoneの標準写真)も読みたい場合は追加します。
Mac/Windows 共通
pip install pillow-heif上記のコマンドは一度入れればOKです。以降のサンプルコードでインポート+有効化しています。
補足:--format keep のとき、HEICは内部的に HEIFフォーマットとして保存されます(拡張子は .heic でもOK)。エクスプローラ/プレビューで開けない場合は、--format jpg などに変換して出力してください。
\ iPhone写真をPCへ高速転送。
HEICのまま取り込んで、本記事の手順で一括変換できます。 /
コピペで使える一括リサイズスクリプト
ファイル名:resize_images.py
フォルダ内を再帰的に走査し、長辺基準または枠内(最大幅×最大高)で一括リサイズ。
既定では拡大しない。EXIF(写真の向きの情報)の回転補正、ICCプロファイル(色の情報)の引き継ぎを試み、JPEG/WebP品質を指定可能。WebP同時出力にも対応。
import argparse
from pathlib import Path
from PIL import Image, ImageOps
# --- HEICを入れていれば使う(任意) ---
try:
import pillow_heif
pillow_heif.register_heif_opener()
HEIF_ENABLED = True
except ImportError:
HEIF_ENABLED = False
# ----------------------------------------
EXTS = {".jpg", ".jpeg", ".png", ".webp", ".tif", ".tiff"}
if HEIF_ENABLED:
EXTS |= {".heic", ".heif"}
def calc_new_size(w, h, *, long_edge=None, max_w=None, max_h=None, no_upscale=True):
if long_edge:
scale = long_edge / max(w, h)
else:
max_w = max_w or 10**9
max_h = max_h or 10**9
scale = min(max_w / w, max_h / h)
if no_upscale:
scale = min(scale, 1.0)
return (max(1, int(w * scale)), max(1, int(h * scale)))
def ensure_rgb_for_jpeg(img: Image.Image) -> Image.Image:
if img.mode in ("RGBA", "LA"):
bg = Image.new("RGB", img.size, (255, 255, 255))
bg.paste(img, mask=img.split()[-1])
return bg
if img.mode in ("P", "CMYK"):
return img.convert("RGB")
return img
def save_image(im: Image.Image, out_path: Path, fmt: str, quality: int, exif, icc):
fmt = fmt.upper()
if fmt == "JPG":
fmt = "JPEG"
if fmt in ("TIF", "TIFF"):
fmt = "TIFF"
if fmt in ("HEIC", "HEIF"):
fmt = "HEIF"
save_kwargs = {}
if fmt in ("JPEG", "WEBP"):
save_kwargs["quality"] = quality
if fmt == "JPEG":
im = ensure_rgb_for_jpeg(im)
save_kwargs.update(dict(optimize=True, progressive=True))
if exif: save_kwargs["exif"] = exif
if icc: save_kwargs["icc_profile"] = icc
elif fmt == "PNG":
if icc: save_kwargs["icc_profile"] = icc
save_kwargs["optimize"] = True
elif fmt == "WEBP":
save_kwargs.update(dict(method=6)) # 最高圧縮(遅い方)
if icc: save_kwargs["icc_profile"] = icc
im.save(out_path, format=fmt, **save_kwargs)
def process_file(src_path: Path, dst_root: Path, args):
rel = src_path.relative_to(args.src)
out_ext = ("." + args.format.lower()) if args.format else src_path.suffix.lower()
out_path = (dst_root / rel).with_suffix(out_ext)
out_path.parent.mkdir(parents=True, exist_ok=True)
try:
with Image.open(src_path) as im:
im = ImageOps.exif_transpose(im) # EXIF(写真の向きの情報)回転補正
orig_w, orig_h = im.size
new_w, new_h = calc_new_size(
orig_w, orig_h,
long_edge=args.long_edge,
max_w=args.max_width,
max_h=args.max_height,
no_upscale=not args.allow_upscale
)
if (new_w, new_h) != (orig_w, orig_h):
im = im.resize((new_w, new_h), Image.Resampling.LANCZOS)
exif = im.info.get("exif")
icc = im.info.get("icc_profile")
fmt_hint = None if (args.format in (None, "keep")) else args.format
primary_fmt = (fmt_hint or src_path.suffix[1:]).upper()
save_image(im, out_path, primary_fmt, args.quality, exif, icc)
if args.also_webp:
webp_path = out_path.with_suffix(".webp")
save_image(im, webp_path, "WEBP", args.webp_quality or args.quality, exif, icc)
return True, f"{src_path.name}: {orig_w}x{orig_h} -> {new_w}x{new_h}"
except Exception as e:
return False, f"{src_path.name}: ERROR {e}"
def main():
p = argparse.ArgumentParser(description="画像の一括リサイズ")
p.add_argument("--src", type=Path, required=True, help="入力フォルダ")
p.add_argument("--dst", type=Path, default=Path("./resized"), help="出力フォルダ")
g = p.add_mutually_exclusive_group(required=True)
g.add_argument("--long-edge", type=int, help="長辺のピクセル数(例: 1600)")
g.add_argument("--max-width", type=int, help="最大幅(例: 1600)")
p.add_argument("--max-height", type=int, help="最大高(例: 1200)")
p.add_argument("--quality", type=int, default=85, help="JPEG/WEBP品質(1-95推奨)")
p.add_argument("--format", choices=["keep","jpg","jpeg","png","webp"], help="出力フォーマットを強制変換")
p.add_argument("--allow-upscale", action="store_true", help="小さな画像も拡大してよい")
p.add_argument("--also-webp", action="store_true", help="主出力に加えてWebPも同時保存")
p.add_argument("--webp-quality", type=int, help="WebPの品質(未指定なら --quality と同じ)")
args = p.parse_args()
files = [p for p in args.src.rglob("*") if p.suffix.lower() in EXTS]
if not files:
print("対象画像が見つかりませんでした。")
return
print(f"Found {len(files)} files.")
ok = err = 0
for f in files:
success, msg = process_file(f, args.dst, args)
print(msg)
ok += int(success)
err += int(not success)
print(f"Done. success={ok}, error={err}, out={args.dst.resolve()}")
if __name__ == "__main__":
main()ImageOps.exif_transpose()でスマホ写真の縦横回転問題を自動補正。- デフォルトで拡大禁止(小さい元画像はそのまま)。
--allow-upscaleを付けたときだけ拡大。 - JPEG/WebPは
--qualityで品質指定(85前後が現実解)。 --also-webpでJPEGなどの主出力+WebP同時保存に対応。
使い方(実行コマンド例)
1) 長辺を 1600px にそろえる(拡大禁止、品質85)
python3 resize_images.py --src ./input_images --dst ./resized --long-edge 16002) 1600×1200 の枠内に収める(アスペクト比は保持)
python3 resize_images.py --src ./input_images --dst ./resized --max-width 1600 --max-height 12003) 強制的に WebP 化したい
python3 resize_images.py --src ./input_images --dst ./webp --long-edge 1600 --format webp --quality 804) JPEGを主出力にしつつ、WebPも同時に保存
python3 resize_images.py --src ./input_images --dst ./out --long-edge 1600 --format jpg --quality 85 --also-webp --webp-quality 805) 小さい画像も拡大していい場合
python3 resize_images.py --src ./input_images --dst ./large --long-edge 2048 --allow-upscalepython3 の代わりに py -3 でもOK。
用途別サイズ目安(Web/共有/印刷)
- Webページ・資料共有:長辺 1600〜2048px
- SNS/OGP:1200×630
- 正方形サムネ:1080×1080
- メール添付を軽く:長辺 1280〜1600px
- 印刷(L判〜A4):長辺 3000px前後 / JPEG品質90〜
目的別レシピ(小スクリプト)
A. 正方形サムネを作る(中央クロップ)
from PIL import Image, ImageOps
# --- HEICを入れていれば使う(任意) ---
try:
import pillow_heif
pillow_heif.register_heif_opener()
HEIF_ENABLED = True
except ImportError:
HEIF_ENABLED = False
# ----------------------------------------
def square_crop_resize(src, dst, size=1080):
with Image.open(src) as im:
im = ImageOps.exif_transpose(im)
im = ImageOps.fit(im, (size, size), method=Image.Resampling.LANCZOS, centering=(0.5, 0.5))
im.save(dst, quality=90, optimize=True, progressive=True)B. 目標ファイルサイズ(KB)に近づける(JPEGの品質調整)
from PIL import Image, ImageOps
import io
# --- HEICを入れていれば使う(任意) ---
try:
import pillow_heif
pillow_heif.register_heif_opener()
HEIF_ENABLED = True
except ImportError:
HEIF_ENABLED = False
# ----------------------------------------
def save_under_kb(src, dst, max_kb=300, quality_start=90):
with Image.open(src) as im:
im = ImageOps.exif_transpose(im).convert("RGB")
q = quality_start
while q >= 50:
buf = io.BytesIO()
im.save(buf, format="JPEG", quality=q, optimize=True, progressive=True)
if len(buf.getvalue()) <= max_kb * 1024:
with open(dst, "wb") as f:
f.write(buf.getvalue())
return q
q -= 5
return Noneよくある質問・トラブルシュート
zsh: command not found: python3(Mac)-
Homebrew等でPythonを入れるか、
python --versionで既存のPythonに切り替えて実行してください。pyenvを使ってもOK。 ModuleNotFoundError: No module named 'PIL'-
pip install Pillowを忘れている可能性。仮想環境がアクティブかも確認。 - 画像が横向き/逆さになる
-
スクリプト内で
ImageOps.exif_transpose()を使っています。自前処理の際はこの一行を必ず入れてください。 - PNGの透過が白くなる
-
JPEGは透過不可。透過を保ちたいときはPNG/WEBPで保存(
--format pngor--format webp)。 - 色が違って見える
-
ICCプロファイル(色の情報)を付与していますが、ブラウザ/アプリ差で見え方が変わる場合があります。sRGBで一元化したい場合は
img = img.convert('RGB')の上でICCなし保存も検討。 - 既存ファイルを上書きしたい
-
安全のため別フォルダ出力にしています。上書きは事故の元なのでおすすめしません(Git管理やバックアップがあれば対応可)。
実務TIPS
- 品質(quality):85は視覚品質とサイズの妥協点。写真多めの記事は80〜85、図版・文字多めは90でもOK。
- WebP:ほぼ全ブラウザ対応。JPEG + WebP併用にしておくと、テーマやCDNの最適化にも噛みやすい。
- 命名規則:
post-slug_001.jpgのように連番&記事スラッグを入れると、後で管理が楽。(自動リネームは別スクリプトで) - CDN/最適化:Cloudflare Images / 画像圧縮プラグインの前処理として、このスクリプトで事前縮小しておくと負荷が減ります。
\ 撮影→圧縮→アップが一気に短縮。 /
\ 元データは外付けに退避→記事用は本スクリプトで軽量化 /
まとめ
- Pillowだけで現実運用に耐える一括リサイズが可能。
- まずは 長辺1600px・品質85 から。必要に応じて WebP同時出力や正方形サムネを併用。
- WordPress/SWELLでも、アップ前に最適サイズへ整えると表示が軽く、SEOにもプラス。

