2026-06-27
การบีบอัดรูปภาพใน Python ด้วย Pillow, WebP และ mozjpeg
บีบอัดรูปภาพ JPEG, PNG และ WebP ใน Python โดยใช้ Pillow, cwebp และ mozjpeg พร้อมด้วยการตั้งค่าคุณภาพ (quality settings), ลูปกำหนดขนาดเป้าหมาย (target-size loops) และสคริปต์แบทช์ที่รวดเร็ว

คำตอบสั้นๆ: วิธีบีบอัดรูปภาพใน Python คืออะไร?
เปิดรูปภาพด้วย Pillow จากนั้นบันทึกโดยใช้ format flags ที่เหมาะสม สำหรับภาพถ่าย ให้บันทึกเป็น JPEG โดยใช้ quality=80, optimize=True, และ progressive=True สำหรับไฟล์สมัยใหม่ที่ต้องการขนาดเล็กที่สุด ให้บันทึกเป็น WebP ด้วย quality=80, method=6 ส่วนกราฟิกแบนและภาพหน้าจอ ให้คงรูปแบบ PNG ไว้และส่งค่า optimize=True
ฟังก์ชันสี่บรรทัดนี้สามารถลดขนาด JPEG จากโทรศัพท์และ DSLR ส่วนใหญ่ได้ถึง 40 ถึง 70 เปอร์เซ็นต์ ส่วนที่เหลือของคู่มือนี้จะเพิ่มเป้าหมายด้านขนาด, WebP, mozjpeg และ batch runner เพื่อให้คุณชี้ไปที่ directory แล้วปล่อยให้มันทำงาน
ต้องเตรียมอะไรบ้างก่อนเริ่ม?
คุณต้องมี Python 3.9 หรือใหม่กว่า และ Pillow ซึ่งเป็นฟอร์กที่ได้รับการดูแลของ PIL Pillow สามารถจัดการกับ JPEG, PNG, และ WebP ได้ทันทีบนแพลตฟอร์มทั่วไปทุกชนิด
สำหรับผลลัพธ์ที่เล็กที่สุด คุณควรมีตัวเข้ารหัสแบบบรรทัดคำสั่งอีกสองตัวที่ Python สามารถเรียกใช้ได้ ได้แก่ cwebp จาก libwebp และ cjpeg จาก mozjpeg
ตรวจสอบว่าแต่ละส่วนใช้ทำอะไรก่อนที่คุณจะเขียนโค้ด:
- Pillow ใช้สำหรับอ่านและเขียนทุกรูปแบบ และทำหน้าที่ปรับขนาดรูปภาพ
- cwebp สร้างไฟล์ WebP ที่มีขนาดเล็กที่สุดและเปิดให้มีการปรับแต่งมากกว่า Pillow
- mozjpeg ทำการเข้ารหัสใหม่ (re-encodes) ไฟล์ JPEG ให้มีขนาดเล็กกว่า libjpeg มาตรฐานที่ Pillow ใช้
- เครื่องมือช่วยรายงานผล เพื่อให้ทุกครั้งที่รันจะแสดงจำนวนไบต์ที่คุณประหยัดได้
นี่คือตัวช่วยที่ใช้ตลอดคู่มือนี้:
หากคุณต้องการบีบอัดแบบครั้งเดียวและไม่ต้องการติดตั้งอะไรเลย เครื่องมือบีบอัดรูปภาพบนเบราว์เซอร์ image compressor ก็สามารถทำงานเดียวกันนี้ได้สำหรับไฟล์จำนวนเล็กน้อย
ต้องทำอย่างไรถึงจะบีบอัดไฟล์ JPEG ด้วย Pillow?
ฟลาก (flags) สามตัวที่สำคัญสำหรับ JPEG คือ quality, optimize, และ progressive โดย quality ควบคุมว่า encoder จะทิ้งรายละเอียดไปมากน้อยแค่ไหน การตั้งค่า optimize=True จะรันรอบที่สองเพื่อสร้าง Huffman table ที่มีขนาดเล็กลง ส่วน progressive=True จะจัดเรียงไฟล์ใหม่เพื่อให้แสดงผลจากบนลงล่างด้วยความละเอียดต่ำก่อน ซึ่งจะให้ความรู้สึกว่าเร็วขึ้นในการเชื่อมต่อที่ช้า และโดยปกติแล้วยังช่วยลดขนาดไฟล์ได้อีกเล็กน้อย

ควรเลือกค่าคุณภาพตามสถานที่ที่ภาพจะถูกนำไปใช้ ไม่ใช่ตัวเลขเดียวทั่วโลก:
| Quality value | Typical use | What to expect |
|---|---|---|
| 90-95 | ภาพฮีโร่, ตัวอย่างงานพิมพ์ | ใกล้เคียงต้นฉบับ, ไฟล์มีขนาดใหญ่ขึ้นอย่างเห็นได้ชัด |
| 75-85 | รูปภาพบนเว็บส่วนใหญ่ | ค่าเริ่มต้นที่ปลอดภัย, ประหยัดพื้นที่มาก |
| 60-70 | ภาพย่อและตัวอย่างพรีวิว | ความนุ่มลงของรายละเอียดเล็กน้อยที่มองเห็นได้ |
| Below 50 | หลีกเลี่ยงสำหรับรูปถ่าย | สิ่งแปลกปลอมแบบบล็อกรอบขอบ |
ข้อผิดพลาดที่ทำให้คนส่วนใหญ่ติดขัดคือ: JPEG ไม่มี alpha channel หากคุณเปิดภาพหน้าจอ PNG ที่มีความโปร่งใสและบันทึกเป็น JPEG โดยตรง Pillow จะแจ้งข้อผิดพลาดว่า cannot write mode RGBA as JPEG การเรียกใช้ convert("RGB") ในฟังก์ชันก่อนหน้านี้จะทำการทำให้ความโปร่งใสนั้นแบนลงบนพื้นหลังสีทึบก่อน ซึ่งนั่นคือเหตุผลที่มันต้องทำงานก่อนการบันทึกไฟล์ JPEG ทุกครั้ง
การบีบอัด PNG และการแปลงเป็น WebP
PNG เป็นรูปแบบที่ไม่มีการสูญเสียข้อมูล (lossless) ดังนั้นคุณจึงไม่สามารถแลกเปลี่ยนคุณภาพกับขนาดได้เหมือนกับการใช้ JPEG สิ่งที่คุณทำได้คือเรียกใช้ตัวปรับปรุงของ Pillow และสำหรับสิ่งใดก็ตามที่เป็นภาพถ่ายจริง ๆ คุณควรเปลี่ยนรูปแบบโดยสิ้นเชิง
method=6 บอกให้ตัวเข้ารหัส WebP ใช้เวลามากขึ้นในการค้นหาไฟล์ที่มีขนาดเล็กลง แม้ว่าจะช้ากว่าต่อภาพ แต่ก็คุ้มค่าในขั้นตอนการสร้าง (build step) สำหรับภาพถ่ายที่เริ่มต้นเป็น PNG ขนาด 2 MB, WebP ที่คุณภาพ 80 มักจะมีขนาดต่ำกว่า 200 KB ในขณะที่ดูเหมือนกันเมื่อแสดงผลตามปกติ การวัดของ Google เองระบุว่า WebP มีขนาดเล็กกว่า JPEG ที่เทียบเคียงได้ประมาณ 25 ถึง 35 เปอร์เซ็นต์ ตาม WebP documentation
ใช้ตารางนี้เพื่อเลือกรูปแบบแทนการคาดเดา:
| Source content | Best format | Why |
|---|---|---|
| Photograph | WebP or JPEG | Smooth gradients compress well lossy |
| Logo, icon, flat UI | PNG or WebP lossless | Sharp edges stay crisp |
| Screenshot with text | PNG or lossless WebP | Avoids fuzzy text from lossy passes |
| Image needing transparency | WebP or PNG | JPEG cannot store an alpha channel |
หากคุณยังคงตัดสินใจเลือกระหว่างรูปแบบสำหรับเว็บไซต์ทั้งหมด การสรุปใน WebP vs JPEG vs PNG จะครอบคลุมการรองรับของเบราว์เซอร์และการแลกเปลี่ยนข้อดีข้อเสียอย่างละเอียดกว่า
การกำหนดขนาดไฟล์เป้าหมายด้วยการวนซ้ำ
"Make it under 200 KB" เป็นข้อกำหนดทั่วไปจากเครื่องมืออีเมล, marketplace, และขีดจำกัดการอัปโหลดของ CMS คุณไม่สามารถเลือกค่าคุณภาพที่ตรงกับเป้าหมายไบต์ได้ในการลองครั้งแรก เพราะคุณภาพเดียวกันจะให้ขนาดที่แตกต่างกันมากสำหรับภาพที่มีรายละเอียดสูงเทียบกับภาพเรียบๆ ให้วนลูปลดคุณภาพลงจากระดับสูงจนกว่าจะได้ขนาดต่ำกว่าขีดจำกัด:
อาร์กิวเมนต์ floor จะหยุดลูปก่อนที่คุณภาพจะลดลงจนอยู่ในระดับที่ไม่ชัดเจน (smear territory) หากรูปภาพไม่สามารถถึงเป้าหมายที่สูงกว่าค่า floor ได้ ฟังก์ชันก็จะยังคงส่งค่ากลับมาเพื่อให้คุณสามารถบันทึกข้อมูลและปรับขนาดรูปภาพแทนการบีบอัดให้หนักขึ้น สำหรับงบประมาณไบต์ที่กำหนด เช่น 100 KB หรือ 50 KB ลูปเดียวกันนี้ก็ใช้ได้เช่นกัน บทแนะนำใน compress images without losing quality อธิบายว่าเมื่อใดที่การปรับขนาดดีกว่าการลดคุณภาพ
จะทำให้ JPEG มีขนาดเล็กลงด้วย mozjpeg และ cwebp ได้อย่างไร?
Pillow บันทึก JPEG ด้วย libjpeg encoder มาตรฐาน mozgjpeg เป็น drop-in encoder จาก Mozilla ที่สร้างไฟล์ที่มีขนาดเล็กลงในคุณภาพทางสายตาที่เท่ากัน โดยปกติจะลดได้อีก 5 ถึง 15 เปอร์เซ็นต์ เนื่องจาก Pillow ไม่ได้รวมมันไว้ จึงต้องเรียกใช้ binary cjpeg ผ่าน subprocess ส่วน cjpeg ของ mozgjpeg สามารถอ่าน PPM ได้อย่างเชื่อถือ ดังนั้นให้ทำการ flatten รูปภาพด้วย Pillow ก่อน:
สำหรับ WebP การเรียกใช้ cwebp โดยตรงจะให้คุณเข้าถึงตัวควบคุมที่ Pillow ไม่ได้เปิดเผย เช่น -m 6 สำหรับความพยายามสูงสุด และ -sharp_yuv สำหรับขอบสีที่คมชัดยิ่งขึ้น:
นี่คือการเปรียบเทียบตัวเลือกต่างๆ เพื่อให้คุณตัดสินใจได้ว่าจะติดตั้งอะไร:
| Tool | Best for | Trade-off |
|---|---|---|
| Pillow | General scripting, every format | Not the smallest JPEG |
| mozjpeg | Smallest progressive JPEG | Extra binary, PPM round-trip |
| cwebp (libwebp) | Tightest WebP control | Separate binary to install |
| pillow-simd | Faster resizing on x86 servers | Harder to build and pin |
โปรเจกต์ mozgjpeg ได้จัดทำเอกสารเกี่ยวกับ encoder และ benchmarks ของมันในที่ mozjpeg repository และรายการตัวเลือกการบันทึกของ Pillow ทั้งหมดอยู่ใน Pillow image file formats reference
จะบีบอัดโฟลเดอร์จำนวนมากให้เร็วได้อย่างไร?
รูปภาพเดียวทำได้ง่าย งานที่แท้จริงคือไดเรกทอรีที่มีหลายร้อยไฟล์ คุณต้องปรับขนาดทุกอย่างให้แคบกว่าความต้องการของเลย์เอาต์ จากนั้นจึงทำการบีบอัด และรันงานข้ามเธรดเพื่อให้โฟลเดอร์ 500 รูปภาพเสร็จสิ้นภายในไม่กี่วินาทีแทนที่จะเป็นนาที

ข้อสังเกตเชิงปฏิบัติบางประการจากการใช้งานจริงในสภาพแวดล้อม Production:
- ปรับขนาดก่อนบีบอัด การเสิร์ฟภาพถ่าย 6000 px ให้กับคอลัมน์ 1200 px จะทำให้เสียไบต์ที่การตั้งค่าคุณภาพใด ๆ ก็ไม่สามารถกู้คืนได้
- Pillow จะปล่อย GIL ในระหว่างการเข้ารหัส ดังนั้นเธรดจึงช่วยเพิ่มความเร็วได้จริงที่นี่ คุณไม่จำเป็นต้องใช้ multiprocessing สำหรับโฟลเดอร์ส่วนใหญ่
- เขียนไปยังไดเรกทอรีเอาต์พุตแยกต่างหาก เพื่อให้แน่ใจว่าการรันที่ผิดพลาดจะไม่เขียนทับไฟล์ต้นฉบับของคุณ
- ใช้ Image.LANCZOS สำหรับการลดขนาด (downscaling) เพราะมันช่วยรักษาขอบให้คมชัดกว่าฟิลเตอร์เริ่มต้น
- บันทึกไฟล์ทุกไฟล์ด้วยตัวช่วย report และเก็บไฟล์ต้นฉบับไว้จนกว่าคุณจะได้ตรวจสอบตัวอย่างแล้ว
หากงานของคุณเป็นแบบที่ทำซ้ำ ๆ ไม่ใช่ครั้งเดียว รูปแบบใน batch image processing จะครอบคลุมเรื่องคิว (queues), การลองใหม่ (retries) และข้อกำหนดในการตั้งชื่อ สำหรับการรันโดยไม่ต้องใช้โค้ดกับไฟล์ zip, batch tool และ image converter จะจัดการการเปลี่ยนแปลงรูปแบบได้โดยไม่จำเป็นต้องมีสคริปต์
คุณควรเลือกแนวทางไหน?
ให้จับคู่วิธีการให้เข้ากับงาน แทนที่จะใช้เครื่องมือที่หนักที่สุดเสมอไป:
- รูปภาพ Web ในขั้นตอนการสร้าง (build step): ใช้ Pillow WebP ที่คุณภาพ 80 หรือใช้ cwebp ด้วย
-m 6เมื่อคุณต้องการเพิ่มอีกไม่กี่เปอร์เซ็นต์สุดท้าย - งบประมาณไบต์ที่เข้มงวด: ใช้ลูป
compress_to_target, และย้อนกลับไปใช้การปรับขนาดเมื่อถึงขีดจำกัดแล้ว - ระบบงาน JPEG แบบเก่าที่คุณไม่สามารถเปลี่ยนแปลงได้: ทำการเข้ารหัสผลลัพธ์ใหม่ด้วย mozjpeg เพื่อประหยัดพื้นที่ฟรี
- ภาพหน้าจอและแผนผัง: ใช้ PNG ที่มี
optimize=True, หรือใช้ WebP แบบไม่สูญเสียข้อมูล (lossless) หากเบราว์เซอร์ของคุณรองรับ
สำหรับทฤษฎีเบื้องหลังว่าทำไมการตั้งค่าเหล่านี้ถึงใช้งานได้จริง image compression guide ได้อธิบายเรื่อง lossy เทียบกับ lossless และวิธีที่ quantization tables ส่งผลต่อผลลัพธ์
ข้อผิดพลาดและการแก้ไขทั่วไป
ข้อยกเว้นเพียงไม่กี่ข้อเป็นสาเหตุของการทำงานที่ล้มเหลวส่วนใหญ่:
cannot write mode RGBA as JPEG— ให้เรียกใช้img.convert("RGB")ก่อนบันทึกเป็น JPEG.Image.DecompressionBombError— Pillow ป้องกันรูปภาพขนาดใหญ่มาก; ให้เพิ่มขีดจำกัดเฉพาะสำหรับไฟล์ที่คุณเชื่อถือด้วยImage.MAX_IMAGE_PIXELS = 200_000_000.OSError: broken data stream— ไฟล์ต้นฉบับถูกตัดทอน; ให้ตั้งค่าImageFile.LOAD_TRUNCATED_IMAGES = Trueเพื่อกู้คืน จากนั้นดาวน์โหลดซ้ำเมื่อเป็นไปได้.- ผลลัพธ์มีขนาดใหญ่กว่าอินพุต — คุณบันทึกไฟล์ JPEG ที่ถูกบีบอัดแล้วซ้ำ; ให้บีบอัดจากต้นฉบับ ไม่ใช่จากการส่งออกครั้งก่อน.
- สีดูจาง — ไฟล์ต้นฉบับที่เป็น CMYK ถูกบันทึกโดยไม่มีการแปลง; ให้เรียกใช้
convert("RGB")ก่อน.

ข้อสรุปที่สำคัญ
Pillow จัดการการบีบอัดภาพถึง 90 percent ใน Python ด้วยแฟล็ก JPEG สามตัวและ WebP save ให้ใช้ mojpeg และ cwebp เมื่อคุณต้องการไฟล์ที่มีขนาดเล็กที่สุด ห่อทุกอย่างด้วย target-size loop เมื่องบประมาณไบต์คงที่ และรันโฟลเดอร์ผ่านฟังก์ชัน batch แบบ threaded เมื่อปริมาณเพิ่มขึ้น เก็บไฟล์ต้นฉบับของคุณ ปรับขนาดก่อนที่คุณจะบีบอัด และพิมพ์จำนวนที่ประหยัดได้ในการรันทุกครั้ง เพื่อให้คุณทราบเสมอว่า pipeline กำลังทำอะไรอยู่จริง ๆ
ตัวอย่างโค้ดที่เก็บรักษาไว้
from PIL import Image
def compress_jpeg(src, dst, quality=80):
img = Image.open(src)
if img.mode in ("RGBA", "P"):
img = img.convert("RGB")
img.save(dst, "JPEG", quality=quality, optimize=True, progressive=True)
pip install Pillow
brew install webp mozjpeg # macOS; Linux: apt install webp, build mozjpeg
import os
def report(src, dst):
before, after = os.path.getsize(src), os.path.getsize(dst)
saved = (1 - after / before) * 100
print(f"{before/1024:.0f} KB -> {after/1024:.0f} KB ({saved:.0f}% smaller)")
def compress_png(src, dst):
Image.open(src).save(dst, "PNG", optimize=True, compress_level=9)
def to_webp(src, dst, quality=80):
img = Image.open(src)
img.save(dst, "WEBP", quality=quality, method=6)
def compress_to_target(src, dst, target_kb=200, q=90, floor=35):
img = Image.open(src).convert("RGB")
while q >= floor:
img.save(dst, "JPEG", quality=q, optimize=True, progressive=True)
if os.path.getsize(dst) <= target_kb * 1024:
return q
q -= 5
return q
import subprocess
def mozjpeg(src, dst, quality=80):
Image.open(src).convert("RGB").save("_tmp.ppm")
subprocess.run(["cjpeg", "-quality", str(quality), "-progressive",
"-optimize", "-outfile", dst, "_tmp.ppm"], check=True)
os.remove("_tmp.ppm")
def cwebp(src, dst, quality=82):
subprocess.run(["cwebp", "-q", str(quality), "-m", "6",
"-sharp_yuv", src, "-o", dst], check=True)
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
def batch(in_dir, out_dir, quality=80, max_width=1920):
out = Path(out_dir); out.mkdir(parents=True, exist_ok=True)
files = [p for p in Path(in_dir).iterdir()
if p.suffix.lower() in {".jpg", ".jpeg", ".png"}]
def work(p):
img = Image.open(p)
if img.width > max_width:
h = round(img.height * max_width / img.width)
img = img.resize((max_width, h), Image.LANCZOS)
img.convert("RGB").save(out / f"{p.stem}.jpg", "JPEG",
quality=quality, optimize=True, progressive=True)
with ThreadPoolExecutor() as pool:
list(pool.map(work, files))
return len(files)
from PIL import Image, ImageFile
Image.MAX_IMAGE_PIXELS = 200_000_000
ImageFile.LOAD_TRUNCATED_IMAGES = True
ใช้เครื่องมือฟรีของเราขณะทำตามคู่มือนี้
อ่านต่อ

Wed Mar 18 2026 20:00:00 GMT-0400 (北美东部夏令时间)
WebP Converter: วิธีแปลงรูปภาพเป็น WebP (พร้อมวัดขนาดจริง)
แปลงไฟล์ JPEG และ PNG ให้เป็น WebP เพื่อให้ได้ไฟล์เว็บที่มีขนาดเล็กลง ด้วยการวัดขนาดที่แม่นยำ คำสั่ง cwebp, วิธีใช้ Python และเบราว์เซอร์ รวมถึงกลยุทธ์สำรองสำหรับ JPEG/PNG

Tue Mar 17 2026 20:00:00 GMT-0400 (北美东部夏令时间)
PNG to WebP: วิธีแปลงและย่อขนาดรูปภาพ PNG
แปลง PNG เป็น WebP เพื่อให้ได้ไฟล์เว็บที่มีขนาดเล็กลง เรียนรู้ว่าเมื่อใดที่ WebP แบบ lossless จะดีกว่าแบบ lossy พร้อมดูขนาดจริง และคำสั่ง cwebp กับ Pillow รวมถึงการสำรองด้วย PNG.

Tue Mar 10 2026 20:00:00 GMT-0400 (北美东部夏令时间)
การปรับปรุง Image SEO: รายการตรวจสอบภาคปฏิบัติปี 2026
รายการตรวจสอบ Image SEO ที่ใช้งานได้จริงสำหรับปี 2026 ครอบคลุม alt text, ชื่อไฟล์, formats, compression, Core Web Vitals, structured data และวิธีการวัดผลอย่างละเอียด