徹底搞清楚pygame的blend mode

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

呼!折騰了好久,終於徹底搞清楚pygame的各個blend mode所用的計算式,到底是長啥樣子了。

在數位影像編輯和電腦圖學中,當不同的顏色混在一起時,最後會呈現出什麼顏色,完全取決於背後用的是怎樣的計算方式。不同的計算方式,就會得到不同的顏色,而blend mode就是指這些不同的計算方式。如果把blend mode翻譯成「混色模式」,應該可以讓人比較容易理解那到底是個什麼玩意兒。

在寫《The Nature of Code閱讀心得筆記——使用Python實作》《The Nature of Code閱讀心得與Python實作》第4.9節時,因為是有關於blend mode的內容,所以必須知道pygame在這部分有提供哪些功能,這樣才有辦法寫程式。讓人意想不到的是,明明內容不多,看來也都是些很簡單容易理解的概念,真正寫起程式來,卻老是做不出原書的效果,實在是讓人懷疑人生。

「啊你不會網路上查一下喔?!問一下AI也可以啊!」一定會有人帶著懷疑的眼神,以略帶不屑的口吻這樣說。是啦!是啦!這誰不知道啊?但問題也就出在這兒啊,網路上看到的資料中,有已經過時的、有寫錯的,而Google那個萬人迷的Gemini,吃了那些亂七八糟的東西之後,嘴裡吐出來的東西,也是亂七八遭的,根本不知道哪些是正確的,哪些是錯誤的。

既然真相這麼難找,那最後又是怎麼找到的?這個啊,套句電視劇灑狗血用的台詞,就「回歸初心」囉!乖乖的研究pygame的原始檔案中,這部分到底是怎麼設計的。這樣做雖然有點燒腦,但很實在。

在pygame中,混色模式除了BLEND_PREMULTIPLIEDBLEND_ALPHA_SDL2這兩個比較特殊孤僻的模式之外,可以由命名方式區分為兩大類,而其主要的差異在於混色時,包含或不包含透明度。

不包含透明度的混色模式

BLEND_ADD, BLEND_SUB, BLEND_MULT, BLEND_MIN, BLEND_MAX

BLEND_RGB_ADD, BLEND_RGB_SUB, BLEND_RGB_MULT, BLEND_RGB_MIN, BLEND_RGB_MAX

這裡要注意的是,中間有或沒有RGB三個字母,其實是一樣的模式,只是名稱不同而已。例如,BLEND_ADDBLEND_RGB_ADD,指的其實是同樣的模式。

包含透明度的混色模式

BLEND_RGBA_ADD, BLEND_RGBA_SUB, BLEND_RGBA_MULT, BLEND_RGBA_MIN, BLEND_RGBA_MAX

這些模式會利用不同的計算式,來決定混色之後的顏色數值。假設

0 <= src, dest <= 255

當把來源像素的顏色src混色到目標像素的顏色dest而得到顏色c時,各個模式的RGBA值計算式為:

ADD: c = (dest+src) if (dest+src)<=255 else 255

SUB: c = (dest-src) if (dest-src)>=0 else 0

MULT: c = (dest*src+255)//256

MIN: c = min(dest, src)

MAX: c = max(dest, src)

其中MULT模式有兩個比較特別的性質:當destsrc有一個是0時,則混色之後的值,就會是0;而當destsrc有一個是255時,則混色之後的值,會是另外那個顏色的值。所以,當我們把一張具備透明度的圖片,以MULT混色模式blit到一張顏色為(255, 255, 255, A)的圖片之後,所得到的圖片,顏色會跟原來的圖片一樣,而且,完全透明的部分,也會跟原來的圖片一樣;被改變的,就只是完全不透明以及不完全透明部分的透明度。

在pygame的blit()fill()方法中,有個special_flags參數,可以用來選擇混色模式;如果不特別指定而使用預設的混色模式,則混色後的顏色,計算方式為:

if destA == 0:
c = src
A = srcA
else:
    c = (src*srcA + dest*(255-srcA))//255
  A = srcA + destA*(255-srcA)//255

這裡的srcAdestA分別指的是來源像素和目標像素的alpha值,而A則是混色後所得到的alpha值。不過要注意的是,這兩個式子所算出的值,和用pygame所算出的值,可能會有些小小的差距。造成這個小小差距的原因,在於pygame為了加快計算速度,用了很多技巧來避免浮點數運算,但同時也犧牲了一些計算上的準確度。另外,從計算式可以看出來,當目標像素是完全透明時,混色之後得到的會是來源像素,完全無視目標像素的存在。

以上就是pygame各種blend mode的計算方式。這些計算式看起來挺簡單的,不是嗎?但怎會那麼折騰人呢?以下就是挖掘真相的辛酸血淚史。

這一切的一切,都是因為pygame的說明文件,實在是有夠不清不楚的。

在pygame的說明文件中,只列出了各個blend mode的名稱,並沒有說明相關的計算方式。所以,就只能鼻子摸一摸,在網路上搜尋看看有沒有更詳細的資料。

顯然有不少網友有同樣的疑問,所以在stack overflow和reddit上,可以看到不少相關的討論。只是很不幸的,pygame在發展的過程中,針對混色的計算方式,進行過幾次的調整,而網路上查到的那些網友提供的計算式,有一些是調整前的式子,難怪實際測試時,老是得不到預期中的結果。

要想知道pygame各個blend mode所用的計算式,比較好的辦法,就是直接去讀surface.h這個檔案。不過,千萬千萬要注意,網路上有網友提供這個檔案的連結,要讀之前,先確認一下日期,因為那是個過時的檔案,裡頭關於MULT模式的計算式有bug。所以囉,最萬無一失的方法,就是把安裝在自己電腦上的surface.h找出來讀,這樣就不用擔心版本不符的問題了。

在所有的blend mode中,預設模式的計算式花了最多時間才搞清楚。之所以會這樣,還是因為文件寫得不完整。在<Source Alpha to Source Alpha Surface Blit Guarantees — wiki>這篇文章中,說明了pygame在混色時的計算方式。這個其實也就是blend mode預設模式的計算式。只是啊只是,文章中並沒有提到一個特殊狀況:當目標像素是完全透明時,混色之後得到的RGBA值,會和來源像素的RGBA值一模一樣。就因為這個不完整的說明,又讓人昏天暗地的多花了很多時間,才終於搞清楚問題出在哪。

從這個挖掘pygame的blend mode真相的過程就可以知道,清楚且詳細的說明文件,是多麼的重要而且珍貴啊!

avatar-img
15會員
131內容數
寫點東西自娛娛人
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
在寫《The Nature of Code閱讀心得筆記——使用Python實作》的[第四章]4.3節時,原書提到,在使用Java的ArrayList時,如果用迴圈一面走訪一面又移除其中的元素,那會有難以察覺的問題存在。寫個小程式測試的結果發現,Python的list也會有一樣的問題。
用matplotlib畫正弦函數sin的圖形會有多難呢?應該是挺簡單的。不過,要畫得漂亮讓人滿意,還是非得費一番功夫調整不可。
MOUSEBUTTONDOWN的個性和mouse.get_pressed()是完全相反的。mouse.get_pressed()只活在當下,完全不管過去發生過什麼事;MOUSEBUTTONDOWN則會記得所有還沒處理完的事,只要事件佇列還沒被塞滿的話。
身為頂級藝術細胞缺乏者,總是非常羨慕那些能隨手畫出漂亮圖畫的人。看著自己寫的程式在螢幕上展現出事先無法預期的漂亮圖案,還真是很有成就感,也不免有些興奮地想著:「嘿!看來頂級藝術細胞缺乏者有藥醫了!」 這個圖
忽然覺得,似乎、彷彿、好像、應該有個for... else語法,可以讓程式漂亮一點。
就這樣,因為拖延症犯了想偷懶,結果是對dictionary的使用時機和使用方式,有了新的體會。原來,dictionary這樣用,也是可以的啦!
在寫《The Nature of Code閱讀心得筆記——使用Python實作》的[第四章]4.3節時,原書提到,在使用Java的ArrayList時,如果用迴圈一面走訪一面又移除其中的元素,那會有難以察覺的問題存在。寫個小程式測試的結果發現,Python的list也會有一樣的問題。
用matplotlib畫正弦函數sin的圖形會有多難呢?應該是挺簡單的。不過,要畫得漂亮讓人滿意,還是非得費一番功夫調整不可。
MOUSEBUTTONDOWN的個性和mouse.get_pressed()是完全相反的。mouse.get_pressed()只活在當下,完全不管過去發生過什麼事;MOUSEBUTTONDOWN則會記得所有還沒處理完的事,只要事件佇列還沒被塞滿的話。
身為頂級藝術細胞缺乏者,總是非常羨慕那些能隨手畫出漂亮圖畫的人。看著自己寫的程式在螢幕上展現出事先無法預期的漂亮圖案,還真是很有成就感,也不免有些興奮地想著:「嘿!看來頂級藝術細胞缺乏者有藥醫了!」 這個圖
忽然覺得,似乎、彷彿、好像、應該有個for... else語法,可以讓程式漂亮一點。
就這樣,因為拖延症犯了想偷懶,結果是對dictionary的使用時機和使用方式,有了新的體會。原來,dictionary這樣用,也是可以的啦!
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這篇內容,將會講解什麼是變數,以及與變數相關的知識。包括變數、資料型態、變數賦值、變數的命名規則、變數的作用區域、變數的可重複性、內建變數。
Thumbnail
這篇文章主要介紹了繪圖軟體中的色彩模式,包括RGB和CMYK的概念和用法。對於網路上使用和印刷的影像處理有很好的指導意義。
Thumbnail
本文介紹了各種運算符的用法和優先級,包括算術運算符、比較運算符、賦值運算符、邏輯運算符、位元運算符、成員運算符和身份運算符。每種運算符都有詳細的描述和示例程式碼,幫助理解其功能和用法。
Thumbnail
Python語法包括條件語句、迴圈、函數和變數的使用。條件語句如if、elif和else用於進行條件判斷,for和while是兩種主要的迴圈,def用於定義函數。變數可以被賦予數字或字符串,並可使用類型提示來指定變數的類型。註解可以是單行或多行,並可用於解釋函數或類的用途和作用。
Thumbnail
Creative Coding 作品變化概念,有或沒有的差別,隨機性,色彩模式的調整...等
Thumbnail
這篇文章介紹如何使用Python整理資料成百分比資料以及繪製百分比堆疊直條圖。
在求學階段,你已經對代數的計算熟到不能再熟,所以變數(variable)對你來說應該不至於太陌生,先來看看以下這個例子:   
Thumbnail
涉及圖像處理和計算機視覺時,色彩空間轉換是一個常見操作,應用如下: 降維: 將一張彩色圖像轉換為灰度圖像可以減少數據的維度,簡化處理過程,同時在某些情況下保留重要的視覺信息。 突顯特徵: 在某些情況下,某些色彩通道可能包含冗餘或不必要的信息,通過轉換到其他色彩空間,可以更好地突顯圖像中的重要特徵
Thumbnail
用photoshop製圖時常會用到混和模式的效果, 但切成網頁圖片時,卻呈現不出來,例如光暈旁邊都會帶黑邊, 最近看到一個css3的混色模式可以達成這樣的效果...
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這篇內容,將會講解什麼是變數,以及與變數相關的知識。包括變數、資料型態、變數賦值、變數的命名規則、變數的作用區域、變數的可重複性、內建變數。
Thumbnail
這篇文章主要介紹了繪圖軟體中的色彩模式,包括RGB和CMYK的概念和用法。對於網路上使用和印刷的影像處理有很好的指導意義。
Thumbnail
本文介紹了各種運算符的用法和優先級,包括算術運算符、比較運算符、賦值運算符、邏輯運算符、位元運算符、成員運算符和身份運算符。每種運算符都有詳細的描述和示例程式碼,幫助理解其功能和用法。
Thumbnail
Python語法包括條件語句、迴圈、函數和變數的使用。條件語句如if、elif和else用於進行條件判斷,for和while是兩種主要的迴圈,def用於定義函數。變數可以被賦予數字或字符串,並可使用類型提示來指定變數的類型。註解可以是單行或多行,並可用於解釋函數或類的用途和作用。
Thumbnail
Creative Coding 作品變化概念,有或沒有的差別,隨機性,色彩模式的調整...等
Thumbnail
這篇文章介紹如何使用Python整理資料成百分比資料以及繪製百分比堆疊直條圖。
在求學階段,你已經對代數的計算熟到不能再熟,所以變數(variable)對你來說應該不至於太陌生,先來看看以下這個例子:   
Thumbnail
涉及圖像處理和計算機視覺時,色彩空間轉換是一個常見操作,應用如下: 降維: 將一張彩色圖像轉換為灰度圖像可以減少數據的維度,簡化處理過程,同時在某些情況下保留重要的視覺信息。 突顯特徵: 在某些情況下,某些色彩通道可能包含冗餘或不必要的信息,通過轉換到其他色彩空間,可以更好地突顯圖像中的重要特徵
Thumbnail
用photoshop製圖時常會用到混和模式的效果, 但切成網頁圖片時,卻呈現不出來,例如光暈旁邊都會帶黑邊, 最近看到一個css3的混色模式可以達成這樣的效果...