鏈接的圖像是不是一個真正的阿爾法掩模但磨砂圖像。不同之處在於,無光澤圖像代表將作爲alpha通道,但將其顯示爲RGB(或灰度)組件。它實際上並沒有alpha通道。無光澤圖像在視頻合成軟件中很常見,但在網絡上不太實用。
畫布或其使用的Porter-Duff方法不直接支持亞光圖像,因此必須先將其轉換爲實際的Alpha通道。要做到這一點,你必須迭代每個像素,並將其中一個分量值(從紅色,綠色或藍色 - 無所謂)放入alpha通道。
完成後,您可以使用現在具有合適alpha通道的畫布對象以及僅使用alpha信息的混合操作(混合模式是不同的章節)。
更好的方法當然是提供圖像作爲PNG與適當的alpha通道。但在任何情況下,以顯示它有可能也採用磨砂圖像工作,但效率不高,我們可以做到以下幾點:
轉換無光澤的圖案爲Alpha通道
第一步:此代碼段展示瞭如何可以高效地完成將無光澤圖像轉換爲Alpha通道的預備步驟。正如已經提到的那樣,最終的顏色對於主合成步驟來說並不重要,因爲它僅使用alpha通道。
只需確保圖像在嘗試使用圖像之前已正確加載,方法是使用圖像的onload
回調或在加載所有內容後運行腳本。
此代碼將使用像素的全部32位值(爲了提高效率)簡單地將組件(在本例中爲藍色)轉換爲alpha通道,使圖像看起來像是青色的,但使用正確的alpha,如您所見通過橙色背景顯示(儘管大部分代碼是處理加載和設置的)。
window.onload = function() {
// at this stage the image has loaded:
var img = document.getElementById("img");
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
// - setup canvas to match image
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
// - draw image
ctx.drawImage(img, 0, 0);
// CONV. STEP: move a component channel to alpha-channel
var idata = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data32 = new Uint32Array(idata.data.buffer);
var i = 0, len = data32.length;
while(i < len) {
data32[i] = data32[i++] << 8; // shift blue channel into alpha (little-endian)
}
// update canvas
ctx.putImageData(idata, 0, 0);
};
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ►
<canvas id="c"></canvas>
復化
然後,第二部分成爲如何使用新的alpha通道合成。
在這種情況下,無光澤圖像的黑色變得完全透明,而白色變得完全不透明。您可以在轉換步驟中將其逆轉,但只要您瞭解無光澤圖像的外觀,就不會真正消光。
要替換我們使用合成模式source-in
的內部內容。這會根據alpha值取代內容,同時保持alpha通道的狀態。
首先使用相同的模式處理內部部分,使我們可以在繪製框架之前對內容做額外的事情(認爲暈影,陰影等)。
作爲最後一步,我們通過使用複合模式destination-over
來填充透明區域和框架本身,該模式替換了更多透明區域,其中內容被繪製到畫布上(概念上它在現有內容後面繪製)。
下面的代碼使用簡單的彩色框 - 只需用你想繪製的任何東西替換它們即可。
window.onload = function() {
var img = document.getElementById("img");
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0);
var idata = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data32 = new Uint32Array(idata.data.buffer);
var i = 0, len = data32.length;
while(i < len) data32[i] = data32[i++] << 8;
ctx.putImageData(idata, 0, 0);
// COMP. STEPS: use the mask with composite operation. Since our frame
// is black (= transparent as alpha) we can use the following mode:
ctx.globalCompositeOperation = "source-in";
// draw something, here a blue box, replace with whatever you want
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// to fill the frame area, still transparent, use this mode:
ctx.globalCompositeOperation = "destination-over";
ctx.fillStyle = "yellow";
ctx.fillRect(0, 0, canvas.width, canvas.height);
};
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ►
<canvas id="c"></canvas>
來源
2016-11-16 21:40:14
K3N
改變您的圖像,使得白色部分是透明的,然後使用['globalCompositeOperation'](https://developer.mozilla.org/en-US/docs/Web/API/ CanvasRenderingContext2D/globalCompositeOperation)來執行合成。 – Kaiido