徹底搞清楚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會員
129內容數
寫點東西自娛娛人
留言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
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
私密乾癢臭是因這菌!SGS證實:豐傑私密清潔24小時有感 隨著夏天的來臨,女性出現私密搔癢、異味等問題更加頻繁。《豐傑生醫》保養品研發師指出,「加德納菌」是引起細菌性陰道感染的主因之一,當感染發作時,除了散發異味外,也會有發癢的症狀。因此,豐傑生醫領先業界,研發出可抑制「加德納菌高達99.9%」,
Thumbnail
   ※沖犯煞:很多問事的有緣人有沖、犯、煞這一類的問題,常見到的有「喪事、動土、邪符、路上的遊魂、意外驚嚇、業主菩薩與外靈一起干擾……等」。這一類的問題可大可小,常見的為眼神怪異,好像換了個人似的;身體病痛、思緒繁亂、失眠,嚴重一點還見過送醫急救、高溫發燒.........
必須要用最極端的方式忘記你 用恨來掩蓋來埋葬我對你的愛 這是最快速最有效的方式之一 唯有如此才能在對短的時間內 讓你在我心裡的情意徹底忘記
Thumbnail
伊根町位於京都府北部,丹後半島北端,東到北面臨日本海,自古以來就以漁業和農業而繁榮,近年則以漁業及旅遊業為主,傳說是浦島太郎故事的發生地,也是中國秦代方士徐福來到日本的登陸地,是一座擁有得天獨厚的自然風景、充滿船屋和傳說的小鎮。 2005年獲選為重要傳統建築群保存地區 2008年 加入「日本最美
Thumbnail
在這世上,有些事情與我徹底無緣,例如特定形式的性愛。 或許不該把話表達得如此死絕,但就現在、啪咋啪咋打著字的當下,身體或是心靈都毫無辦法開闊的接受這種畫面:光裸、會啪咋啪咋打著字、無論何時都試圖以試探的眼神獵取或被女人獵取的我,在可能有很多前因後果、也可能毫無因素的機緣情況,和光裸的男人啪
以前我總以為自己做不到完全放下前任男友,可如今我卻能完全做到! 這個過程我透過1.常做真心喜愛的事(唱歌和學習成長),接觸並且學習唱歌App,把原本和他語聊的時段替換成唱歌和歌友們交流,認識愛歡唱的好朋友們後,我的生活變得充實開心,又明顯感覺到自己正在一點一滴進步中,我很喜歡自己處於
Thumbnail
什麼是「共情」? 但凡是聽到看到想到別人受到委屈苦難, 或者開心驚喜,你的感同身受就是產生共情。 共情是一種天賦,更是一種偏見......
Thumbnail
影片連結: https://youtu.be/7wgoKiJBjfo 哈囉,各位觀眾大家好,歡迎回到方小小的股格驚奇。今天來跟大家談困擾許多股民一輩子,總是害自己小賺大賠的「心魔」 其實科學嚴謹的講,所謂心魔,只是心態出問題而已。 我經常強調,要成為市場贏家。正確的心態才是重重重點,任何知識/
Thumbnail
2021/12/03 【今日交易】 今天算是考驗停損是否確實的日子 停損了一整天,完全沒抓到行情 但交易就是這樣嘛 今天不太順,停損有沒有做好 輸的金額是不是正常的 如果答案都是肯定的 那何嘗不是好的一天呢! 今天雖然輸了但還活著,下次一定可以討回來。 當沖含退:-3000
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
私密乾癢臭是因這菌!SGS證實:豐傑私密清潔24小時有感 隨著夏天的來臨,女性出現私密搔癢、異味等問題更加頻繁。《豐傑生醫》保養品研發師指出,「加德納菌」是引起細菌性陰道感染的主因之一,當感染發作時,除了散發異味外,也會有發癢的症狀。因此,豐傑生醫領先業界,研發出可抑制「加德納菌高達99.9%」,
Thumbnail
   ※沖犯煞:很多問事的有緣人有沖、犯、煞這一類的問題,常見到的有「喪事、動土、邪符、路上的遊魂、意外驚嚇、業主菩薩與外靈一起干擾……等」。這一類的問題可大可小,常見的為眼神怪異,好像換了個人似的;身體病痛、思緒繁亂、失眠,嚴重一點還見過送醫急救、高溫發燒.........
必須要用最極端的方式忘記你 用恨來掩蓋來埋葬我對你的愛 這是最快速最有效的方式之一 唯有如此才能在對短的時間內 讓你在我心裡的情意徹底忘記
Thumbnail
伊根町位於京都府北部,丹後半島北端,東到北面臨日本海,自古以來就以漁業和農業而繁榮,近年則以漁業及旅遊業為主,傳說是浦島太郎故事的發生地,也是中國秦代方士徐福來到日本的登陸地,是一座擁有得天獨厚的自然風景、充滿船屋和傳說的小鎮。 2005年獲選為重要傳統建築群保存地區 2008年 加入「日本最美
Thumbnail
在這世上,有些事情與我徹底無緣,例如特定形式的性愛。 或許不該把話表達得如此死絕,但就現在、啪咋啪咋打著字的當下,身體或是心靈都毫無辦法開闊的接受這種畫面:光裸、會啪咋啪咋打著字、無論何時都試圖以試探的眼神獵取或被女人獵取的我,在可能有很多前因後果、也可能毫無因素的機緣情況,和光裸的男人啪
以前我總以為自己做不到完全放下前任男友,可如今我卻能完全做到! 這個過程我透過1.常做真心喜愛的事(唱歌和學習成長),接觸並且學習唱歌App,把原本和他語聊的時段替換成唱歌和歌友們交流,認識愛歡唱的好朋友們後,我的生活變得充實開心,又明顯感覺到自己正在一點一滴進步中,我很喜歡自己處於
Thumbnail
什麼是「共情」? 但凡是聽到看到想到別人受到委屈苦難, 或者開心驚喜,你的感同身受就是產生共情。 共情是一種天賦,更是一種偏見......
Thumbnail
影片連結: https://youtu.be/7wgoKiJBjfo 哈囉,各位觀眾大家好,歡迎回到方小小的股格驚奇。今天來跟大家談困擾許多股民一輩子,總是害自己小賺大賠的「心魔」 其實科學嚴謹的講,所謂心魔,只是心態出問題而已。 我經常強調,要成為市場贏家。正確的心態才是重重重點,任何知識/
Thumbnail
2021/12/03 【今日交易】 今天算是考驗停損是否確實的日子 停損了一整天,完全沒抓到行情 但交易就是這樣嘛 今天不太順,停損有沒有做好 輸的金額是不是正常的 如果答案都是肯定的 那何嘗不是好的一天呢! 今天雖然輸了但還活著,下次一定可以討回來。 當沖含退:-3000