Python實現(xiàn)批量圖片轉(zhuǎn)GIF動圖(附源代碼)
本文分享如何實現(xiàn) 批量圖片轉(zhuǎn) GIF 動圖:
關(guān)鍵內(nèi)容
- 支持 PNG/JPG/BMP 等主流圖片格式,自動過濾非圖片文件;
- 參數(shù)靈活配置輸入目錄、輸出路徑、GIF 幀率(FPS)、圖像名稱順序和循環(huán)次數(shù);
- 自動處理圖片格式兼容問題,并包含完善的異常提示。
- 多維度輕量化壓縮,支持 0.1-1.0 縮放因子調(diào)整圖片大小。
運行效果:

簡潔版
首先分享的是簡潔版,一個批量圖片轉(zhuǎn)GIF動圖的Python腳本,基于PIL庫實現(xiàn)。
代碼的參數(shù)配置:
| 階段 | 關(guān)鍵操作 | 說明 |
|---|---|---|
| 參數(shù)解析 | argparse | 支持輸入目錄、輸出路徑、FPS、循環(huán)次數(shù)、排序方式 |
| 文件篩選 | os.listdir + 后綴過濾 | 僅保留支持的5種圖片格式 |
| 智能排序 | re.search(r'\d+') | 提取文件名中的數(shù)字進(jìn)行排序,處理如 frame_001.png |
| 圖像處理 | Image.open → convert('RGB') | 統(tǒng)一轉(zhuǎn)RGB,解決透明通道兼容問題 |
| GIF生成 | images[0].save(save_all=True) | 首幀保存,其余幀append |
| 目錄處理 | os.makedirs(exist_ok=True) | 自動創(chuàng)建不存在的輸出目錄 |
思路流程:

源代碼:
import os
import argparse
import re
from PIL import Image
def create_gif(image_folder, output_path, fps=10, loop=0, sort_order='asc'):
"""
從指定目錄的圖片創(chuàng)建GIF動圖
參數(shù):
image_folder (str): 圖片目錄路徑
output_path (str): GIF輸出路徑
fps (int/float): 每秒幀數(shù),默認(rèn)0.5
loop (int): 循環(huán)次數(shù)(0=無限),默認(rèn)0
sort_order (str): 排序方式(asc=升序/desc=降序),默認(rèn)asc
"""
# 支持的圖片格式
IMAGE_EXTS = ('.png', '.jpg', '.jpeg', '.bmp', '.webp')
# 篩選目錄內(nèi)的圖片文件
image_files = [
os.path.join(image_folder, f)
for f in os.listdir(image_folder)
if f.lower().endswith(IMAGE_EXTS)
]
if not image_files:
raise ValueError(f"目錄 '{image_folder}' 未找到圖片文件")
# 提取文件名中的數(shù)字作為排序依據(jù)
def sort_key(filename):
basename = os.path.basename(filename)
match = re.search(r'\d+', basename)
return int(match.group()) if match else basename
# 根據(jù)參數(shù)切換升/降序排序
reverse_flag = True if sort_order == 'desc' else False
image_files.sort(key=sort_key, reverse=reverse_flag)
# 打印排序后的圖片列表
print(f"找到 {len(image_files)} 張圖片,排序方式: {sort_order}")
for i, f in enumerate(image_files):
print(f" {i+1}. {os.path.basename(f)}")
# 打開并處理圖片(轉(zhuǎn)RGB兼容透明通道)
images = []
for img_path in image_files:
try:
img = Image.open(img_path)
img = img.convert('RGB') # 統(tǒng)一轉(zhuǎn)為RGB模式
images.append(img)
except Exception as e:
print(f"警告: 無法打開圖片 {img_path} - {e}")
if not images:
raise ValueError("無可用圖片文件")
# 計算每幀持續(xù)時間(毫秒)
duration = 1000 / fps
# 保存GIF
images[0].save(
output_path,
save_all=True,
append_images=images[1:],
duration=duration,
loop=loop
)
# 打印生成結(jié)果
print(f"\nGIF已保存至: {output_path}")
print(f"幀率: {fps} FPS | 圖片數(shù)量: {len(images)} | 循環(huán)次數(shù): {'無限' if loop == 0 else loop}")
def main():
# 命令行參數(shù)解析
parser = argparse.ArgumentParser(description='批量圖片轉(zhuǎn)GIF動圖工具')
parser.add_argument('--input_dir', default='./coco_test/', help='輸入圖片目錄(默認(rèn): ./coco_test/)')
parser.add_argument('--output_file', default='Output_GIF/coco_test-202601.gif', help='輸出GIF文件路徑')
parser.add_argument('-f', '--fps', type=float, default=0.5, help='每秒幀數(shù)(默認(rèn): 0.5)')
parser.add_argument('-l', '--loop', type=int, default=0, help='循環(huán)次數(shù)(0=無限,默認(rèn): 0)')
parser.add_argument('-s', '--sort_order', choices=['asc', 'desc'], default='asc', help='排序方式(asc=升序/desc=降序,默認(rèn): asc)')
args = parser.parse_args()
# 校驗輸入目錄是否存在
if not os.path.isdir(args.input_dir):
print(f"錯誤: 輸入目錄 '{args.input_dir}' 不存在")
return
# 自動補全GIF擴展名
if not args.output_file.lower().endswith('.gif'):
args.output_file += '.gif'
# 自動創(chuàng)建輸出目錄(如果不存在)
output_dir = os.path.dirname(args.output_file)
if output_dir and not os.path.exists(output_dir):
os.makedirs(output_dir, exist_ok=True)
print(f"提示: 自動創(chuàng)建輸出目錄 '{output_dir}'")
# 生成GIF
try:
create_gif(args.input_dir, args.output_file, args.fps, args.loop, args.sort_order)
except Exception as e:
print(f"錯誤: {e}")
if __name__ == "__main__":
main()
打印信息:
找到 5 張圖片,排序方式: asc
1. 000000000030.jpg
2. 000000000034.jpg
3. 000000000192.jpg
4. 000000000247.jpg
5. 000000000307.jpg
GIF已保存至: Output_GIF/coco_test-202601.gif
幀率: 0.5 FPS | 圖片數(shù)量: 5 | 循環(huán)次數(shù): 無限
運行效果:

專業(yè)版
這是一個增強版批量圖片轉(zhuǎn)GIF工具,相比之前的基礎(chǔ)版本,新增了壓縮優(yōu)化、尺寸縮放、顏色量化等專業(yè)功能。
核心功能對比:
| 特性 | 基礎(chǔ)版 | 增強版(本代碼) |
|---|---|---|
| 圖片轉(zhuǎn)GIF | ? | ? |
| 智能數(shù)字排序 | ? | ? |
| 透明通道處理 | ?(直接轉(zhuǎn)RGB) | ?(白色背景填充) |
| 尺寸縮放 | ? | ?(LANCZOS重采樣) |
| 顏色量化 | ? | ?(MedianCut算法,1-256色) |
| 幀差異優(yōu)化 | ? | ?(optimize參數(shù)) |
| 壓縮級別控制 | ? | ?(0-9級) |
| 調(diào)色板質(zhì)量 | ? | ?(1-100) |
| 尺寸一致性校驗 | ? | ?(打印警告) |
這是一款功能全面、高度可定制的批量圖片轉(zhuǎn) GIF 工具,覆蓋從圖片預(yù)處理到 GIF 優(yōu)化的全流程,核心能力如下:
核心生成:靈活可控的 GIF 創(chuàng)建
- 讀取指定目錄下 PNG/JPG/BMP/WebP 等主流格式圖片,支持通過
-s/--sort_order參數(shù)一鍵切換文件名升序 / 降序排序; - 自定義幀率(FPS)、循環(huán)次數(shù)(0 = 無限循環(huán)),滿足不同播放節(jié)奏需求。
- 讀取指定目錄下 PNG/JPG/BMP/WebP 等主流格式圖片,支持通過
預(yù)處理:智能兼容 & 規(guī)整圖片
- 自動處理 RGBA 透明圖片:將透明背景轉(zhuǎn)為白色,避免 GIF 背景異常;
- 校驗所有圖片尺寸一致性,尺寸不符時給出明確警告,保障動圖顯示效果;
- 支持 0.1-1.0 縮放因子調(diào)整圖片大小,平衡 GIF 清晰度與文件體積。
優(yōu)化:多維度輕量化壓縮
- 可選顏色數(shù)精簡:通過中值切割算法限制最大顏色數(shù)(1-256),大幅降低 GIF 體積;
- 幀優(yōu)化 + 多級壓縮:啟用幀差異編碼、自定義壓縮級別(0-9)、調(diào)色板質(zhì)量(1-100),兼顧畫質(zhì)與壓縮率;
- 內(nèi)置 Floyd-Steinberg 抖動算法,減少顏色精簡后的畫面失真。

源代碼:
import os
import argparse
import re
from PIL import Image
import numpy as np
def create_gif(image_folder, output_path, fps=10, loop=0,
reduce_colors=True, max_colors=256,
optimize_frames=True, resize_factor=1.0,
compress_level=6, quality=85, sort_order='asc'):
"""
從指定目錄圖片創(chuàng)建GIF動圖(支持壓縮/縮放/調(diào)色)
參數(shù):
image_folder (str): 圖片目錄路徑
output_path (str): GIF輸出路徑
fps (int/float): 每秒幀數(shù),默認(rèn)10
loop (int): 循環(huán)次數(shù)(0=無限),默認(rèn)0
reduce_colors (bool): 是否減少顏色數(shù),默認(rèn)True
max_colors (int): 最大顏色數(shù)(1-256),默認(rèn)256
optimize_frames (bool): 是否優(yōu)化幀(差異編碼),默認(rèn)True
resize_factor (float): 縮放因子(0.1-1.0),默認(rèn)1.0(不縮放)
compress_level (int): 壓縮級別(0-9),默認(rèn)6
quality (int): 調(diào)色板質(zhì)量(1-100),默認(rèn)85
sort_order (str): 排序方式(asc=升序/desc=降序),默認(rèn)asc
"""
# 支持的圖片格式
IMAGE_EXTS = ('.png', '.jpg', '.jpeg', '.bmp', '.webp')
# 篩選目錄內(nèi)的圖片文件
image_files = [
os.path.join(image_folder, f)
for f in os.listdir(image_folder)
if f.lower().endswith(IMAGE_EXTS)
]
if not image_files:
raise ValueError(f"目錄 '{image_folder}' 未找到圖片文件")
# 提取文件名中的數(shù)字作為排序依據(jù)
def sort_key(filename):
basename = os.path.basename(filename)
match = re.search(r'\d+', basename)
return int(match.group()) if match else basename
# 根據(jù)參數(shù)切換升/降序排序
reverse = True if sort_order == 'desc' else False
image_files.sort(key=sort_key, reverse=reverse)
# 打印排序結(jié)果
print(f"找到 {len(image_files)} 張圖片,排序方式: {sort_order}")
for i, f in enumerate(image_files):
print(f" {i+1}. {os.path.basename(f)}")
# 加載并統(tǒng)一圖片格式/尺寸
images = []
first_size = None
for img_path in image_files:
try:
img = Image.open(img_path)
# 校驗圖片尺寸一致性
if first_size is None:
first_size = img.size
print(f"\n基準(zhǔn)尺寸: {first_size[0]}x{first_size[1]}")
elif img.size != first_size:
print(f"警告: 圖片 {os.path.basename(img_path)} 尺寸 {img.size} 與基準(zhǔn)不一致")
# 處理透明通道(轉(zhuǎn)為白色背景)
if img.mode == 'RGBA':
background = Image.new('RGB', img.size, (255, 255, 255))
background.paste(img, mask=img.split()[-1])
img = background
else:
img = img.convert('RGB')
images.append(img)
except Exception as e:
print(f"警告: 無法打開圖片 {img_path} - {e}")
if not images:
raise ValueError("無可用圖片文件")
print(f"\n成功加載 {len(images)} 張圖片")
# 圖片縮放(按需)
if resize_factor != 1.0 and 0.1 <= resize_factor <= 1.0:
new_size = (int(first_size[0] * resize_factor),
int(first_size[1] * resize_factor))
print(f"縮放圖片: {first_size} → {new_size} (縮放因子: {resize_factor})")
for i in range(len(images)):
images[i] = images[i].resize(new_size, Image.Resampling.LANCZOS)
# 減少顏色數(shù)(按需)
if reduce_colors and max_colors < 256:
print(f"減少顏色數(shù)至 {max_colors} 色")
for i in range(len(images)):
images[i] = images[i].quantize(colors=max_colors,
method=Image.Quantize.MEDIANCUT)
images[i] = images[i].convert('RGB')
# 計算每幀時長(毫秒)
duration = 1000 / fps
# 自動創(chuàng)建輸出目錄(不存在時)
output_dir = os.path.dirname(os.path.abspath(output_path))
if output_dir:
os.makedirs(output_dir, exist_ok=True)
print(f"\n輸出目錄已確保存在: {output_dir}")
# 生成并保存GIF(帶優(yōu)化參數(shù))
print("正在生成GIF文件...")
images[0].save(
output_path,
save_all=True,
append_images=images[1:],
duration=duration,
loop=loop,
optimize=optimize_frames,
compress_level=compress_level,
quality=quality,
disposal=2,
dither=Image.Dither.FLOYDSTEINBERG
)
# 輸出生成結(jié)果
file_size = os.path.getsize(output_path) / (1024 * 1024)
print(f"\n? GIF已保存至: {output_path}")
print(f"?? 文件大小: {file_size:.2f} MB | ??? 幀率: {fps} FPS (每幀 {duration:.1f}ms)")
print(f"??? 圖片數(shù)量: {len(images)} | ?? 循環(huán)次數(shù): {'無限' if loop == 0 else loop}")
if resize_factor != 1.0:
print(f"?? 縮放因子: {resize_factor}")
if reduce_colors:
print(f"?? 顏色數(shù)限制: {max_colors}")
print(f"??? 壓縮級別: {compress_level} | ?? 質(zhì)量設(shè)置: {quality}")
def main():
# 命令行參數(shù)解析
parser = argparse.ArgumentParser(description='GIF生成工具(支持壓縮/縮放/調(diào)色/排序)')
parser.add_argument('--input_dir', default='./THUD_Robot_data/', help='輸入圖片目錄(默認(rèn): ./Gif_bev_Global_Graph_Range/)')
parser.add_argument('--output_file', default='Output_GIF/THUD_Robot_data-test.gif', help='輸出GIF文件路徑')
parser.add_argument('-f', '--fps', type=float, default=0.5, help='每秒幀數(shù)(默認(rèn): 0.5)')
parser.add_argument('-l', '--loop', type=int, default=0, help='循環(huán)次數(shù)(0=無限,默認(rèn): 0)')
parser.add_argument('-s', '--sort_order', choices=['asc', 'desc'], default='asc',help='排序方式(asc=升序/desc=降序,默認(rèn): asc)')
# 壓縮/優(yōu)化相關(guān)參數(shù)
parser.add_argument('--no-reduce-colors', action='store_false', default=True, dest='reduce_colors',help='不減少顏色數(shù)')
parser.add_argument('--max-colors', type=int, default=256,help='最大顏色數(shù)(1-256),默認(rèn)256')
parser.add_argument('--resize', type=float, default=0.6,help='縮放因子(0.1-1.0),默認(rèn)0.6')
parser.add_argument('--compress', type=int, default=3, choices=range(0, 10),help='壓縮級別(0-9),默認(rèn)3')
parser.add_argument('--quality', type=int, default=95,help='調(diào)色板質(zhì)量(1-100),默認(rèn)95')
args = parser.parse_args()
# 校驗輸入目錄
if not os.path.isdir(args.input_dir):
print(f"? 錯誤: 輸入目錄 '{args.input_dir}' 不存在")
return
# 自動補全GIF擴展名
if not args.output_file.lower().endswith('.gif'):
args.output_file += '.gif'
# 執(zhí)行GIF生成
try:
create_gif(
args.input_dir,
args.output_file,
args.fps,
args.loop,
reduce_colors=args.reduce_colors,
max_colors=args.max_colors,
resize_factor=args.resize,
compress_level=args.compress,
quality=args.quality,
sort_order=args.sort_order
)
except Exception as e:
print(f"\n? 錯誤: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()
配置:零代碼便捷適配
- 全參數(shù)通過命令行配置(輸入 / 輸出路徑、縮放、壓縮、排序等),無需修改代碼;
- 自動補全
.gif擴展名,避免格式錯誤; - 輸出生成后詳細(xì)信息(文件大小、幀率、顏色數(shù)等),直觀掌握結(jié)果。
魯棒性:防錯 & 易調(diào)試
- 自動創(chuàng)建不存在的輸出目錄,無需手動建文件夾;
- 校驗輸入目錄有效性,捕獲異常并打印錯誤堆棧,快速定位問題;
- 跳過無法打開的異常圖片,不中斷整體生成流程。
可視化結(jié)果:

運行信息:
找到 7 張圖片,排序方式: asc
1. frame-000010.color.png
2. frame-000019.color.png
3. frame-000039.color.png
4. frame-000046.color.png
5. frame-000066.color.png
6. frame-000086.color.png
7. frame-000109.color.png
基準(zhǔn)尺寸: 960x540
成功加載 7 張圖片
縮放圖片: (960, 540) → (768, 432) (縮放因子: 0.8)
輸出目錄已確保存在: /home/user/lgp_dev/01_Gif_picture/Output_GIF
正在生成GIF文件...
? GIF已保存至: Output_GIF/THUD_Robot_data-test.gif
?? 文件大小: 1.14 MB | ??? 幀率: 0.5 FPS (每幀 2000.0ms)
??? 圖片數(shù)量: 7 | ?? 循環(huán)次數(shù): 無限
?? 縮放因子: 0.8
?? 顏色數(shù)限制: 256
??? 壓縮級別: 3 | ?? 質(zhì)量設(shè)置: 95
分析完成~
到此這篇關(guān)于Python實現(xiàn)批量圖片轉(zhuǎn)GIF動圖(附源代碼)的文章就介紹到這了,更多相關(guān)Python圖片轉(zhuǎn)GIF動圖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實現(xiàn)統(tǒng)計給定列表中指定數(shù)字出現(xiàn)次數(shù)的方法
這篇文章主要介紹了Python實現(xiàn)統(tǒng)計給定列表中指定數(shù)字出現(xiàn)次數(shù)的方法,涉及Python針對列表的簡單遍歷、計算相關(guān)操作技巧,需要的朋友可以參考下2018-04-04
Pycharm在創(chuàng)建py文件時,自動添加文件頭注釋的實例
今天小編就為大家分享一篇Pycharm在創(chuàng)建py文件時,自動添加文件頭注釋的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05

