Python使用PIL庫實(shí)現(xiàn)高質(zhì)量圖片縮放功能
縮放圖片是圖片處理中最常見的操作,但很多人直接用 resize() 默認(rèn)參數(shù),結(jié)果圖片模糊、鋸齒嚴(yán)重。本文講清楚 PIL 縮放時如何保證高質(zhì)量輸出。
一、先看效果對比
同一張圖縮小到 800×600,不同參數(shù)的效果:
| 方式 | 效果 |
|---|---|
| 默認(rèn)(BILINEAR) | 邊緣模糊,細(xì)節(jié)丟失 |
| BICUBIC | 稍好,但仍有鋸齒 |
| LANCZOS | 清晰銳利,細(xì)節(jié)保留最好 |
| NEAREST | 像素塊狀,僅適合像素畫 |
二、核心:指定resample參數(shù)
PIL 的 resize() 默認(rèn)用 BILINEAR,質(zhì)量一般。高質(zhì)量縮放只需加一個參數(shù):
from PIL import Image
img = Image.open("大圖.jpg")
# ? 默認(rèn)(質(zhì)量一般)
small = img.resize((800, 600))
# ? 高質(zhì)量(推薦)
small = img.resize((800, 600), resample=Image.LANCZOS)
一句話:加上 resample=Image.LANCZOS,就夠了。
三、所有濾波器對比
| 濾波器 | 寫法 | 質(zhì)量 | 速度 | 適用場景 |
|---|---|---|---|---|
| NEAREST | Image.NEAREST | ? | 最快 | 像素畫、標(biāo)簽圖 |
| BILINEAR | Image.BILINEAR | ?? | 快 | 實(shí)時預(yù)覽(默認(rèn)) |
| BICUBIC | Image.BICUBIC | ??? | 中等 | 一般用途 |
| LANCZOS | Image.LANCZOS | ????? | 較慢 | 最終輸出 |
結(jié)論:只要不是追求速度,無腦選 LANCZOS。
四、PIL 版本差異
PIL 10.0+(2024年后)寫法有變化:
# 舊版本(< 10.0) img.resize((800, 600), resample=Image.LANCZOS) # 新版本(>= 10.0) img.resize((800, 600), resample=Image.Resampling.LANCZOS)
兩種都能用,新版本更規(guī)范。
五、保存時也要注意質(zhì)量
縮放完保存 JPEG 時,默認(rèn) quality=75,會再次壓縮導(dǎo)致模糊。保存時也要指定質(zhì)量:
small.save("out.jpg", quality=95, subsampling=0)
| 參數(shù) | 作用 | 推薦值 |
|---|---|---|
quality | JPEG 壓縮質(zhì)量 | 90~95 |
subsampling | 色度采樣,0=不采樣 | 0(最高質(zhì)量) |
optimize | 優(yōu)化文件大小 | True |
六、完整高質(zhì)量流程
from PIL import Image
img = Image.open("大圖.jpg")
# 1. 縮放(LANCZOS 保證縮放質(zhì)量)
small = img.resize((800, 600), resample=Image.LANCZOS)
# 2. 保存(quality=95 保證保存質(zhì)量)
small.save("小圖.jpg", quality=95, subsampling=0, optimize=True)
三步:LANCZOS 縮 → quality=95 存 → subsampling=0 禁色度采樣。
七、放大圖片也用 LANCZOS
很多人以為放大該用 NEAREST 保持像素感,錯。LANCZOS 放大同樣最優(yōu):
# 放大 2 倍,依然用 LANCZOS big = img.resize((4000, 3000), resample=Image.LANCZOS)
NEAREST 放大只會出現(xiàn)馬賽克,LANCZOS 放大細(xì)節(jié)更自然。
八、常見坑
| 坑 | 原因 | 解決 |
|---|---|---|
| 縮放后模糊 | 沒加 resample,默認(rèn) BILINEAR | resample=Image.LANCZOS |
| 保存后更模糊 | JPEG quality 默認(rèn) 75 | quality=95 |
| 顏色發(fā)灰 | 色度采樣 subsampling=1 | subsampling=0 |
| PIL 10+ 報錯 | 舊寫法不兼容 | 用 Image.Resampling.LANCZOS |
| 透明圖縮放后變黑 | RGBA 轉(zhuǎn) RGB 丟失透明 | 用 Image.new("RGBA", ...) 保持模式 |
九、知識擴(kuò)展
在 Python 中使用 Pillow 庫對圖片進(jìn)行高質(zhì)量縮放,關(guān)鍵就在于選擇適合的重采樣算法。
核心:選擇合適的重采樣算法 (Resampling Filter)
resize() 方法包含一個 resample 參數(shù),用于指定重采樣算法,不同的算法直接影響最終圖片的質(zhì)量和處理速度。以下是常見濾鏡的對比:
Image.NEAREST (最近鄰插值):速度最快,質(zhì)量最低,常用于像素藝術(shù)風(fēng)格的縮放。不推薦用于常規(guī)照片。
Image.BILINEAR (雙線性插值):在速度和質(zhì)量間取得良好平衡,比 NEAREST 平滑很多。resize() 的默認(rèn)算法是 Image.BICUBIC,并不是它。
Image.BICUBIC (雙三次插值):比 BILINEAR 質(zhì)量更高,能更好地保留圖像細(xì)節(jié),是默認(rèn)的重采樣算法。
Image.LANCZOS (Lanczos 采樣):在 Pillow 中質(zhì)量最高的重采樣濾鏡,特別適合將大尺寸圖片縮小為小圖(high-quality downsampling)。
- 它能提供比 BICUBIC 更銳利的邊緣和保留更多細(xì)節(jié),效果拔群。
- 注意:早期版本中的
Image.ANTIALIAS常量已被棄用,現(xiàn)在是Image.LANCZOS的別名,都指向了相同的高質(zhì)量算法。
簡單總結(jié),追求極致效果(尤其是縮小圖片)用 LANCZOS,追求速度和質(zhì)量平衡則用 BICUBIC。
高質(zhì)量縮放實(shí)戰(zhàn)案例
1. 基礎(chǔ)縮放:精確指定尺寸
這是最常見的操作,直接將原圖縮放到指定的寬和高。
from PIL import Image
def resize_exact_size(input_path, output_path, new_size):
"""
將圖片精確縮放到指定尺寸 (寬度, 高度)
:param input_path: 輸入圖片路徑
:param output_path: 輸出圖片路徑
:param new_size: 新的尺寸 (寬度, 高度)
"""
try:
with Image.open(input_path) as img:
# Image.LANCZOS 是最高質(zhì)量的濾鏡
resized_img = img.resize(new_size, Image.LANCZOS)
resized_img.save(output_path)
print(f"圖片已成功保存至 {output_path}")
except Exception as e:
print(f"處理圖片時出錯: {e}")
# 使用示例
resize_exact_size("input.jpg", "output_800x600.jpg", (800, 600))resize() 方法會基于原圖創(chuàng)建一個新的縮放后的副本,而原圖保持不變。縮放時可以清晰看到 LANCZOS 提供的平滑過渡與更豐富的細(xì)節(jié)。
2. 保持縱橫比縮放:固定新寬度或高度
當(dāng)只想固定一個尺寸(比如寬度)時,需要手動計算另一個尺寸。
from PIL import Image
def resize_fixed_width(input_path, output_path, target_width):
"""
固定寬度,高度按原圖比例自動縮放
:param input_path: 輸入圖片路徑
:param output_path: 輸出圖片路徑
:param target_width: 目標(biāo)寬度
"""
try:
with Image.open(input_path) as img:
original_width, original_height = img.size
# 按比例計算新的高度
target_height = int(original_height * (target_width / original_width))
new_size = (target_width, target_height)
resized_img = img.resize(new_size, Image.LANCZOS)
resized_img.save(output_path)
print(f"圖片已保存,新尺寸為 {new_size}")
except Exception as e:
print(f"處理圖片時出錯: {e}")
# 示例:固定寬度為 800 像素
resize_fixed_width("input.jpg", "output_width800.jpg", 800)這種方式的優(yōu)勢在于圖片絕不會被拉伸變形,能完美保留原始構(gòu)圖。
3. 生成縮略圖:限制最大寬高
thumbnail() 方法與 resize() 不同,它會在不改變原圖縱橫比的前提下,將圖片縮小到指定的最大范圍內(nèi)。它直接修改原 Image 對象,不返回新對象。
from PIL import Image
def create_thumbnail(input_path, output_path, max_size):
"""
創(chuàng)建縮略圖,確保其尺寸不超過 (max_width, max_height)
:param input_path: 輸入圖片路徑
:param output_path: 輸出圖片路徑
:param max_size: 最大尺寸 (最大寬度, 最大高度)
"""
try:
with Image.open(input_path) as img:
# thumbnail() 會直接修改 img 對象本身
img.thumbnail(max_size, Image.LANCZOS)
img.save(output_path)
print(f"縮略圖已保存,實(shí)際尺寸為 {img.size}")
except Exception as e:
print(f"處理圖片時出錯: {e}")
# 示例:創(chuàng)建一個最大邊長為 400x400 的縮略圖
create_thumbnail("input.jpg", "thumbnail_400x400.jpg", (400, 400))thumbnail() 專用于生成等比的、不超過指定最大尺寸的圖片,非常適合制作網(wǎng)頁預(yù)覽圖或頭像。配合 ImageOps.fit() 可以實(shí)現(xiàn)更精確的封面圖裁剪。
關(guān)鍵注意事項(xiàng)
- 版本兼容性:確保
resample參數(shù)使用Image.LANCZOS,這是當(dāng)前及未來版本的標(biāo)準(zhǔn)寫法。 - 保存圖片質(zhì)量:使用
resize()等操作后,如果仍用默認(rèn)的quality參數(shù)保存,會導(dǎo)致畫質(zhì)再次下降。建議在save()時顯式設(shè)置,如quality=95。 - 圖片模式轉(zhuǎn)換:直接對 PNG 圖片(RGBA 模式)使用
resize(),再保存為 JPEG 格式會報錯。建議統(tǒng)一轉(zhuǎn)換模式:img.convert("RGB")。 - 形狀和內(nèi)存:
resize()返回新的Image對象,需用新變量保存。處理超大圖片時,可先用img.draft()方法預(yù)覽縮放,減少內(nèi)存占用。
完整示例:一個通用的圖片縮放函數(shù)
結(jié)合上述技巧,可以將其封裝成一個靈活的函數(shù)。
from PIL import Image
def resize_image(input_path, output_path, new_size,
keep_aspect=False, use_thumbnail=False, quality=95):
"""
通用的圖片縮放函數(shù)
:param input_path: 輸入圖片路徑
:param output_path: 輸出圖片路徑
:param new_size: 目標(biāo)尺寸,可為 (width, height) 或 (max_width, max_height)
:param keep_aspect: 是否保持縱橫比
:param use_thumbnail: 是否使用 thumbnail 方法 (僅縮小)
:param quality: 輸出圖片的質(zhì)量 (1-100),用于 JPEG
"""
try:
with Image.open(input_path) as img:
# RGBA 轉(zhuǎn) RGB,以防保存為 JPEG 時出錯
if img.mode == 'RGBA' and output_path.lower().endswith('.jpg'):
img = img.convert('RGB')
if use_thumbnail:
# 使用 thumbnail,它會自動保持縱橫比
img.thumbnail(new_size, Image.LANCZOS)
img.save(output_path, quality=quality)
elif keep_aspect:
# 固定寬度或高度,計算另一維
original_width, original_height = img.size
target_width, target_height = new_size
# 判斷是基于寬還是高進(jìn)行縮放
if target_width:
new_h = int(original_height * (target_width / original_width))
final_size = (target_width, new_h)
elif target_height:
new_w = int(original_width * (target_height / original_height))
final_size = (new_w, target_height)
else:
final_size = new_size
resized_img = img.resize(final_size, Image.LANCZOS)
resized_img.save(output_path, quality=quality)
else:
# 精確縮放
resized_img = img.resize(new_size, Image.LANCZOS)
resized_img.save(output_path, quality=quality)
print(f"處理完成:{output_path}")
except Exception as e:
print(f"處理失?。簕e}")
# 示例
# 1. 精確縮放到 800x600
# resize_image("input.jpg", "output_exact.jpg", (800, 600), keep_aspect=False)
# 2. 固定寬度 800,高度按比例
# resize_image("input.jpg", "output_fixed_width.jpg", (800, None), keep_aspect=True)
# 3. 生成一個最大邊長為 400x400 的縮略圖
# resize_image("input.jpg", "output_thumbnail.jpg", (400, 400), use_thumbnail=True)好的總結(jié)能大大降低你的試錯成本。這里有個簡單的對比:追求極致畫質(zhì),尤其是縮小圖片時,優(yōu)先用 LANCZOS;對速度要求高于畫質(zhì)時,可選 BICUBIC;需要等比縮略圖時,thumbnail() 配合 LANCZOS 是絕佳組合。如果批量處理圖片,可以用一個循環(huán)來遍歷文件夾中的所有圖片文件~
十、總結(jié)
| 操作 | 關(guān)鍵參數(shù) |
|---|---|
| 縮放 | resample=Image.LANCZOS |
| 保存 JPEG | quality=95, subsampling=0 |
| 保存 PNG | 直接存,PNG 無損 |
| 放大 | 同樣用 LANCZOS,別用 NEAREST |
記住一句話:resize 加 LANCZOS,save 加 quality=95,圖片質(zhì)量就有保障了。
到此這篇關(guān)于Python使用PIL庫實(shí)現(xiàn)高質(zhì)量圖片縮放功能的文章就介紹到這了,更多相關(guān)Python圖片縮放內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python項(xiàng)目開發(fā)報錯查看與排雷的新手小白手冊
對于剛接觸Python的初學(xué)者來說,屏幕上突然跳出的一大堆紅色英文字符往往令人感到恐慌,本篇手冊將帶你系統(tǒng)地認(rèn)識Python的報錯信息,教你如何像偵探一樣閱讀線索并總結(jié)初學(xué)者最容易遇到的幾類錯誤,希望對大家有所幫助2026-03-03
Python寫的Discuz7.2版faq.php注入漏洞工具
這篇文章主要介紹了Python寫的Discuz7.2版faq.php注入漏洞工具,全自動的一款注入工具,針對Discuz7.2版,需要的朋友可以參考下2014-08-08
使用Python的networkx繪制精美網(wǎng)絡(luò)圖教程
今天小編就為大家分享一篇使用Python的networkx繪制精美網(wǎng)絡(luò)圖教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11
python 列表推導(dǎo)和生成器表達(dá)式的使用
這篇文章主要介紹了python 列表推導(dǎo)和生成器表達(dá)式的使用方法,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-02-02
sklearn中的交叉驗(yàn)證的實(shí)現(xiàn)(Cross-Validation)
這篇文章主要介紹了sklearn中的交叉驗(yàn)證的實(shí)現(xiàn)(Cross-Validation),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
Python基于callable函數(shù)檢測對象是否可被調(diào)用
這篇文章主要介紹了Python基于callable函數(shù)檢測對象是否可被調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10

