2026-06-27 · Dikemas kini 2026-07-26
Mampatkan Imej dalam Python dengan Pillow, WebP, dan mozjpeg
Mampatkan imej JPEG, PNG, dan WebP dalam Python menggunakan Pillow, cwebp, dan mozjpeg. Ia menyokong tetapan kualiti, gelung saiz sasaran, dan skrip batch pantas.

Terakhir dikemas kini: July 26, 2026
Anda mempunyai folder JPEG bersaiz kamera, langkah binaan yang menghantarkannya kepada pengguna, dan bajet berat halaman yang terus membengkak. Memampatkan fail tersebut secara manual dalam penyunting imej tidak boleh diskalakan. Panduan ini menunjukkan skrip Python tepat yang anda perlukan untuk mengecilkan fail JPEG, PNG, dan WebP mengikut jadual, dalam pekerjaan CI, atau di dalam pengendali muat naik.
Jawapan ringkas: cara mampatkan imej dalam Python?
Buka imej menggunakan Pillow, kemudian simpan dengan bendera format yang betul. Untuk foto, simpan sebagai JPEG dengan quality=80, optimize=True, dan progressive=True. Untuk fail moden terkecil, simpan sebagai WebP dengan quality=80, method=6. Untuk grafik rata dan tangkapan skrin, kekalkan PNG dan masukkan optimize=True.
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)
Fungsi empat baris itu sudah boleh mengurangkan kebanyakan JPEG telefon dan DSLR sebanyak 40 hingga 70 percent. Baki panduan ini menambah sasaran saiz, WebP, mozjpeg, dan pelari kelompok (batch runner) supaya anda hanya perlu menunjukkannya pada direktori dan berjalan pergi.
Apa yang anda perlukan sebelum mula?
Anda memerlukan Python 3.9 atau versi yang lebih baharu dan Pillow, fork yang diselenggara bagi PIL. Pillow mengendalikan JPEG, PNG, dan WebP secara sedia ada pada setiap platform biasa.
pip install Pillow
Untuk output yang paling kecil, anda juga akan mahukan dua penyulitan baris perintah (command-line encoders) yang boleh dipanggil oleh Python: cwebp dari libwebp dan cjpeg dari mozjpeg.
brew install webp mozjpeg # macOS; Linux: apt install webp, build mozjpeg
Semak kegunaan setiap komponen sebelum anda menulis kod:
- Pillow membaca dan menulis setiap format serta melakukan pengecilan saiz (resizing).
- cwebp menghasilkan fail WebP yang paling padat dan mendedahkan lebih banyak penalaan berbanding Pillow.
- mozjpeg menyulitkan semula JPEG yang lebih kecil daripada libjpeg standard yang digunakan oleh Pillow.
- Pembantu pelaporan supaya setiap larian mencetak berapa banyak bait yang anda jimatkan.
Berikut adalah pembantu yang digunakan sepanjang panduan ini:
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)")
Jika anda hanya memerlukan pemampatan sekali sahaja dan tidak mahu memasang apa-apa, Pemampat Imej berasaskan pelayar web melakukan tugas yang sama untuk beberapa fail.
Bagaimana cara mampatkan JPEG dengan Pillow?
Tiga bendera yang penting untuk JPEG ialah quality, optimize, dan progressive. quality mengawal berapa banyak butiran yang dibuang oleh pengekod. optimize=True menjalankan laluan kedua untuk membina jadual Huffman yang lebih kecil. progressive=True menyusun semula fail supaya ia melukis dari atas ke bawah pada resolusi rendah dahulu, yang terasa lebih pantas pada sambungan perlahan dan biasanya mengecilkan saiz fail sedikit lagi.

Pilih nilai kualiti berdasarkan di mana imej itu digunakan, bukan satu nombor global tunggal:
| Nilai Kualiti | Kegunaan Biasa | Apa yang diharapkan |
|---|---|---|
| 90-95 | Imej hero, bukti cetakan | Hampir asli, fail lebih besar dengan ketara |
| 75-85 | Kebanyakan foto web | Tetapan lalai selamat, penjimatan besar |
| 60-70 | Ikon dan pratonton | Kelembutan yang kelihatan pada butiran halus |
| Di bawah 50 | Elakkan untuk foto | Artifak blok di sekeliling tepi |
Satu masalah yang sering membuatkan orang keliru: JPEG tidak mempunyai saluran alpha. Jika anda membuka tangkapan skrin PNG dengan ketelusan dan menyimpannya terus ke JPEG, Pillow akan memunculkan cannot write mode RGBA as JPEG. Panggilan convert("RGB") dalam fungsi terdahulu meratakan ketelusan ke latar belakang pepejal dahulu, itulah sebabnya ia dijalankan sebelum setiap simpanan JPEG.
Mampatkan PNG dan menukarnya kepada WebP
PNG adalah lossless, jadi anda tidak boleh menukar kualiti dengan saiz seperti yang anda lakukan dengan JPEG. Apa yang boleh anda lakukan ialah menjalankan pengoptimum Pillow dan, untuk apa-apa yang benar-benar foto, tukar format sepenuhnya.
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)
method=6 memberitahu pengekod WebP untuk meluangkan lebih banyak masa mencari fail yang lebih kecil. Ia lebih perlahan bagi setiap imej tetapi berbaloi dalam langkah binaan (build step). Untuk foto yang bermula sebagai PNG 2 MB, WebP pada kualiti 80 secara rutin berada di bawah 200 KB sambil kelihatan sama saiz pandangan biasa. Pengukuran Google sendiri meletakkan WebP kira-kira 25 hingga 35 peratus lebih kecil daripada JPEG yang setara, mengikut WebP documentation.
Gunakan jadual ini untuk memilih format berbanding meneka:
| Kandungan sumber | Format terbaik | Sebab |
|---|---|---|
| Foto | WebP atau JPEG | Gradien licin dimampatkan dengan baik secara lossy |
| Logo, ikon, UI rata | PNG atau WebP lossless | Tepi tajam kekal jernih |
| Tangkap layar dengan teks | PNG atau WebP lossless | Mengelakkan teks kabur daripada laluan lossy |
| Imej yang memerlukan lutsinar | WebP atau PNG | JPEG tidak boleh menyimpan saluran alfa |
Jika anda masih membuat keputusan antara format untuk keseluruhan laman web, pecahan dalam WebP vs JPEG vs PNG meliputi sokongan pelayar dan pertukaran (trade-offs) dengan lebih mendalam.
Menetapkan saiz fail sasaran dalam gelung (loop)
"Jadikan ia di bawah 200 KB" adalah keperluan biasa daripada alat e-mel, pasaran (marketplaces), dan had muat naik CMS. Anda tidak boleh memilih nombor kualiti yang mencapai sasaran byte pada percubaan pertama, kerana kualiti yang sama menghasilkan saiz yang sangat berbeza untuk foto yang sibuk berbanding yang rata. Gelung ke bawah dari kualiti tinggi sehingga anda berada di bawah had:
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
Argumen floor menghentikan gelung sebelum kualiti jatuh ke kawasan kabur (smear territory). Jika sesebuah imej tidak dapat mencapai sasaran di atas nilai floor, fungsi itu masih akan kembali supaya anda boleh mencatatnya dan mengubah saiz imej itu daripada memampatkan dengan lebih keras. Untuk bajet byte tetap seperti 100 KB atau 50 KB, gelung yang sama berfungsi; panduan dalam compress images without losing quality menjelaskan bila mengubah saiz mengatasi menurunkan kualiti.
Bagaimana memampatkan JPEG menjadi lebih kecil dengan mozjpeg dan cwebp?
Pillow menyimpan JPEG menggunakan pengekod libjpeg standard. mozjpeg ialah pengekod drop-in dari Mozilla yang menghasilkan fail lebih kecil pada kualiti visual yang sama, biasanya 5 hingga 15 peratus lagi. Oleh kerana Pillow tidak menyertakannya, panggil binari cjpeg melalui subprocess. cjpeg milik mozjpeg membaca PPM dengan boleh dipercayai, jadi ratakan imej dengan Pillow dahulu:
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")
Untuk WebP, memanggil cwebp secara langsung memberikan anda tetapan yang tidak didedahkan oleh Pillow, seperti -m 6 untuk usaha maksimum dan -sharp_yuv untuk tepi warna yang lebih bersih:
def cwebp(src, dst, quality=82):
subprocess.run(["cwebp", "-q", str(quality), "-m", "6",
"-sharp_yuv", src, "-o", dst], check=True)
Berikut adalah perbandingan pilihan supaya anda boleh memutuskan apa yang perlu dipasang:
| Alat | Terbaik untuk | Pertukaran |
|---|---|---|
| Pillow | Skrip am, setiap format | Bukan JPEG terkecil |
| mozjpeg | JPEG progresif terkecil | Binari tambahan, pusingan PPM |
| cwebp (libwebp) | Kawalan WebP paling ketat | Binari berasingan untuk dipasang |
| pillow-simd | Penyusunan saiz lebih pantas pada pelayan x86 | Lebih sukar dibina dan disemat |
Projek mozjpeg mendokumentasikan pengekod dan penanda arasnya dalam mozjpeg repository, dan senarai penuh pilihan simpan Pillow terdapat dalam Pillow image file formats reference.
Bagaimana cara mampatkan fail dalam folder secara pukal dengan pantas?
Imej tunggal adalah mudah. Tugas sebenar ialah direktori yang mengandungi ratusan fail. Saizkan semula apa sahaja yang lebih lebar daripada keperluan susun atur anda, kemudian mampatkan, dan jalankan kerja tersebut merentasi benang (threads) supaya folder 500 imej selesai dalam beberapa saat berbanding minit.

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)
Beberapa nota praktikal daripada menjalankan ini dalam persekitaran pengeluaran:
- Saizkan semula sebelum anda mampatkan. Menghantar foto 6000 px ke lajur 1200 px membazirkan bait yang tidak dapat dipulihkan oleh sebarang tetapan kualiti.
- Pillow melepaskan GIL semasa pengekodan (encode), jadi benang memberikan peningkatan kelajuan yang sebenar di sini; anda tidak memerlukan multiprocessing untuk kebanyakan folder.
- Tulis ke direktori keluaran berasingan supaya larian yang buruk tidak pernah menimpa fail asal anda.
- Gunakan
Image.LANCZOSuntuk pengecilan saiz (downscaling); ia mengekalkan tepi yang lebih tajam berbanding penapis lalai. - Log setiap fail dengan bantuan
reportdan simpan fail asal sehingga anda telah menyemak sampel secara visual.
Jika tugas anda adalah berulang (recurring) dan bukannya sekali sahaja, corak dalam batch image processing merangkumi giliran (queues), percubaan semula (retries), dan konvensyen penamaan. Untuk larian tanpa kod ke atas zip fail, Pemproses Kelompok dan Penukar Format mengendalikan perubahan format tanpa skrip.
Pendekatan manakah yang perlu anda pilih?
Padankan kaedah dengan tugasan, daripada sentiasa mencapai alat yang paling berat:
- Foto Web dalam langkah binaan: Pillow WebP pada kualiti 80, atau cwebp dengan
-m 6apabila anda mahukan peratus terakhir. - Bajet bait yang ketat: gelung
compress_to_target, kembali kepada saiz semula apabila had dicapai. - Pipa JPEG lama yang tidak boleh anda ubah: pra-kodkan semula output dengan mozjpeg untuk penjimatan percuma.
- Skrin tangkapan dan rajah: kekalkan PNG dengan
optimize=True, atau WebP tanpa kehilangan jika pelayar anda menyokongnya.
Untuk teori di sebalik mengapa tetapan ini berfungsi, panduan mampatan imej menerangkan lossy berbanding lossless dan bagaimana jadual kuantisasi mempengaruhi hasilnya.
Ralat dan Pembetulan Biasa
Beberapa pengecualian menyumbang kepada kebanyakan larian yang gagal:
cannot write mode RGBA as JPEG— panggilimg.convert("RGB")sebelum menyimpan ke JPEG.Image.DecompressionBombError— Pillow melindungi daripada imej yang besar; tingkatkan had hanya untuk fail yang anda percayai denganImage.MAX_IMAGE_PIXELS = 200_000_000.OSError: broken data stream— fail sumber telah terpotong (truncated); tetapkanImageFile.LOAD_TRUNCATED_IMAGES = Trueuntuk menyelamatkannya, kemudian muat turun semula apabila mungkin.- Output lebih besar daripada input — anda telah menyimpan semula JPEG yang sudah dimampatkan; mampatkan dari asal, bukan eksport sebelumnya.
- Warna kelihatan pudar — sumber CMYK telah disimpan tanpa penukaran; panggil
convert("RGB")dahulu.
from PIL import Image, ImageFile
Image.MAX_IMAGE_PIXELS = 200_000_000
ImageFile.LOAD_TRUNCATED_IMAGES = True
Intipati Utama
Pillow mengendalikan 90 persen pemampatan gambar dalam Python dengan tiga bendera JPEG dan simpanan WebP. Gunakan mozjpeg dan cwebp apabila anda memerlukan fail sekecil mungkin, bungkus semuanya dalam gelung target-size apabila bajet byte ditetapkan, dan jalankan folder melalui fungsi batch berbenang apabila isipadu bertambah. Simpan fail asal anda, ubah saiz sebelum anda mampatkan, dan cetak penjimatan pada setiap larian supaya anda sentiasa tahu apa yang sebenarnya dilakukan oleh paip tersebut.
Gunakan alat percuma kami semasa mengikuti panduan ini.
Teruskan membaca

2026-08-01
Mampatan Imej 2026: WebP, AVIF, JPEG XL & JPEG AI Diuji
Saya menanda aras WebP, AVIF, dan JPEG XL pada 4 foto sebenar. WebP jimat 32% lwn JPEG, AVIF 65%, JPEG XL 30%. Data penuh, sokongan pelayar, dan pilihan format 2026.

2026-07-26
Senarai Semak Pengoptimuman Imej: Setiap Langkah untuk Imej Web Pantas
Senarai semak pengoptimuman imej lengkap: pilihan format, mengubah saiz, mampatan (compression), penghantaran responsif, lazy loading, dan persediaan CDN. Laksanakan senarai ini sebelum setiap penerbitan.

2026-07-26
Cara Memampatkan Imej di Bawah 100KB Tanpa Merosakkan Kualiti
Tukar saiz ke lebar paparan, kemudian eksport WebP. Saiz fail terukur bagi foto telefon, produk dan tangkap layar membuktikan resipi agar setiap satu di bawah 100KB.