方格精選

Python Pillow 套件-製作GIF動畫

更新於 發佈於 閱讀時間約 20 分鐘

圖像互換格式(Graphics Interchange Format, GIF)是一種媒體格式,可以將多偵的圖像組合成一個連續的動畫。無論是在社交媒體上分享有趣的動畫,還是在網站上展示產品的動態效果,GIF都是一個絕佳的選擇。

上一篇文章說明了Pillow套件的基礎操作,例如圖像的縮放,裁減,旋轉、合併等等,而這篇文章,將介紹如何使用上一篇提到的技巧,製作出流暢的GIF動畫。

Pillow將檔案儲存成GIF格式的函式與上一章介紹的一樣,是使用 Image.save() ,而 save​有多個參數可以控制GIF的屬性,以下是常見的參數:

image.save(fp: str, 
           save_all: bool,
           append_images: list,
           optimize: bool,
           duration: int | list,
           loop: int)
  1. image :GIF第一幀的圖。
  2. save_all:是否保存多幀GIF。
  3. append_images :要追加為GIF的其他圖像串列。
  4. duration:每幀的持續時間,以毫秒為單位。可以是單一整數(對所有幀使用相同的持續時間)或整數串列(每幀的持續時間)。
  5. loop:GIF的播放次數。0表示無限循環,1表示播放一次,2表示播放兩次,依此類推

範例1-使用繪製製作動畫

先來看圖像:

square_animation.gif

square_animation.gif

這是一個200x200的圖像,中心有一個紅色矩形,從100x100,每幀邊長各增長10像素,直到填滿200x200的空間,每幀的持續時間為100ms,並且無限循環。

在說明如何製作之前,先來介紹一個可以生成新圖像的函式:

Image.new(mode: str, size: tuple | str, color)
  1. mode:圖像的顏色模式。常見的模式有:
    • 'RGB': 三通道,紅色、綠色和藍色。
    • 'RGBA': 四通道,紅色、綠色、藍色和透明度/alpha。
    • 'L': 灰度模式。
    • '1': 二值模式,只有黑和白。
  2. size:圖像的尺寸,表示為(width, height)
  3. color:背景顏色。對於'RGB'模式,這將是一個三元組,例如(255, 255, 255)表示白色,也可以使用顏色的英文名,如 'white' 。對於'L'模式,這將是一個介於0(黑色)和255(白色)之間的整數。

例如生成一個100x100,背景顏色為藍色的圖像:

from PIL import Image
img = Image.new('RGB', (100, 100), (0, 0, 255))
img.save(r'blue_square.png')
blue.png

blue.png

介紹完 new()之後,就可以開始介紹如何製作了。

製作過程

首先,我們需要一個200x200、背景為透明的圖像:

from PIL import Image, ImageDraw
img = Image.new('RGBA', (200, 200), (255, 255, 255, 0))

接著,在圖像的中間繪製100x100的紅色矩形:

draw = ImageDraw.Draw(img)
upper_left = (100 - 50, 100 - 50)
lower_right = (100 + 50, 100 + 50)
draw.rectangle([upper_left, lower_right], fill='red')
img.save(r'red_square.png')
red_square.png

red_square.png

接下來,因為每次邊長都會增加十,也就是說,下一張圖像的矩形大小會是110x110,為了維持在圖像中央,矩形左上角的點座標會是(100 - 55, 100 - 500),右下地的點座標則是(100 + 55, 100 + 55),依此類推,下一次就是(100 - 60, 100 - 60)與(100 + 60, 100 + 60),直到(0, 0)與(200, 200)時,紅色矩形填滿整個圖像。我們利用 for 迴圈來繪製每一張圖像,並且將圖像儲存至 images​ 的列表內,程式碼如下:

# 創建一個圖像列表
images = []
for i in range(100, 201, 10):
    # 創建一個200x200的透明背景
    img = Image.new('RGBA', (200, 200), (255, 255, 255, 0))
   
    # 在正中間繪製紅色矩形
    draw = ImageDraw.Draw(img)
    upper_left = (100 - i//2, 100 - i//2)
    lower_right = (100 + i//2, 100 + i//2)
    draw.rectangle([upper_left, lower_right], fill='red')
   
    images.append(img)

接下來,我們只要將圖像利用 save 輸出成GIF就完成了,第一幀圖像是 images列表的第一個元素,因此使用 images[0].save() 來製作GIF,按照上面的格式依序填入參數:

images[0].save(r'square_animation.gif',
                save_all = True,
                append_images = images[1:],
                optimize = False,
                duration = 100,
                loop = 0)

值得注意的是 append_images = images[1:],使用列表分割使得 images[0] 不會出現兩幀。以下是完整的程式碼:

from PIL import Image, ImageDraw

# 創建一個圖像列表
images = []
for i in range(100, 201, 10):
    # 創建一個200x200的透明背景
    img = Image.new('RGBA', (200, 200), (255, 255, 255, 0))
   
    # 在正中間繪製紅色正方形
    draw = ImageDraw.Draw(img)
    upper_left = (100 - i//2, 100 - i//2)
    lower_right = (100 + i//2, 100 + i//2)
    draw.rectangle([upper_left, lower_right], fill='red')
   
    images.append(img)

# 將圖像列表保存為GIF
images[0].save(r'square_animation.gif',
               save_all = True,
               append_images = images[1:],
               optimize = False,
               duration = 100,
               loop = 0)

範例二-圖像旋轉

接下來用上一篇文章提到的 rotate() 製作如下動畫:

rotated_animation,gif

rotated_animation,gif


這是一個100x100的水藍色矩形,以逆時針每次旋轉10度,無限循環,每幀的持續時間為100ms。

首先一樣使用 new() 來製作一個100x100的水藍色圖像:


from PIL import Image
base_img = Image.new('RGB', (100, 100), color = 'aqua')
base_img.save(r'aqua.png')
aqua.png

aqua.png

來看看轉五十度的圖像:

rotated.png

rotated.png

旋轉成功,那我們就可以使用 for 迴圈來快速製作旋轉10度到350度的圖像,由於旋轉0度等於360度, saveloop 參數會自動幫我們回到第一幀圖像,因此我們 for 迴圈只要到 350 就行了。

rotated_images = []
# 旋轉圖像
for angle in range(10, 360, 10):
    rotated_images.append(base_img.rotate(angle))

將圖像列表合併成GIF動畫:

# 將旋轉的圖像保存為GIF
rotated_images[0].save(r'rotated_animation.gif',
                      save_all = True,
                      append_images = rotated_images[1:],
                      optimize = False,
                      duration = 100,
                      loop = 0)

製作旋轉圖像也可以使用Python的生成式,完整程式碼如下:

from PIL import Image
# 創建一個水藍色圖像
base_img = Image.new('RGB', (100, 100), color = 'aqua')

# 旋轉圖像
rotated_images = [base_img.rotate(angle) for angle in range(0, 360, 10)]

# 將旋轉的圖像保存為GIF
rotated_images[0].save(r'rotated_animation.gif',
                      save_all = True,
                      append_images = rotated_images[1:],
                      optimize = False,
                      duration = 100,
                      loop = 0)

範例三-圖像裁剪

現在有一張風景圖:

landscape.png

landscape.png

我們希望能擁有以下效果:

sliding_window.gif

sliding_window.gif

這張gif的大小為640x300,每幀擷取的部份的會往下5像素,到最底後會回彈,並以每幀往上5巷素的方式移動,直到回到圖像的最頂端,無限循環,每幀的持續時間為50ms。

一開始,我們先讀入 landscape.png,並顯示其大小:

from PIL import Image
img = Image.open(r'landscape.png')
width, height = img.size
print(f'大小:{width}x{height}')
大小:640x640

先擷取(0, 0)到(640, 300)的範圍:

cropped = img.crop((0, 0, 640, 300))
cropped.save(r'cropped.png')
cropped.png

cropped.png

接著只要一路以每幀5像素的速度向下裁剪,直到碰到底部,也就是裁剪到(0, 340, 640, 640):

for step in range(0, height - 300 + 1, 5):
    box = (0, 0 + step, width, 300 + step)
    cropped = img.crop(box)
    images.append(cropped)

由於碰到底部要回彈,也就是將剛剛的過程反著再來一遍,我們可以直接複製 images內倒數第二個元素到第二個的元素,也就是去掉頭尾,然後連接到原本 images的後面,程式碼如下:

images += images[-2:0:-1]

接著將圖像列表轉為GIF並儲存:

images[0].save(r'example3\sliding_window.gif',
                save_all = True,
                append_images = images[1:],
                optimize = False,
                duration = 50,
                loop = 0)

完整程式碼如下:

from PIL import Image

img = Image.open(r'landscape.png')
images = []
width, height = img.size

for step in range(0, height - 300 + 1, 5):
    box = (0, 0 + step, width, 300 + step)
    cropped = img.crop(box)
    images.append(cropped)

images += images[-2:0:-1]

images[0].save(r'sliding_window.gif',
                save_all = True,
                append_images = images[1:],
                optimize = False,
                duration = 50,
                loop = 0)

範例四-圖像合併

有三張風景圖:

0.png

0.png

1.png

1.png

2.png

2.png

我們可以直接使用 blend()來達成如下效果:

blend.gif

blend.gif

利用Python的生成式將圖像依序讀入並存於 images列表中 :

from PIL import Image

images = [Image.open(f'{img}.png') for img in range(3)]

images列表存為GIF:

images[0].save(r'blend.gif', 
               save_all = True,
               append_images = images[1:],
               optimize = False,
               duration = 500,
               loop = 0)

但這樣轉場過於單調,我們可以透過調整 alpha參數來製作淡出的效果,淡出的過程每幀持續時間100ms,每次淡出圖像的透明度增加10%,圖像每幀持續時間300​ms:

fade_out.gif

fade_out.gif

一樣先讀入圖像,不過為了等等製作淡出動畫方便, base_images的最後我們再增加一張開頭的圖像:

from PIL import Image

base_images = [Image.open(f'{img}.png') for img in range(3)]
base_images.append(base_images[0])
images = []

先將目前顯示的圖像加入到 images中,接著開始製作淡出動畫,淡出圖像的透明度每幀增加10%:

for i in range(len(base_images) - 1):
    # 將目前圖像加入至images
    images.append(base_images[i])

    # 每幀淡出圖像的透明度增加10%
    for alpha in range(10):
        blend = Image.blend(base_images[i], base_images[i + 1], alpha = alpha / 10)
        images.append(blend)

淡出過程有10幀圖像,這個過程每幀100ms,而顯示完整圖像時每幀300ms,完整圖像分別位於 images[0]images[11]images[22],也就是說,當索引值是11的倍數時,持續時間須為300ms,剩下的每幀持續時間為100ms,我們利用以下程式碼製作 durations陣列:

for i in range(len(images)):
    if i % 11:
        durtions.append(100)
   
    else:
        durtions.append(300)

最後將圖像列表儲存為GIF就成功啦:

images[0].save(r'example4\fade_out.gif', 
               save_all = True,
               append_images = images[1:],
               optimize = False,
               duration = durtions,
               loop = 0)

完整程式碼如下:

from PIL import Image

base_images = [Image.open(f'example4\\{img}.png') for img in range(3)]
base_images.append(base_images[0])
images = []

for i in range(len(base_images) - 1):
    # 將目前圖像加入至images
    images.append(base_images[i])

    # 每幀淡出圖像的透明度增加10%
    for alpha in range(10):
        blend = Image.blend(base_images[i], base_images[i + 1], alpha = alpha / 10)
        images.append(blend)

durtions = []

for i in range(len(images)):
    if i % 11:
        durtions.append(100)
   
    else:
        durtions.append(300)

images[0].save(r'example4\fade_out.gif',
               save_all = True,
               append_images = images[1:],
               optimize = False,
               duration = durtions,
               loop = 0)

以上就是一些利用Pillow套件製作gif的範例,範例程式碼與圖片可以在此查看與下載:YukiHataRin/vocus_gif (github.com)。感謝大家的閱讀!

留言
avatar-img
留言分享你的想法!
avatar-img
HataRin的沙龍
14會員
4內容數
HataRin的沙龍的其他內容
2023/09/15
動態規劃(Dynamic Programming)的基本思想是將複雜的問題分解為較小的子問題,並找到這些子問題的關聯性,通過這些子問題的解,我們可以避免重複計算,從而節省計算資源。這種過程稱為「記憶化(Memoization)」,通常使用數組或字典來實現,以在後續的計算中快速查找和重用中間結果。
Thumbnail
2023/09/15
動態規劃(Dynamic Programming)的基本思想是將複雜的問題分解為較小的子問題,並找到這些子問題的關聯性,通過這些子問題的解,我們可以避免重複計算,從而節省計算資源。這種過程稱為「記憶化(Memoization)」,通常使用數組或字典來實現,以在後續的計算中快速查找和重用中間結果。
Thumbnail
2023/09/04
序列化(serialization)是將資料結構或對象轉換為一個格式,可以被儲存到文件或記憶體中,或者可以透過網路傳輸到另一個系統環境。這使得資料可以在不同的系統之間進行交換,並在需要時重新建構回原始的資料結構。本文將介紹兩個好用的Python套件-JSON與Pickle,並比較兩者的不同。
Thumbnail
2023/09/04
序列化(serialization)是將資料結構或對象轉換為一個格式,可以被儲存到文件或記憶體中,或者可以透過網路傳輸到另一個系統環境。這使得資料可以在不同的系統之間進行交換,並在需要時重新建構回原始的資料結構。本文將介紹兩個好用的Python套件-JSON與Pickle,並比較兩者的不同。
Thumbnail
2023/08/26
在當今的數位時代,圖像處理已成為許多應用和項目的核心部分,從網站設計到機器學習,高效且靈活的圖像處理工具變得越來越重要。本文將介紹一個好用的Python套件-Pillow,Pillow套件是Python Imaging Library(PIL)的一個分支雖,然它不像Photoshop等軟體一樣強大,
Thumbnail
2023/08/26
在當今的數位時代,圖像處理已成為許多應用和項目的核心部分,從網站設計到機器學習,高效且靈活的圖像處理工具變得越來越重要。本文將介紹一個好用的Python套件-Pillow,Pillow套件是Python Imaging Library(PIL)的一個分支雖,然它不像Photoshop等軟體一樣強大,
Thumbnail
看更多
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
GIFShift 是一個免費的 AI GIF 轉換工具,可以將 GIF 圖片轉換為動漫風格,支援輸入提示改變圖像內容,例如指定英雄電影主角來生成人物,用情緒描述更換臉部表情。無須註冊、完全免費,提供 GIPHY 搜尋功能,方便尋找素材創作新的 GIF 梗圖。
Thumbnail
GIFShift 是一個免費的 AI GIF 轉換工具,可以將 GIF 圖片轉換為動漫風格,支援輸入提示改變圖像內容,例如指定英雄電影主角來生成人物,用情緒描述更換臉部表情。無須註冊、完全免費,提供 GIPHY 搜尋功能,方便尋找素材創作新的 GIF 梗圖。
Thumbnail
涉及圖像處理和計算機視覺時,色彩空間轉換是一個常見操作,應用如下: 降維: 將一張彩色圖像轉換為灰度圖像可以減少數據的維度,簡化處理過程,同時在某些情況下保留重要的視覺信息。 突顯特徵: 在某些情況下,某些色彩通道可能包含冗餘或不必要的信息,通過轉換到其他色彩空間,可以更好地突顯圖像中的重要特徵
Thumbnail
涉及圖像處理和計算機視覺時,色彩空間轉換是一個常見操作,應用如下: 降維: 將一張彩色圖像轉換為灰度圖像可以減少數據的維度,簡化處理過程,同時在某些情況下保留重要的視覺信息。 突顯特徵: 在某些情況下,某些色彩通道可能包含冗餘或不必要的信息,通過轉換到其他色彩空間,可以更好地突顯圖像中的重要特徵
Thumbnail
本文將介紹影像的基本操作包括:影像的讀取、顯示、保存,以及一些常見的操作如裁剪、旋轉、縮放等。 語法介紹 讀取影像: cv2.imread函數的參數是影像的檔案路徑。讀取後的影像以NumPy的ndarray形式表示。
Thumbnail
本文將介紹影像的基本操作包括:影像的讀取、顯示、保存,以及一些常見的操作如裁剪、旋轉、縮放等。 語法介紹 讀取影像: cv2.imread函數的參數是影像的檔案路徑。讀取後的影像以NumPy的ndarray形式表示。
Thumbnail
Pika Labs可以透過文生影片、圖生影片、影片轉影片三種影片產生方式,Pika也可以生成多種風格影片,像是3D動畫、動漫、卡通和電影等,一次生成3秒的影片,影片具有真實的場景感,超絲滑的運動效果,目前免費無限次數。
Thumbnail
Pika Labs可以透過文生影片、圖生影片、影片轉影片三種影片產生方式,Pika也可以生成多種風格影片,像是3D動畫、動漫、卡通和電影等,一次生成3秒的影片,影片具有真實的場景感,超絲滑的運動效果,目前免費無限次數。
Thumbnail
粒子消散效果指令: 我想將照片塊狀消散效果應用到這張圖片上。你能幫我嗎?為我提供下載生成的視頻的連結。使用下面的代碼
Thumbnail
粒子消散效果指令: 我想將照片塊狀消散效果應用到這張圖片上。你能幫我嗎?為我提供下載生成的視頻的連結。使用下面的代碼
Thumbnail
上一篇文章說明了Pillow套件的基礎操作,這篇文章則會透過四個範例來示範如何利用Pillow製作簡單的GIF動畫。
Thumbnail
上一篇文章說明了Pillow套件的基礎操作,這篇文章則會透過四個範例來示範如何利用Pillow製作簡單的GIF動畫。
Thumbnail
在當今的數位時代,圖像處理已成為許多應用和項目的核心部分,從網站設計到機器學習,高效且靈活的圖像處理工具變得越來越重要。本文將介紹一個好用的Python套件-Pillow,Pillow套件是Python Imaging Library(PIL)的一個分支雖,然它不像Photoshop等軟體一樣強大,
Thumbnail
在當今的數位時代,圖像處理已成為許多應用和項目的核心部分,從網站設計到機器學習,高效且靈活的圖像處理工具變得越來越重要。本文將介紹一個好用的Python套件-Pillow,Pillow套件是Python Imaging Library(PIL)的一個分支雖,然它不像Photoshop等軟體一樣強大,
Thumbnail
圖案在Illustrator電繪完成後, 再進入Photoshop合成....製作影格動畫。
Thumbnail
圖案在Illustrator電繪完成後, 再進入Photoshop合成....製作影格動畫。
Thumbnail
用FFMPEG將圖片變成影片吧! 步驟一、確定資料夾路徑 使用左下角搜尋或是WINDOS+R,輸入CMD 將命令提示字元(CMD)叫出來 複製上面這段資料夾路徑 並在檔案總管理 貼上剛剛複製的路徑,enter 這個資料夾,就是我們的工作檯面,等等我們要處理的任何東西,都要放進這個資料夾才行 尤其是我
Thumbnail
用FFMPEG將圖片變成影片吧! 步驟一、確定資料夾路徑 使用左下角搜尋或是WINDOS+R,輸入CMD 將命令提示字元(CMD)叫出來 複製上面這段資料夾路徑 並在檔案總管理 貼上剛剛複製的路徑,enter 這個資料夾,就是我們的工作檯面,等等我們要處理的任何東西,都要放進這個資料夾才行 尤其是我
Thumbnail
這次來用這個網站 https://gifmaker.me/ ,製作 GIF 動圖,主要是覺得把自己畫貓的過程弄成動圖時覺得很療癒... 什麼?!?你說你不會畫,沒關係,即使是畫個火柴棒人也可以很趣味的...
Thumbnail
這次來用這個網站 https://gifmaker.me/ ,製作 GIF 動圖,主要是覺得把自己畫貓的過程弄成動圖時覺得很療癒... 什麼?!?你說你不會畫,沒關係,即使是畫個火柴棒人也可以很趣味的...
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News