基于Python實(shí)現(xiàn)png轉(zhuǎn)webp的命令行工具
前言
網(wǎng)頁上使用webp格式的圖片更加省網(wǎng)絡(luò)流量和存儲空間,但本地圖片一般是png格式的,所以考慮用python的pillow庫將png格式的圖片轉(zhuǎn)換為webp格式。
需求:
- 可以在系統(tǒng)任意地方調(diào)用。這需要編譯成二進(jìn)制程序或?qū)懗赡_本放到PATH環(huán)境變量下
- 支持指定圖片文件輸入目錄。默認(rèn)為當(dāng)前目錄。
- 支持指定圖片文件輸出目錄。默認(rèn)為輸入文件的同級目錄。
- 支持指定圖片壓縮質(zhì)量。默認(rèn)為80。需要校驗(yàn)傳參。
- 支持并發(fā)同時壓縮多個圖片文件。默認(rèn)為串行。傳參的并發(fā)數(shù)最大為CPU核心數(shù)。
代碼
from PIL import Image
import argparse
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
import os
from time import time
def parse_args():
"""解析命令行參數(shù)"""
parser = argparse.ArgumentParser(description="Convert PNG to WEBP",
usage="""
# 直接執(zhí)行, 默認(rèn)轉(zhuǎn)換當(dāng)前目錄下的所有png文件到同級目錄
python main.py
# 將轉(zhuǎn)換后的webp文件保存到output目錄下
python main.py -o output
# 轉(zhuǎn)換單個png文件, 單獨(dú)轉(zhuǎn)換時不支持指定輸出目錄
python main.py -f 1.png
# 同時轉(zhuǎn)換, -t 指定最大并發(fā)數(shù), 默認(rèn)為1, 最大不得超過CPU核心數(shù)
python main.py -t 2
# 指定圖片壓縮質(zhì)量, 默認(rèn)為80, 取值區(qū)間為[0, 100], 值越高, 質(zhì)量越好, 生成圖片體積越大
python main.py -q 75
""")
parser.add_argument(
"-i", type=str, default=os.getcwd(), help="Path to the input PNG image"
)
parser.add_argument(
"-o", type=str, default=os.getcwd(), help="Path to the output WEBP image"
)
parser.add_argument("-f", type=str, default="", help="specific file name")
parser.add_argument("-t", type=int, default=1, help="Number of threads to use")
parser.add_argument(
"-q", type=int, default=80, help="Quality of the output WEBP image"
)
return parser.parse_args()
def convert_png_to_webp(input_path: Path, output_path: Path, quality=80) -> None:
"""
轉(zhuǎn)換PNG為WEBP
Args:
input_path (Path): 輸入文件路徑
output_path (Path): 輸出文件路徑, 可以是一個目錄, 也可以是一個webp文件的路徑
quality (int, optional): 圖片壓縮質(zhì)量. 默認(rèn)為 80.
"""
# 如果quality不在0到100之間, 則設(shè)置為80
if quality > 100 or quality < 0:
print("quality must be between 0 and 100, now set to 80")
real_q = quality if quality <= 100 and quality > 0 else 80
# 如果輸入文件不存在, 則打印錯誤信息并返回
if not input_path.exists():
print(f"input file {input_path} not found")
return
# 如果指定了輸出目錄, 則嘗試創(chuàng)建輸出目錄
if not output_path.exists() and output_path.suffix.lower() != ".webp":
try:
output_path.mkdir(parents=True)
except Exception as e:
print(e)
print("Failed to create output directory")
return
# 如果指定了輸出目錄, 則修改輸出文件名為為輸入文件名, 并修改擴(kuò)展名為.webp
if output_path.suffix.lower() != ".webp":
output_path = output_path / input_path.with_suffix(".webp").name
start = time()
try:
with Image.open(input_path) as img:
print(
f"Converting {input_path}, quality={real_q}, size: {input_path.stat().st_size / 1024:.2f}KB"
)
img.save(output_path, "WEBP", quality=real_q)
print(
f"Convert png2webp successfully, output file: {output_path.name}, size: {int(output_path.stat().st_size) / 1024:.2f}KB, elapsed time: {time() - start:.2f}s"
)
except Exception as e:
print(f"Convert png2webp failed: {e}")
def multi_thread_convert(max_workers: int, input_path, output_path, quality) -> None:
"""并發(fā)轉(zhuǎn)換png為webp"""
print(f"convert png to webp with multi threads, max_workers: {max_workers}")
p = Path(input_path)
op = Path(output_path) if output_path != os.getcwd() else None
max_workers = max_workers if max_workers < os.cpu_count() else os.cpu_count()
with ThreadPoolExecutor(max_workers=max_workers) as executor:
for f in p.glob("**/*.png"):
executor.submit(
convert_png_to_webp, f, op or f.with_suffix(".webp"), quality
)
def main():
start = time()
args = parse_args()
if not args.f:
if args.t > 1:
multi_thread_convert(args.t, args.i, args.o, args.q)
else:
p = Path(args.i)
op = Path(args.o) if args.o != os.getcwd() else None
for f in p.glob("**/*.png"):
convert_png_to_webp(f, op or f.with_suffix(".webp"), args.q)
else:
p = Path(args.f)
convert_png_to_webp(p, p.with_suffix(".webp"), args.q)
print(f"Finished! Total elapsed time: {time() - start:.2f}s")
if __name__ == "__main__":
main()
編譯
因?yàn)槭窃趐ython虛擬環(huán)境中安裝的pillow,如果要在其它位置調(diào)用這個腳本,個人想了兩種方式:
- 另外編寫一個shell腳本,如果是windows,則編寫powershell腳本,在這個腳本內(nèi)編寫調(diào)用邏輯,并把這個腳本放到
PATH環(huán)境變量的路徑下。 - 編譯成二進(jìn)制文件,將編譯好的二進(jìn)制文件放到
PATH環(huán)境變量下。這比較方便發(fā)送給別人,這樣別人就不需要在電腦上安裝python環(huán)境。
這里用pyinstaller將程序編譯成二進(jìn)制文件,盡量在python虛擬環(huán)境下編譯,以減小二進(jìn)制文件的體積
1.創(chuàng)建虛擬環(huán)境
python -m venv png2webp
2.激活虛擬環(huán)境
# linux cd png2webp source ./bin/activate # windows powershell cd png2webp .\Scripts\activate
3.安裝依賴
python -m pip install pillow pyinstaller
4.編譯。注意修改實(shí)際的python文件路徑。
pyinstaller -F --clean .\main.py
5.生成的二進(jìn)制文件在當(dāng)前目錄下的dist目錄,將其放置到PATH環(huán)境變量下,如有需要可重命名。
6.測試在其他目錄下調(diào)用
png2webp --help
使用
# 直接執(zhí)行, 默認(rèn)轉(zhuǎn)換當(dāng)前目錄下的所有png文件到同級目錄 png2webp # 將轉(zhuǎn)換后的webp文件保存到output目錄下 png2webp -o output # 轉(zhuǎn)換單個png文件, 單獨(dú)轉(zhuǎn)換時不支持指定輸出目錄 png2webp -f 1.png # 同時轉(zhuǎn)換, -t 指定最大并發(fā)數(shù), 默認(rèn)為1, 最大不得超過CPU核心數(shù) png2webp -t 2 # 指定圖片壓縮質(zhì)量, 默認(rèn)為80, 取值區(qū)間為[0, 100], 值越高, 質(zhì)量越好, 生成圖片體積越大 png2webp -q 75
到此這篇關(guān)于基于Python實(shí)現(xiàn)png轉(zhuǎn)webp的命令行工具 的文章就介紹到這了,更多相關(guān)Python png轉(zhuǎn)webp內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python通過對字典的排序,對json字段進(jìn)行排序的實(shí)例
今天小編就為大家分享一篇python通過對字典的排序,對json字段進(jìn)行排序的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
Python判斷遠(yuǎn)程服務(wù)器上Excel文件是否被人打開的方法
這篇文章主要介紹了Python如何判斷遠(yuǎn)程服務(wù)器上Excel文件是否被人打開,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07
使用Folium在Python中進(jìn)行地圖可視化的操作指南
在數(shù)據(jù)分析和可視化領(lǐng)域,地圖可視化是一項(xiàng)非常重要的技能,它能夠幫助我們更直觀地理解和展示地理空間數(shù)據(jù),Folium是一個基于Python的地圖可視化庫,本文將詳細(xì)介紹如何使用Folium在Python中進(jìn)行地圖可視化,需要的朋友可以參考下2025-03-03
python調(diào)用文字識別OCR輕松搞定驗(yàn)證碼
本文主要介紹了python調(diào)用文字識別OCR輕松搞定驗(yàn)證碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11
python機(jī)器學(xué)習(xí)之隨機(jī)森林(七)
這篇文章主要為大家詳細(xì)介紹了python機(jī)器學(xué)習(xí)之隨機(jī)森林,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03
Python中字典和列表的索引效率分析及實(shí)戰(zhàn)結(jié)果
Python中的索引是一種訪問數(shù)據(jù)結(jié)構(gòu)中特定元素的方法,它在各種數(shù)據(jù)類型中都有應(yīng)用,包括字符串、列表、元組和字典,這篇文章主要介紹了Python中字典和列表的索引效率分析及實(shí)戰(zhàn)結(jié)果的相關(guān)資料,需要的朋友可以參考下2026-03-03

