2022年4月1日 星期五

HTML5 : Canvas 圖片合成的模式

2022年4月1日 星期五

之前設計「柵欄動畫」是利用 Inkscape 或是 ImageMagick 的 convert 來合成圖片,其實利用 HTML5 的 Canvas 2D API 也是可以,而且可以在大家比較熟悉的瀏覽器上操作,應該會更有親和力。

畫柵欄只要使用 Canvas 2D API 的「fillRect」。每一個影格的圖片的製作,在則是柵欄和影格原始圖片做「運算」後產出。

在 ImageMagick 中,我是使用「-compose DstIn」的參數,以圖片為底,再搭柵欄。

在 HTML5 Canvas 2D API 中,則參考底下的說明文件:

我想的合成程序是:先畫好遮罩用的柵欄,要顯示的部份用黑垂直線,一條條畫好;載入影格的原始圖片後,再將它利用 Canvas 2D API 的「drawImage」合成。

HTML5 Canvas 2D API 範例裡面,將 globalCompositeOperation 設為「source-in」能達到我的需求,所以在執行「drawImage」前要先設定:

globalCompositeOperation = 'source-in'

這樣子,原始圖片中,只會保留和遮罩黑色部份相同位置的內容。

[圖1] 以 fillRect 畫的柵欄(線寬4px)

[圖2] 第一張原始相片

[圖3] 以「source-in」將[圖1]和 [圖2]合成

[圖3] 是處理好的第一影格,和 [圖2] 的原圖比較,只剩下和 [圖1] 柵欄中一樣的部份,每一個細長條都只有 4px 的寬度。

合成好的影格圖片,再儲存備用,或是直接畫到輸出用的 Canvas 中。

那下一個影格和前一個影格合成前,globalCompositeOperation 要用什麼呢?

反正該去除的部份都會變成「透明」的,應該是直接用最原始的預設值,也就是「source-over」:

globalCompositeOperation = 'source-over'

下面將第一影格 [圖3] 和第二影格 [圖4],以「source-over」合成前和合成後 [圖5],放在一起作比較:

[圖3] 第一影格

[圖4] 第二影格

[圖5] 兩個影格合成的結果

照前面的方法,繼續將四張照片都合在一起後的最後成果:

[圖6] 四張相片以柵欄縫隙 4px 合成的圖片

哈!看到 [圖6] 的成品,一定覺得怎麼畫質那麼差!

其實這是有原因的,為了能看出柵欄將相片遮成一條條的功用,我特別將柵欄的縫隙設為 4px,其實正式製作相片的柵欄動畫時,我是將柵欄的縫隙設為 1px 的,看一下正常版:

[圖7] 四張相片以柵欄縫隙 1px 合成的圖片

[圖7] 是不是好很多!不過啊~怎麼還是看起來怪怪的?

沒錯!看起來怪其實是正常的,因為它是將四張相片合在一張,必須要用相同縫隙的柵欄來看,才會看到正常的影像。

[圖8] 以柵欄看合成圖

[圖9] 柵欄下的合成圖

[圖9] 是使用柵欄放在 [圖7] 上後,所呈現的效果;只要移動柵欄,就可以看到另外三張照片。

順便記錄一下,有關 Canvas 2D API  的「putImageData」的測試經驗。

原本以為每完成一個影格的合成後,用 Canvas 2D API  的「getImageData」將結果先存用,再直接用「putImageData」「貼到」前一影格上就可以。測試的結果是,使用「putImageData」時,它並不會管 globalCompositeOperation 設成什麼,都是直接將 Canvas 中的原有內容「覆蓋」。所以依我要將多張影格的圖片合成的需求,不能使用「putImageData」,還是得用「drawImage」,不然合成完,只會剩下最後加上去的圖片。

相關文章




沒有留言:

張貼留言

 
雄::gsyan © 2009. Design by Pocket